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