1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| package org.apache.hivemind.service.impl; |
16 |
| |
17 |
| import java.lang.reflect.Constructor; |
18 |
| import java.lang.reflect.InvocationTargetException; |
19 |
| import java.lang.reflect.Method; |
20 |
| import java.lang.reflect.Modifier; |
21 |
| import java.util.ArrayList; |
22 |
| import java.util.Collection; |
23 |
| import java.util.Collections; |
24 |
| import java.util.Comparator; |
25 |
| import java.util.HashSet; |
26 |
| import java.util.Iterator; |
27 |
| import java.util.List; |
28 |
| import java.util.Set; |
29 |
| |
30 |
| import org.apache.commons.logging.Log; |
31 |
| import org.apache.hivemind.ApplicationRuntimeException; |
32 |
| import org.apache.hivemind.ErrorHandler; |
33 |
| import org.apache.hivemind.HiveMind; |
34 |
| import org.apache.hivemind.Location; |
35 |
| import org.apache.hivemind.ServiceImplementationFactoryParameters; |
36 |
| import org.apache.hivemind.internal.Module; |
37 |
| import org.apache.hivemind.service.EventLinker; |
38 |
| import org.apache.hivemind.util.ConstructorUtils; |
39 |
| import org.apache.hivemind.util.PropertyUtils; |
40 |
| |
41 |
| |
42 |
| |
43 |
| |
44 |
| |
45 |
| |
46 |
| |
47 |
| public class BuilderFactoryLogic |
48 |
| { |
49 |
| |
50 |
| private ServiceImplementationFactoryParameters _factoryParameters; |
51 |
| |
52 |
| private String _serviceId; |
53 |
| |
54 |
| private BuilderParameter _parameter; |
55 |
| |
56 |
| private Log _log; |
57 |
| |
58 |
| private Module _contributingModule; |
59 |
| |
60 |
790
| public BuilderFactoryLogic(ServiceImplementationFactoryParameters factoryParameters,
|
61 |
| BuilderParameter parameter) |
62 |
| { |
63 |
790
| _factoryParameters = factoryParameters;
|
64 |
790
| _parameter = parameter;
|
65 |
| |
66 |
790
| _log = _factoryParameters.getLog();
|
67 |
790
| _serviceId = factoryParameters.getServiceId();
|
68 |
790
| _contributingModule = factoryParameters.getInvokingModule();
|
69 |
| } |
70 |
| |
71 |
790
| public Object createService()
|
72 |
| { |
73 |
790
| try
|
74 |
| { |
75 |
790
| Object result = instantiateCoreServiceInstance();
|
76 |
| |
77 |
789
| setProperties(result);
|
78 |
| |
79 |
789
| registerForEvents(result);
|
80 |
| |
81 |
789
| invokeInitializer(result);
|
82 |
| |
83 |
789
| return result;
|
84 |
| } |
85 |
| catch (Exception ex) |
86 |
| { |
87 |
1
| throw new ApplicationRuntimeException(ServiceMessages.failureBuildingService(
|
88 |
| _serviceId, |
89 |
| ex), _parameter.getLocation(), ex); |
90 |
| } |
91 |
| } |
92 |
| |
93 |
4
| private void error(String message, Location location, Throwable cause)
|
94 |
| { |
95 |
4
| _factoryParameters.getErrorLog().error(message, location, cause);
|
96 |
| } |
97 |
| |
98 |
790
| private Object instantiateCoreServiceInstance()
|
99 |
| { |
100 |
790
| Class serviceClass = _contributingModule.resolveType(_parameter.getClassName());
|
101 |
| |
102 |
790
| List parameters = _parameter.getParameters();
|
103 |
| |
104 |
790
| if (_parameter.getAutowireServices() && parameters.isEmpty())
|
105 |
| { |
106 |
740
| return instantiateConstructorAutowiredInstance(serviceClass);
|
107 |
| } |
108 |
| |
109 |
50
| return instantiateExplicitConstructorInstance(serviceClass, parameters);
|
110 |
| } |
111 |
| |
112 |
50
| private Object instantiateExplicitConstructorInstance(Class serviceClass, List builderParameters)
|
113 |
| { |
114 |
50
| int numberOfParams = builderParameters.size();
|
115 |
50
| List constructorCandidates = getServiceConstructorsOfLength(serviceClass, numberOfParams);
|
116 |
| |
117 |
62
| outer: for (Iterator candidates = constructorCandidates.iterator(); candidates.hasNext();)
|
118 |
| { |
119 |
62
| Constructor candidate = (Constructor) candidates.next();
|
120 |
| |
121 |
62
| Class[] parameterTypes = candidate.getParameterTypes();
|
122 |
| |
123 |
62
| Object[] parameters = new Object[parameterTypes.length];
|
124 |
| |
125 |
62
| for (int i = 0; i < numberOfParams; i++)
|
126 |
| { |
127 |
58
| BuilderFacet facet = (BuilderFacet) builderParameters.get(i);
|
128 |
| |
129 |
58
| if (!facet.isAssignableToType(_factoryParameters, parameterTypes[i]))
|
130 |
12
| continue outer;
|
131 |
| |
132 |
46
| parameters[i] = facet.getFacetValue(_factoryParameters, parameterTypes[i]);
|
133 |
| } |
134 |
| |
135 |
50
| return ConstructorUtils.invoke(candidate, parameters);
|
136 |
| } |
137 |
| |
138 |
0
| throw new ApplicationRuntimeException(ServiceMessages.unableToFindAutowireConstructor(),
|
139 |
| _parameter.getLocation(), null); |
140 |
| } |
141 |
| |
142 |
50
| private List getServiceConstructorsOfLength(Class serviceClass, int length)
|
143 |
| { |
144 |
50
| List fixedLengthConstructors = new ArrayList();
|
145 |
| |
146 |
50
| Constructor[] constructors = serviceClass.getDeclaredConstructors();
|
147 |
| |
148 |
50
| outer: for (int i = 0; i < constructors.length; i++)
|
149 |
| { |
150 |
159
| if (!Modifier.isPublic(constructors[i].getModifiers()))
|
151 |
0
| continue;
|
152 |
| |
153 |
159
| Class[] parameterTypes = constructors[i].getParameterTypes();
|
154 |
| |
155 |
159
| if (parameterTypes.length != length)
|
156 |
85
| continue;
|
157 |
| |
158 |
74
| fixedLengthConstructors.add(constructors[i]);
|
159 |
| } |
160 |
| |
161 |
50
| return fixedLengthConstructors;
|
162 |
| } |
163 |
| |
164 |
740
| private Object instantiateConstructorAutowiredInstance(Class serviceClass)
|
165 |
| { |
166 |
740
| List serviceConstructorCandidates = getOrderedServiceConstructors(serviceClass);
|
167 |
| |
168 |
740
| outer: for (Iterator candidates = serviceConstructorCandidates.iterator(); candidates
|
169 |
| .hasNext();) |
170 |
| { |
171 |
743
| Constructor candidate = (Constructor) candidates.next();
|
172 |
| |
173 |
743
| Class[] parameterTypes = candidate.getParameterTypes();
|
174 |
| |
175 |
743
| Object[] parameters = new Object[parameterTypes.length];
|
176 |
| |
177 |
743
| for (int i = 0; i < parameters.length; i++)
|
178 |
| { |
179 |
11
| BuilderFacet facet = _parameter.getFacetForType(
|
180 |
| _factoryParameters, |
181 |
| parameterTypes[i]); |
182 |
| |
183 |
11
| if (facet != null && facet.canAutowireConstructorParameter())
|
184 |
3
| parameters[i] = facet.getFacetValue(_factoryParameters, parameterTypes[i]);
|
185 |
8
| else if (_contributingModule.containsService(parameterTypes[i]))
|
186 |
4
| parameters[i] = _contributingModule.getService(parameterTypes[i]);
|
187 |
| else |
188 |
4
| continue outer;
|
189 |
| } |
190 |
| |
191 |
739
| return ConstructorUtils.invoke(candidate, parameters);
|
192 |
| } |
193 |
| |
194 |
1
| throw new ApplicationRuntimeException(ServiceMessages.unableToFindAutowireConstructor(),
|
195 |
| _parameter.getLocation(), null); |
196 |
| } |
197 |
| |
198 |
740
| private List getOrderedServiceConstructors(Class serviceClass)
|
199 |
| { |
200 |
740
| List orderedInterfaceConstructors = new ArrayList();
|
201 |
| |
202 |
740
| Constructor[] constructors = serviceClass.getDeclaredConstructors();
|
203 |
| |
204 |
740
| outer: for (int i = 0; i < constructors.length; i++)
|
205 |
| { |
206 |
753
| if (!Modifier.isPublic(constructors[i].getModifiers()))
|
207 |
0
| continue;
|
208 |
| |
209 |
753
| Class[] parameterTypes = constructors[i].getParameterTypes();
|
210 |
| |
211 |
753
| if (parameterTypes.length > 0)
|
212 |
| { |
213 |
15
| Set seenTypes = new HashSet();
|
214 |
| |
215 |
15
| for (int j = 0; j < parameterTypes.length; j++)
|
216 |
| { |
217 |
23
| if (!parameterTypes[j].isInterface() || seenTypes.contains(parameterTypes[j]))
|
218 |
4
| continue outer;
|
219 |
| |
220 |
19
| seenTypes.add(parameterTypes[j]);
|
221 |
| } |
222 |
| } |
223 |
| |
224 |
749
| orderedInterfaceConstructors.add(constructors[i]);
|
225 |
| } |
226 |
| |
227 |
740
| Collections.sort(orderedInterfaceConstructors, new Comparator()
|
228 |
| { |
229 |
9
| public int compare(Object o1, Object o2)
|
230 |
| { |
231 |
9
| return ((Constructor) o2).getParameterTypes().length
|
232 |
| - ((Constructor) o1).getParameterTypes().length; |
233 |
| } |
234 |
| }); |
235 |
| |
236 |
740
| return orderedInterfaceConstructors;
|
237 |
| } |
238 |
| |
239 |
789
| private void invokeInitializer(Object service)
|
240 |
| { |
241 |
789
| String methodName = _parameter.getInitializeMethod();
|
242 |
| |
243 |
789
| boolean allowMissing = HiveMind.isBlank(methodName);
|
244 |
| |
245 |
789
| String searchMethodName = allowMissing ? "initializeService" : methodName;
|
246 |
| |
247 |
789
| try
|
248 |
| { |
249 |
789
| findAndInvokeInitializerMethod(service, searchMethodName, allowMissing);
|
250 |
| } |
251 |
| catch (InvocationTargetException ex) |
252 |
| { |
253 |
1
| Throwable cause = ex.getTargetException();
|
254 |
| |
255 |
1
| error(ServiceMessages.unableToInitializeService(_serviceId, searchMethodName, service
|
256 |
| .getClass(), cause), _parameter.getLocation(), cause); |
257 |
| } |
258 |
| catch (Exception ex) |
259 |
| { |
260 |
1
| error(ServiceMessages.unableToInitializeService(_serviceId, searchMethodName, service
|
261 |
| .getClass(), ex), _parameter.getLocation(), ex); |
262 |
| } |
263 |
| } |
264 |
| |
265 |
789
| private void findAndInvokeInitializerMethod(Object service, String methodName,
|
266 |
| boolean allowMissing) throws IllegalAccessException, InvocationTargetException, |
267 |
| NoSuchMethodException |
268 |
| { |
269 |
789
| Class serviceClass = service.getClass();
|
270 |
| |
271 |
789
| try
|
272 |
| { |
273 |
789
| Method m = serviceClass.getMethod(methodName, null);
|
274 |
| |
275 |
312
| m.invoke(service, null);
|
276 |
| } |
277 |
| catch (NoSuchMethodException ex) |
278 |
| { |
279 |
477
| if (allowMissing)
|
280 |
476
| return;
|
281 |
| |
282 |
1
| throw ex;
|
283 |
| } |
284 |
| } |
285 |
| |
286 |
789
| private void registerForEvents(Object result)
|
287 |
| { |
288 |
789
| List eventRegistrations = _parameter.getEventRegistrations();
|
289 |
| |
290 |
789
| if (eventRegistrations.isEmpty())
|
291 |
786
| return;
|
292 |
| |
293 |
3
| EventLinker linker = new EventLinkerImpl(_factoryParameters.getErrorLog());
|
294 |
| |
295 |
3
| Iterator i = eventRegistrations.iterator();
|
296 |
3
| while (i.hasNext())
|
297 |
| { |
298 |
3
| EventRegistration er = (EventRegistration) i.next();
|
299 |
| |
300 |
| |
301 |
| |
302 |
3
| linker.addEventListener(er.getProducer(), er.getEventSetName(), result, er
|
303 |
| .getLocation()); |
304 |
| } |
305 |
| } |
306 |
| |
307 |
789
| private void setProperties(Object service)
|
308 |
| { |
309 |
789
| List properties = _parameter.getProperties();
|
310 |
789
| int count = properties.size();
|
311 |
| |
312 |
| |
313 |
| |
314 |
789
| Set writeableProperties = new HashSet(PropertyUtils.getWriteableProperties(service));
|
315 |
| |
316 |
789
| for (int i = 0; i < count; i++)
|
317 |
| { |
318 |
5114
| BuilderFacet facet = (BuilderFacet) properties.get(i);
|
319 |
| |
320 |
5113
| String propertyName = wireProperty(service, facet);
|
321 |
| |
322 |
5112
| if (propertyName != null)
|
323 |
1173
| writeableProperties.remove(propertyName);
|
324 |
| } |
325 |
| |
326 |
789
| if (_parameter.getAutowireServices())
|
327 |
781
| autowireServices(service, writeableProperties);
|
328 |
| |
329 |
| } |
330 |
| |
331 |
| |
332 |
| |
333 |
| |
334 |
| |
335 |
5114
| private String wireProperty(Object service, BuilderFacet facet)
|
336 |
| { |
337 |
5113
| String propertyName = facet.getPropertyName();
|
338 |
| |
339 |
5113
| try
|
340 |
| { |
341 |
| |
342 |
| |
343 |
5113
| String autowirePropertyName = facet.autowire(service, _factoryParameters);
|
344 |
| |
345 |
5113
| if (autowirePropertyName != null)
|
346 |
744
| return autowirePropertyName;
|
347 |
| |
348 |
| |
349 |
| |
350 |
| |
351 |
| |
352 |
4369
| if (propertyName == null)
|
353 |
3938
| return null;
|
354 |
| |
355 |
431
| Class targetType = PropertyUtils.getPropertyType(service, propertyName);
|
356 |
| |
357 |
430
| Object value = facet.getFacetValue(_factoryParameters, targetType);
|
358 |
| |
359 |
429
| PropertyUtils.write(service, propertyName, value);
|
360 |
| |
361 |
429
| if (_log.isDebugEnabled())
|
362 |
9
| _log.debug("Set property " + propertyName + " to " + value);
|
363 |
| |
364 |
429
| return propertyName;
|
365 |
| } |
366 |
| catch (Exception ex) |
367 |
| { |
368 |
2
| error(ex.getMessage(), facet.getLocation(), ex);
|
369 |
| |
370 |
2
| return null;
|
371 |
| } |
372 |
| } |
373 |
| |
374 |
781
| private void autowireServices(Object service, Collection propertyNames)
|
375 |
| { |
376 |
781
| Iterator i = propertyNames.iterator();
|
377 |
781
| while (i.hasNext())
|
378 |
| { |
379 |
1060
| String propertyName = (String) i.next();
|
380 |
| |
381 |
1060
| autowireProperty(service, propertyName);
|
382 |
| } |
383 |
| } |
384 |
| |
385 |
1057
| private void autowireProperty(Object service, String propertyName)
|
386 |
| { |
387 |
1060
| Class propertyType = PropertyUtils.getPropertyType(service, propertyName);
|
388 |
| |
389 |
1060
| try
|
390 |
| { |
391 |
| |
392 |
| |
393 |
1060
| if( _contributingModule.containsService( propertyType ) )
|
394 |
| { |
395 |
910
| Object collaboratingService = _contributingModule.getService(propertyType);
|
396 |
910
| PropertyUtils.write(service, propertyName, collaboratingService);
|
397 |
| |
398 |
910
| if (_log.isDebugEnabled())
|
399 |
| { |
400 |
0
| _log.debug("Autowired service property " + propertyName + " to "
|
401 |
| + collaboratingService); |
402 |
| } |
403 |
| } |
404 |
| } |
405 |
| catch (Exception ex) |
406 |
| { |
407 |
0
| getErrorHandler().error(
|
408 |
| _log, |
409 |
| ServiceMessages.autowirePropertyFailure(propertyName, _serviceId, ex), |
410 |
| _parameter.getLocation(), |
411 |
| ex); |
412 |
| } |
413 |
| } |
414 |
| |
415 |
0
| private ErrorHandler getErrorHandler()
|
416 |
| { |
417 |
0
| return _contributingModule.getErrorHandler();
|
418 |
| } |
419 |
| |
420 |
| } |