1 15 package org.apache.hivemind.annotations.internal; 16 17 import java.lang.annotation.Annotation ; 18 import java.lang.reflect.Method ; 19 import java.lang.reflect.Modifier ; 20 21 import org.apache.commons.logging.Log; 22 import org.apache.commons.logging.LogFactory; 23 import org.apache.hivemind.ApplicationRuntimeException; 24 import org.apache.hivemind.ClassResolver; 25 import org.apache.hivemind.ErrorHandler; 26 import org.apache.hivemind.Location; 27 import org.apache.hivemind.Resource; 28 import org.apache.hivemind.annotations.AnnotationsMessages; 29 import org.apache.hivemind.annotations.definition.Configuration; 30 import org.apache.hivemind.annotations.definition.Module; 31 import org.apache.hivemind.annotations.definition.Service; 32 import org.apache.hivemind.annotations.definition.Submodule; 33 import org.apache.hivemind.definition.Contribution; 34 import org.apache.hivemind.definition.ImplementationConstructor; 35 import org.apache.hivemind.definition.ImplementationDefinition; 36 import org.apache.hivemind.definition.Occurances; 37 import org.apache.hivemind.definition.RegistryDefinition; 38 import org.apache.hivemind.definition.Visibility; 39 import org.apache.hivemind.definition.impl.ConfigurationPointDefinitionImpl; 40 import org.apache.hivemind.definition.impl.ContributionDefinitionImpl; 41 import org.apache.hivemind.definition.impl.ModuleDefinitionImpl; 42 import org.apache.hivemind.definition.impl.ImplementationDefinitionImpl; 43 import org.apache.hivemind.definition.impl.ServicePointDefinitionImpl; 44 import org.apache.hivemind.util.ClasspathResource; 45 import org.apache.hivemind.util.IdUtils; 46 47 57 public class AnnotatedModuleProcessor 58 { 59 private static final Log _log = LogFactory.getLog(AnnotatedModuleProcessor.class); 60 61 private ClassResolver _classResolver; 62 63 private ErrorHandler _errorHandler; 64 65 private RegistryDefinition _registryDefinition; 66 67 public AnnotatedModuleProcessor(RegistryDefinition registryDefinition, 68 ClassResolver classResolver, ErrorHandler errorHandler) 69 { 70 _registryDefinition = registryDefinition; 71 _classResolver = classResolver; 72 _errorHandler = errorHandler; 73 } 74 75 public void processModule(Class moduleClass) 76 { 77 String moduleId = determineModuleId(moduleClass); 78 processModule(moduleClass, moduleId); 79 } 80 81 86 public void processModule(Class moduleClass, String moduleId) 87 { 88 checkModuleClassPrerequisites(moduleClass); 89 90 ModuleDefinitionImpl module = new ModuleDefinitionImpl(moduleId, 91 createModuleLocation(moduleClass), _classResolver, moduleClass.getPackage().getName()); 92 93 95 ModuleInstanceProvider instanceProvider = new ModuleInstanceProviderImpl(moduleClass, 96 module.getId()); 97 _registryDefinition.addRegistryInitializationListener(instanceProvider); 100 101 processModuleMethods(moduleClass, module, instanceProvider); 102 _registryDefinition.addModule(module); 103 104 } 105 106 111 protected void checkModuleClassPrerequisites(Class moduleClass) 112 { 113 final int validModifiers = Modifier.PUBLIC; 115 116 int invalidModifiers = moduleClass.getModifiers() & ~validModifiers; 117 if (invalidModifiers > 0) { 118 throw new ApplicationRuntimeException(AnnotationsMessages.moduleClassHasInvalidModifiers(moduleClass, invalidModifiers)); 119 } 120 121 if ((moduleClass.getModifiers() & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE)) == 0) { 123 throw new ApplicationRuntimeException(AnnotationsMessages.moduleClassIsPackagePrivate(moduleClass)); 124 } 125 } 126 127 private void processModuleMethods(Class moduleClass, ModuleDefinitionImpl module, 128 ModuleInstanceProvider instanceProvider) 129 { 130 Method [] methods = moduleClass.getDeclaredMethods(); 133 for (int i = 0; i < methods.length; i++) 134 { 135 Method method = methods[i]; 136 processMethod(method, module, instanceProvider); 137 Class superClass = moduleClass.getSuperclass(); 139 if (!superClass.equals(Object .class)) { 140 processModuleMethods(superClass, module, instanceProvider); 141 } 142 } 143 } 144 145 private void processMethod(Method method, ModuleDefinitionImpl module, 146 ModuleInstanceProvider instanceProvider) 147 { 148 if (_log.isDebugEnabled()) 149 { 150 _log.debug("Checking method " + method.getName() + " for annotations"); 151 } 152 153 Annotation [] annotations = method.getAnnotations(); 154 for (int j = 0; j < annotations.length; j++) 155 { 156 Annotation annotation = annotations[j]; 157 158 if (Service.class.equals(annotation.annotationType())) 159 { 160 processAnnotatedServiceMethod( 161 method, 162 (Service) annotation, 163 module, 164 instanceProvider); 165 } 166 else if (Configuration.class.equals(annotation.annotationType())) 167 { 168 processAnnotatedConfigurationMethod( 169 method, 170 (Configuration) annotation, 171 module, 172 instanceProvider); 173 } 174 else if (org.apache.hivemind.annotations.definition.Contribution.class.equals(annotation.annotationType())) 175 { 176 processAnnotatedContributionMethod( 177 method, 178 (org.apache.hivemind.annotations.definition.Contribution) annotation, 179 module, 180 instanceProvider); 181 } 182 else if (Submodule.class.equals(annotation.annotationType())) 183 { 184 processAnnotatedSubmoduleMethod( 185 method, 186 (Submodule) annotation, 187 module, 188 instanceProvider); 189 } 190 } 191 192 } 193 194 201 protected void checkMethodModifiers(Method method, int allowedModifiers, String methodType) 202 { 203 final int validModifiers = Modifier.PUBLIC | Modifier.PROTECTED | allowedModifiers; 205 206 int invalidModifiers = method.getModifiers() & ~validModifiers; 207 if (invalidModifiers > 0) { 208 throw new ApplicationRuntimeException(AnnotationsMessages.annotatedMethodHasInvalidModifiers(method, methodType, invalidModifiers)); 209 } 210 211 213 if (Modifier.isProtected(method.getModifiers())) { 215 try 217 { 218 method.setAccessible(true); 219 } 220 catch (SecurityException e) 221 { 222 throw new ApplicationRuntimeException(AnnotationsMessages.annotatedMethodIsProtectedAndNotAccessible(method, methodType)); 223 } 224 } 225 } 226 227 private void processAnnotatedServiceMethod(Method method, Service service, 228 ModuleDefinitionImpl module, ModuleInstanceProvider instanceProvider) 229 { 230 checkMethodModifiers(method, 0, "service point"); 231 232 if (_log.isDebugEnabled()) 233 { 234 _log.debug("Method " + method.getName() + "classified as service point."); 235 } 236 237 Location location = new AnnotatedModuleLocation(module.getLocation().getResource(), 238 method.getDeclaringClass(), method); 239 240 Visibility visibility = Visibility.PUBLIC; 241 if (Modifier.isProtected(method.getModifiers())) { 242 visibility = Visibility.PRIVATE; 243 } 244 ServicePointDefinitionImpl spd = new ServicePointDefinitionImpl(module, service.id(), location, 245 visibility, method.getReturnType().getName()); 246 module.addServicePoint(spd); 247 248 ImplementationConstructor constructor = new MethodCallImplementationConstructor(location, 249 method, instanceProvider); 250 251 ImplementationDefinition sid = new ImplementationDefinitionImpl(module, location, 252 constructor, service.serviceModel(), true); 253 254 spd.addImplementation(sid); 255 256 } 257 258 private void processAnnotatedConfigurationMethod(Method method, Configuration configuration, ModuleDefinitionImpl module, ModuleInstanceProvider instanceProvider) 259 { 260 checkMethodModifiers(method, 0, "configuration point"); 261 262 if (_log.isDebugEnabled()) 263 { 264 _log.debug("Method " + method.getName() + "classified as configuration point."); 265 } 266 267 Location location = new AnnotatedModuleLocation(module.getLocation().getResource(), 268 method.getDeclaringClass(), method); 269 270 Visibility visibility = Visibility.PUBLIC; 271 if (Modifier.isProtected(method.getModifiers())) { 272 visibility = Visibility.PRIVATE; 273 } 274 ConfigurationPointDefinitionImpl cpd = new ConfigurationPointDefinitionImpl(module, configuration.id(), 275 location, visibility, method.getReturnType().getName(), Occurances.UNBOUNDED); 276 module.addConfigurationPoint(cpd); 277 278 Contribution contribution = new MethodCallContributionConstructor( 280 location, method, instanceProvider); 281 ContributionDefinitionImpl cd = new ContributionDefinitionImpl(module, location, contribution, true); 282 cpd.addContribution(cd); 283 } 284 285 private void processAnnotatedContributionMethod(Method method, org.apache.hivemind.annotations.definition.Contribution contribution, ModuleDefinitionImpl module, ModuleInstanceProvider instanceProvider) 286 { 287 checkMethodModifiers(method, 0, "contribution"); 288 289 if (_log.isDebugEnabled()) 290 { 291 _log.debug("Method " + method.getName() + "classified as contribution."); 292 } 293 294 Location location = new AnnotatedModuleLocation(module.getLocation().getResource(), 295 method.getDeclaringClass(), method); 296 297 Contribution constructor = new MethodCallContributionConstructor( 298 location, method, instanceProvider); 299 300 ContributionDefinitionImpl cd = new ContributionDefinitionImpl(module, location, constructor, false); 301 String qualifiedConfigurationId = IdUtils.qualify( 302 module.getId(), 303 contribution.configurationId()); 304 module.addContribution(qualifiedConfigurationId, cd); 305 306 } 307 308 311 private void processAnnotatedSubmoduleMethod(Method method, Submodule submodule, ModuleDefinitionImpl module, ModuleInstanceProvider instanceProvider) 312 { 313 checkMethodModifiers(method, 0, "submodule"); 314 315 if (_log.isDebugEnabled()) 316 { 317 _log.debug("Method " + method.getName() + "classified as submodule."); 318 } 319 320 String fullModuleId = IdUtils.qualify( 321 module.getId(), 322 submodule.id()); 323 AnnotatedModuleProcessor submoduleProcessor = new AnnotatedModuleProcessor(_registryDefinition, 325 _classResolver, _errorHandler); 326 submoduleProcessor.processModule(method.getReturnType(), fullModuleId); 327 } 328 329 332 protected Location createModuleLocation(Class moduleClass) 333 { 334 String path = "/" + moduleClass.getName().replace('.', '/'); 335 336 Resource r = new ClasspathResource(_classResolver, path); 337 338 return new AnnotatedModuleLocation(r, moduleClass); 339 } 340 341 350 private String determineModuleId(Class moduleClass) 351 { 352 Module moduleAnnotation = (Module) moduleClass.getAnnotation(Module.class); 353 if (moduleAnnotation != null) { 354 return moduleAnnotation.id(); 355 } else { 356 return getDefaultModuleId(moduleClass); 357 } 358 } 359 360 private String getDefaultModuleId(Class moduleClass) 361 { 362 return moduleClass.getName(); 363 } 364 } 365 | Popular Tags |