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