KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > spring > support > SpringInjectionSupport


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22
23 package org.jboss.spring.support;
24
25 import java.lang.reflect.Field JavaDoc;
26 import java.lang.reflect.Member JavaDoc;
27 import java.lang.reflect.Method JavaDoc;
28 import java.util.*;
29
30 import org.jboss.annotation.spring.Spring;
31 import org.jboss.logging.Logger;
32 import org.jboss.util.naming.Util;
33 import org.springframework.beans.factory.BeanFactory;
34 import org.springframework.beans.factory.ListableBeanFactory;
35
36 /**
37  * Injects objects from bean factory located in JNDI at jndiName gained
38  * from @Spring annotation's field jndiName.
39  * It is applied to setter methods and fields annotated with @Spring annotation.
40  *
41  * @author <a HREF="mailto:ales.justin@genera-lynx.com">Ales Justin</a>
42  * @see MethodComparator Excludes overridden @Spring annotated methods
43  * Class type check is performed before actual setting.
44  */

45 public abstract class SpringInjectionSupport
46 {
47
48    protected Logger log = Logger.getLogger(getClass());
49    private final Comparator<Method JavaDoc> METHOD_COMPARATOR = new MethodComparator();
50
51    protected Object JavaDoc inject(Object JavaDoc target) throws Exception JavaDoc
52    {
53
54       log.debug("Invoking Spring injection: " + target.getClass().getName());
55
56       Method JavaDoc[] methods = getAllMethods(target);
57       for (Method JavaDoc m : methods)
58       {
59          Spring spring = m.getAnnotation(Spring.class);
60          if (spring != null)
61          {
62             if (isSetterMethod(m))
63             {
64                injectToMethod(target, m, spring);
65             }
66             else
67             {
68                log.warn("Spring annotation only allowed on setter methods.");
69             }
70          }
71       }
72
73       Field JavaDoc[] fields = getAllFields(target);
74       for (Field JavaDoc f : fields)
75       {
76          Spring spring = f.getAnnotation(Spring.class);
77          if (spring != null)
78          {
79             injectToField(target, f, spring);
80          }
81       }
82
83       return target;
84    }
85
86    protected Method JavaDoc[] getAllMethods(Object JavaDoc bean)
87    {
88       Class JavaDoc beanClass = bean.getClass();
89       Set<Method JavaDoc> methods = new TreeSet<Method JavaDoc>(METHOD_COMPARATOR);
90       while (beanClass != Object JavaDoc.class)
91       {
92          methods.addAll(Arrays.asList(beanClass.getDeclaredMethods()));
93          beanClass = beanClass.getSuperclass();
94       }
95       return methods.toArray(new Method JavaDoc[methods.size()]);
96    }
97
98    protected Field JavaDoc[] getAllFields(Object JavaDoc bean)
99    {
100       Class JavaDoc beanClass = bean.getClass();
101       List<Field JavaDoc> fields = new ArrayList<Field JavaDoc>();
102       while (beanClass != Object JavaDoc.class)
103       {
104          fields.addAll(Arrays.asList(beanClass.getDeclaredFields()));
105          beanClass = beanClass.getSuperclass();
106       }
107       return fields.toArray(new Field JavaDoc[fields.size()]);
108    }
109
110    private boolean isSetterMethod(Method JavaDoc m)
111    {
112       return m.getName().startsWith("set") && m.getParameterTypes().length == 1;
113    }
114
115    private Object JavaDoc getObjectFromBeanFactory(Spring spring, String JavaDoc defaultBeanName, Class JavaDoc beanType) throws Exception JavaDoc
116    {
117       BeanFactory beanFactory = (BeanFactory) Util.lookup(spring.jndiName(), BeanFactory.class);
118       String JavaDoc beanName = spring.bean();
119       if (beanName != null && beanName.length() > 0)
120       {
121          return beanFactory.getBean(beanName, beanType);
122       }
123       else
124       {
125          // by type injection
126
if (beanFactory instanceof ListableBeanFactory)
127          {
128             ListableBeanFactory lbf = (ListableBeanFactory) beanFactory;
129             Map beans = lbf.getBeansOfType(beanType);
130             if (beans.size() > 1)
131             {
132                Object JavaDoc bean = beans.get(defaultBeanName);
133                if (bean == null)
134                {
135                   throw new IllegalArgumentException JavaDoc("More than one bean of type: " + beanType);
136                }
137                return bean;
138             }
139             else if (beans.size() == 1)
140             {
141                return beans.values().iterator().next();
142             }
143             else
144             {
145                throw new IllegalArgumentException JavaDoc("No such bean by type: " + beanType);
146             }
147          }
148          else
149          {
150             // bean factory is not listable - use default bean name
151
return beanFactory.getBean(defaultBeanName, beanType);
152          }
153       }
154    }
155
156    private void injectToMethod(Object JavaDoc target, Method JavaDoc method, Spring spring) throws Exception JavaDoc
157    {
158       String JavaDoc defaultBeanName = getDefaultBeanName(method);
159       Object JavaDoc bean = getObjectFromBeanFactory(spring, defaultBeanName, method.getParameterTypes()[0]);
160       logInjection(spring, bean, target, method);
161       method.setAccessible(true);
162       method.invoke(target, bean);
163    }
164
165    protected String JavaDoc getDefaultBeanName(Method JavaDoc method)
166    {
167       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
168       buffer.append(method.getName().substring(3, 3).toLowerCase());
169       buffer.append(method.getName().substring(4));
170       return buffer.toString();
171    }
172
173    private void injectToField(Object JavaDoc target, Field JavaDoc field, Spring spring) throws Exception JavaDoc
174    {
175       String JavaDoc defaultBeanName = getDefaultBeanName(field);
176       Object JavaDoc bean = getObjectFromBeanFactory(spring, defaultBeanName, field.getType());
177       logInjection(spring, bean, target, field);
178       field.setAccessible(true);
179       field.set(target, bean);
180    }
181
182    protected String JavaDoc getDefaultBeanName(Field JavaDoc field)
183    {
184       return field.getName();
185    }
186
187    private void logInjection(Spring spring, Object JavaDoc bean, Object JavaDoc target, Member JavaDoc m)
188    {
189       log.debug("Injecting bean '" + spring.bean() + "' of class type " +
190             bean.getClass().getName() + " into " + target + " via " + m);
191    }
192
193    /**
194     * Equals on overridden methods.
195     * Any other solution?
196     */

197    private class MethodComparator implements Comparator<Method JavaDoc>
198    {
199
200       public int compare(Method JavaDoc m1, Method JavaDoc m2)
201       {
202          String JavaDoc name1 = m1.getName();
203          String JavaDoc name2 = m2.getName();
204
205          if (name1.equals(name2))
206          {
207             Class JavaDoc returnType1 = m1.getReturnType();
208             Class JavaDoc returnType2 = m2.getReturnType();
209             Class JavaDoc[] params1 = m1.getParameterTypes();
210             Class JavaDoc[] params2 = m1.getParameterTypes();
211             if (params1.length == params2.length)
212             {
213                if (returnType1.equals(returnType2))
214                {
215                   int i;
216                   int length = params1.length;
217                   for (i = 0; i < length; i++)
218                   {
219                      if (!params1[i].equals(params2[i]))
220                      {
221                         break;
222                      }
223                   }
224                   //not equal
225
if (i < length)
226                   {
227                      return params1[i].getName().compareTo(params2[i].getName());
228                   }
229                   else
230                   {
231                      //overridden method
232
if (m1.getAnnotation(Spring.class) != null)
233                      {
234                         log.warn("Found overridden @Spring annotated method: " + m1);
235                      }
236                      return 0;
237                   }
238                }
239                else
240                {
241                   return returnType1.getName().compareTo(returnType2.getName());
242                }
243             }
244             else
245             {
246                return params1.length - params2.length;
247             }
248          }
249          else
250          {
251             return name1.compareTo(name2);
252          }
253       }
254
255    }
256 }
257
Popular Tags