1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.spring.annotation;
21  
22  import java.beans.PropertyDescriptor;
23  
24  import java.util.Map;
25  import java.util.concurrent.ConcurrentHashMap;
26  
27  import org.springframework.beans.BeansException;
28  import org.springframework.beans.PropertyValues;
29  import org.springframework.beans.factory.BeanCreationException;
30  import org.springframework.beans.factory.BeanFactory;
31  import org.springframework.beans.factory.BeanFactoryAware;
32  import org.springframework.beans.factory.annotation.InjectionMetadata;
33  import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
34  import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
35  import org.springframework.beans.factory.support.RootBeanDefinition;
36  import org.springframework.util.ReflectionUtils;
37  
38  /**
39   * <a href="BeanReferenceAnnotationBeanPostProcessor.java.html"><b><i>View
40   * Source</i></b></a>
41   *
42   * @author Michael Young
43   *
44   */
45  public class BeanReferenceAnnotationBeanPostProcessor
46      implements BeanFactoryAware, InstantiationAwareBeanPostProcessor,
47          MergedBeanDefinitionPostProcessor {
48  
49      public Object postProcessAfterInitialization(Object bean, String beanName)
50          throws BeansException {
51  
52          return bean;
53      }
54  
55      public boolean postProcessAfterInstantiation(Object bean, String beanName)
56          throws BeansException {
57  
58          InjectionMetadata injectionMetadata = findResourceMetadata(
59              bean.getClass());
60  
61          try {
62              injectionMetadata.injectFields(bean, beanName);
63          }
64          catch (Throwable t) {
65              throw new BeanCreationException(
66                  beanName, "Injection of BeanReference fields failed", t);
67          }
68  
69          return true;
70      }
71  
72      public Object postProcessBeforeInitialization(Object bean, String beanName)
73          throws BeansException {
74  
75          return bean;
76      }
77  
78      public Object postProcessBeforeInstantiation(
79              Class beanClass, String beanName)
80          throws BeansException {
81  
82          return null;
83      }
84  
85      public void postProcessMergedBeanDefinition(
86              RootBeanDefinition beanDefinition, Class beanType,
87              String beanName) {
88  
89          if (beanType == null) {
90              return;
91          }
92  
93          InjectionMetadata injectionMetadata = findResourceMetadata(beanType);
94  
95          injectionMetadata.checkConfigMembers(beanDefinition);
96      }
97  
98      public PropertyValues postProcessPropertyValues(
99              PropertyValues propertyValues,
100             PropertyDescriptor[] propertyDescriptors, Object bean,
101             String beanName)
102         throws BeansException {
103 
104         InjectionMetadata metadata = findResourceMetadata(bean.getClass());
105 
106         try {
107             metadata.injectMethods(bean, beanName, propertyValues);
108         }
109         catch (Throwable t) {
110             throw new BeanCreationException(
111                 beanName, "Injection of BeanReference methods failed", t);
112         }
113 
114         return propertyValues;
115     }
116 
117     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
118         _beanFactory = beanFactory;
119     }
120 
121     protected InjectionMetadata findResourceMetadata(Class clazz) {
122         InjectionMetadata injectionMetadata = _injectionMetadataMap.get(clazz);
123 
124         if (injectionMetadata != null) {
125             return injectionMetadata;
126         }
127 
128         synchronized (_injectionMetadataMap) {
129             injectionMetadata = _injectionMetadataMap.get(clazz);
130 
131             if (injectionMetadata == null) {
132                 injectionMetadata = new InjectionMetadata(clazz);
133 
134                 BeanReferenceCallback callback = new BeanReferenceCallback(
135                     _beanFactory, injectionMetadata, clazz);
136 
137                 ReflectionUtils.doWithFields(clazz, callback);
138                 ReflectionUtils.doWithMethods(clazz, callback);
139 
140                 _injectionMetadataMap.put(clazz, injectionMetadata);
141             }
142         }
143 
144         return injectionMetadata;
145     }
146 
147     private BeanFactory _beanFactory;
148 
149     private Map<Class<?>, InjectionMetadata> _injectionMetadataMap =
150         new ConcurrentHashMap<Class<?>, InjectionMetadata>();
151 
152 }