001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.spring.annotation;
016    
017    import com.liferay.portal.kernel.annotation.BeanReference;
018    import com.liferay.portal.kernel.bean.BeanLocatorException;
019    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
020    
021    import java.io.PrintWriter;
022    import java.io.StringWriter;
023    
024    import java.lang.reflect.Field;
025    
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    import org.springframework.beans.BeansException;
030    import org.springframework.beans.factory.BeanCreationException;
031    import org.springframework.beans.factory.BeanFactory;
032    import org.springframework.beans.factory.BeanFactoryAware;
033    import org.springframework.beans.factory.NoSuchBeanDefinitionException;
034    import org.springframework.beans.factory.config.BeanPostProcessor;
035    import org.springframework.util.ReflectionUtils;
036    
037    /**
038     * @author Michael Young
039     * @author Shuyang Zhou
040     */
041    public class BeanReferenceAnnotationBeanPostProcessor
042            implements BeanFactoryAware, BeanPostProcessor {
043    
044            public void destroy() {
045                    _beans.clear();
046            }
047    
048            public Object postProcessAfterInitialization(Object bean, String beanName)
049                    throws BeansException {
050    
051                    return bean;
052            }
053    
054            public Object postProcessBeforeInitialization(Object bean, String beanName)
055                    throws BeansException {
056    
057                    _autoInject(bean, beanName, bean.getClass());
058    
059                    return bean;
060            }
061    
062            public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
063                    _beanFactory = beanFactory;
064            }
065    
066            private void _autoInject(
067                    Object targetBean, String targetBeanName, Class<?> beanClass) {
068    
069                    if ((beanClass == null) || beanClass.isInterface()) {
070                            return;
071                    }
072    
073                    String className = beanClass.getName();
074    
075                    if (className.equals(_JAVA_LANG_OBJECT) ||
076                            className.startsWith(_ORG_SPRINGFRAMEWORK)) {
077    
078                            return;
079                    }
080    
081                    Field[] fields = beanClass.getDeclaredFields();
082    
083                    for (Field field : fields) {
084                            BeanReference beanReference = field.getAnnotation(
085                                    BeanReference.class);
086    
087                            String referencedBeanName = null;
088                            Class<?> referencedBeanType = null;
089    
090                            if (beanReference != null) {
091                                    referencedBeanName = beanReference.name();
092                                    referencedBeanType = beanReference.type();
093                            }
094                            else {
095                                    continue;
096                            }
097    
098                            if (!Object.class.equals(referencedBeanType)) {
099                                    referencedBeanName = referencedBeanType.getName();
100                            }
101    
102                            Object referencedBean = _beans.get(referencedBeanName);
103    
104                            if (referencedBean == null) {
105                                    try {
106                                            referencedBean = _beanFactory.getBean(referencedBeanName);
107                                    }
108                                    catch (NoSuchBeanDefinitionException nsbde) {
109                                            try {
110                                                    referencedBean = PortalBeanLocatorUtil.locate(
111                                                            referencedBeanName);
112                                            }
113                                            catch (BeanLocatorException ble) {
114                                                    StringWriter stringWriter = new StringWriter();
115    
116                                                    PrintWriter printWriter = new PrintWriter(stringWriter);
117    
118                                                    printWriter.print("BeanFactory could not find bean: ");
119    
120                                                    nsbde.printStackTrace(printWriter);
121    
122                                                    printWriter.print(
123                                                            " and PortalBeanLocator failed with: ");
124                                                    printWriter.append(ble.getMessage());
125    
126                                                    printWriter.close();
127    
128                                                    throw new BeanLocatorException(
129                                                            stringWriter.toString(), ble);
130                                            }
131                                    }
132    
133                                    _beans.put(referencedBeanName, referencedBean);
134                            }
135    
136                            ReflectionUtils.makeAccessible(field);
137    
138                            try {
139                                    field.set(targetBean, referencedBean);
140                            }
141                            catch (Throwable t) {
142                                    throw new BeanCreationException(
143                                            targetBeanName, "Could not inject BeanReference fields",
144                                            t);
145                            }
146                    }
147    
148                    _autoInject(targetBean, targetBeanName, beanClass.getSuperclass());
149            }
150    
151            private static final String _JAVA_LANG_OBJECT = "java.lang.Object";
152    
153            private static final String _ORG_SPRINGFRAMEWORK = "org.springframework";
154    
155            private BeanFactory _beanFactory;
156            private Map<String, Object> _beans = new HashMap<String, Object>();
157    
158    }