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 public <T> Collection<T> getBeansOfType(Class<T> interfaceClass) {
124 try
125 {
126 Map<String, T> beans = (Map<String, T>) nativeGetBeansOfTypeMethod.invoke(nativeBeanFactory, interfaceClass);
127 return beans.values();
128 }
129 catch (final IllegalAccessException e)
130 {
131
132 throw new PluginException("Unable to access getBeansOfType method", e);
133 }
134 catch (final InvocationTargetException e)
135 {
136 handleSpringMethodInvocationError(e);
137 return null;
138 }
139 }
140
141 public void autowireBean(final Object instance, AutowireCapablePlugin.AutowireStrategy autowireStrategy)
142 {
143 try
144 {
145 nativeAutowireBeanMethod.invoke(nativeBeanFactory, instance, autowireStrategy.ordinal(), false);
146 }
147 catch (final IllegalAccessException e)
148 {
149
150 throw new PluginException("Unable to access createBean method", e);
151 }
152 catch (final InvocationTargetException e)
153 {
154 handleSpringMethodInvocationError(e);
155 }
156 }
157
158 public Object getBean(String id)
159 {
160 try
161 {
162 return nativeGetBeanMethod.invoke(nativeBeanFactory, id);
163 }
164 catch (final IllegalAccessException e)
165 {
166
167 throw new PluginException("Unable to access getBean method", e);
168 }
169 catch (final InvocationTargetException e)
170 {
171 handleSpringMethodInvocationError(e);
172 return null;
173 }
174 }
175 }