1 package com.atlassian.plugin.osgi.spring;
2
3 import com.atlassian.plugin.PluginException;
4 import com.atlassian.plugin.AutowireCapablePlugin;
5
6 import java.lang.reflect.InvocationTargetException;
7 import java.lang.reflect.Method;
8 import java.util.Collection;
9 import java.util.Map;
10
11 import org.apache.commons.lang.Validate;
12
13
14
15
16
17
18 public class DefaultSpringContainerAccessor implements SpringContainerAccessor
19 {
20 private final Object nativeBeanFactory;
21 private final Method nativeCreateBeanMethod;
22 private final Method nativeAutowireBeanMethod;
23 private final Method nativeGetBeanMethod;
24 private final Method nativeGetBeansOfTypeMethod;
25
26
27
28
29 private enum AutowireStrategy
30 {
31 AUTOWIRE_NO,
32
33 AUTOWIRE_BY_NAME,
34
35
36 AUTOWIRE_BY_TYPE,
37
38
39 AUTOWIRE_BY_CONSTRUCTOR,
40
41
42
43
44
45 AUTOWIRE_AUTODETECT
46 }
47
48 public DefaultSpringContainerAccessor(final Object applicationContext)
49 {
50 Object beanFactory = null;
51 try
52 {
53 final Method m = applicationContext.getClass().getMethod("getAutowireCapableBeanFactory");
54 beanFactory = m.invoke(applicationContext);
55 }
56 catch (final NoSuchMethodException e)
57 {
58
59 throw new PluginException("Cannot find createBean method on registered bean factory: " + beanFactory, e);
60 }
61 catch (final IllegalAccessException e)
62 {
63
64 throw new PluginException("Cannot access createBean method", e);
65 }
66 catch (final InvocationTargetException e)
67 {
68 handleSpringMethodInvocationError(e);
69 }
70
71 nativeBeanFactory = beanFactory;
72 try
73 {
74 nativeCreateBeanMethod = beanFactory.getClass().getMethod("createBean", Class.class, int.class, boolean.class);
75 nativeAutowireBeanMethod = beanFactory.getClass().getMethod("autowireBeanProperties", Object.class, int.class, boolean.class);
76 nativeGetBeanMethod = beanFactory.getClass().getMethod("getBean", String.class);
77 nativeGetBeansOfTypeMethod = beanFactory.getClass().getMethod("getBeansOfType", Class.class);
78
79 Validate.noNullElements(new Object[] {nativeGetBeansOfTypeMethod, nativeAutowireBeanMethod, nativeCreateBeanMethod, nativeGetBeanMethod});
80 }
81 catch (final NoSuchMethodException e)
82 {
83
84 throw new PluginException("Cannot find one or more methods on registered bean factory: " + nativeBeanFactory, e);
85 }
86 }
87
88 private void handleSpringMethodInvocationError(final InvocationTargetException e)
89 {
90 if (e.getCause() instanceof Error)
91 {
92 throw (Error) e.getCause();
93 }
94 else if (e.getCause() instanceof RuntimeException)
95 {
96 throw (RuntimeException) e.getCause();
97 }
98 else
99 {
100
101 throw new PluginException("Unable to invoke createBean", e.getCause());
102 }
103 }
104
105 public <T> T createBean(final Class<T> clazz)
106 {
107 try
108 {
109 return clazz.cast(nativeCreateBeanMethod.invoke(nativeBeanFactory, clazz, AutowireStrategy.AUTOWIRE_AUTODETECT.ordinal(), false));
110 }
111 catch (final IllegalAccessException e)
112 {
113
114 throw new PluginException("Unable to access createBean method", e);
115 }
116 catch (final InvocationTargetException e)
117 {
118 handleSpringMethodInvocationError(e);
119 return null;
120 }
121 }
122
123 @Override
124 public <T> T injectBean(T bean)
125 {
126 autowireBean(bean, AutowireCapablePlugin.AutowireStrategy.AUTOWIRE_AUTODETECT);
127 return bean;
128 }
129
130 public <T> Collection<T> getBeansOfType(Class<T> interfaceClass) {
131 try
132 {
133 Map<String, T> beans = (Map<String, T>) nativeGetBeansOfTypeMethod.invoke(nativeBeanFactory, interfaceClass);
134 return beans.values();
135 }
136 catch (final IllegalAccessException e)
137 {
138
139 throw new PluginException("Unable to access getBeansOfType method", e);
140 }
141 catch (final InvocationTargetException e)
142 {
143 handleSpringMethodInvocationError(e);
144 return null;
145 }
146 }
147
148 public void autowireBean(final Object instance, AutowireCapablePlugin.AutowireStrategy autowireStrategy)
149 {
150 try
151 {
152 nativeAutowireBeanMethod.invoke(nativeBeanFactory, instance, autowireStrategy.ordinal(), false);
153 }
154 catch (final IllegalAccessException e)
155 {
156
157 throw new PluginException("Unable to access createBean method", e);
158 }
159 catch (final InvocationTargetException e)
160 {
161 handleSpringMethodInvocationError(e);
162 }
163 }
164
165 public Object getBean(String id)
166 {
167 try
168 {
169 return nativeGetBeanMethod.invoke(nativeBeanFactory, id);
170 }
171 catch (final IllegalAccessException e)
172 {
173
174 throw new PluginException("Unable to access getBean method", e);
175 }
176 catch (final InvocationTargetException e)
177 {
178 handleSpringMethodInvocationError(e);
179 return null;
180 }
181 }
182 }