public ComponentDescriptor analyze(ASTType astType) { Application applicationAnnotation = astType.getAnnotation(Application.class); PackageClass inputType = astType.getPackageClass(); PackageClass applicationClassName; if (StringUtils.isBlank(applicationAnnotation.name())) { applicationClassName = inputType.append("Application"); } else { applicationClassName = inputType.replaceName(applicationAnnotation.name()); } ComponentDescriptor applicationDescriptor = new ComponentDescriptor(android.app.Application.class.getName(), applicationClassName); // analyze delegate AnalysisContext analysisContext = analysisContextFactory.buildAnalysisContext(buildVariableBuilderMap()); // application generation profile setupApplicationProfile(applicationDescriptor, astType, analysisContext); // add manifest elements setupManifest( applicationAnnotation, applicationDescriptor.getPackageClass().getFullyQualifiedName(), applicationAnnotation.label()); return applicationDescriptor; }
public void processType(ASTType astType) { ImplementedBy annotation = astType.getAnnotation(ImplementedBy.class); if (annotation != null) { TypeMirror implementedClass = getTypeMirror(new ImplementedByClassTypeMirrorRunnable(annotation)); ASTType implAstType = implementedClass.accept(astTypeBuilderVisitor, null); if (!implAstType.inheritsFrom(astType)) { throw new TransfuseAnalysisException( "ImplementedBy configuration points to a class that doesn't inherit from the given base class"); } injectionNodeBuilders.putModuleConfig( astType, variableInjectionBuilderFactory.buildVariableInjectionNodeBuilder(implAstType)); } }
@Override public void generate(ASTType descriptor) { if (descriptor.isConcreteClass()) { throw new TransfuseAnalysisException("Unable to build injector from concrete class"); } try { JDefinedClass implClass = codeModel._class(JMod.PUBLIC, descriptor.getName() + IMPL_EXT, ClassType.CLASS); JClass interfaceClass = codeModel.ref(descriptor.getName()); implClass._implements(interfaceClass); for (ASTMethod interfaceMethod : descriptor.getMethods()) { MirroredMethodGenerator mirroredMethodGenerator = componentBuilderFactory.buildMirroredMethodGenerator(interfaceMethod, false); MethodDescriptor methodDescriptor = mirroredMethodGenerator.buildMethod(implClass); JBlock block = methodDescriptor.getMethod().body(); AnalysisContext context = analysisContextFactory.buildAnalysisContext(injectionNodeBuilderRepository); InjectionNodeFactory injectionNodeFactory = componentBuilderFactory.buildInjectionNodeFactory( interfaceMethod.getReturnType(), context); // Injections InjectionNode returnType = injectionNodeFactory.buildInjectionNode(methodDescriptor); Map<InjectionNode, TypedExpression> expressionMap = injectionFragmentGenerator.buildFragment(block, implClass, returnType); block._return(expressionMap.get(returnType).getExpression()); } injectorRepositoryGenerator.generateInjectorRepository(interfaceClass, implClass); } catch (JClassAlreadyExistsException e) { throw new TransfuseAnalysisException( "Class already exists for generated type " + descriptor.getName(), e); } catch (ClassNotFoundException e) { throw new TransfuseAnalysisException("Target class not found", e); } }
@Test public void testAnalysis() { AnalysisContext analysisContext = simpleAnalysisContextFactory.buildContext(); analysisContext.getAOPRepository().put(aopAnnotationASTType, methodInterceptorASTType); for (ASTMethod astMethod : proxyTargetASTType.getMethods()) { proxyAnalyzer.analyzeMethod( proxyTargetInjectionNode, proxyTargetASTType, astMethod, analysisContext); } assertTrue(proxyTargetInjectionNode.containsAspect(AOPProxyAspect.class)); AOPProxyAspect aspect = proxyTargetInjectionNode.getAspect(AOPProxyAspect.class); for (ASTMethod astMethod : proxyTargetASTType.getMethods()) { assertTrue(aspect.getMethodInterceptors().containsKey(astMethod)); Set<InjectionNode> interceptorInjectionNodes = aspect.getMethodInterceptors().get(astMethod); for (InjectionNode interceptorInjectionNode : interceptorInjectionNodes) { assertEquals(methodInterceptorASTType, interceptorInjectionNode.getASTType()); } } }
@Override public void analyzeType( InjectionNode injectionNode, ASTType concreteType, AnalysisContext context) { if (injectionNode.getASTType().equals(concreteType)) { for (Class<? extends Annotation> scopeType : scopeAspectFactoryRepository.getScopes()) { if (concreteType.isAnnotated(scopeType)) { ScopeAspectFactory scopeAspectFactory = scopeAspectFactoryRepository.getScopeAspectFactory(scopeType); injectionNode.addAspect( scopeAspectFactory.buildAspect(injectionNode, concreteType, context)); } } } }
private InjectionNode innerGenerateProxyCode(InjectionNode injectionNode) { AOPProxyAspect aopProxyAspect = injectionNode.getAspect(AOPProxyAspect.class); JDefinedClass definedClass; String proxyClassName = injectionNode.getClassName() + "_AOPProxy"; ASTInjectionAspect injectionAspect = injectionNode.getAspect(ASTInjectionAspect.class); ConstructorInjectionPoint constructorInjectionPoint = injectionAspect.getConstructorInjectionPoint(); ConstructorInjectionPoint proxyConstructorInjectionPoint = new ConstructorInjectionPoint(ASTAccessModifier.PUBLIC); try { definedClass = codeModel._class(JMod.PUBLIC, proxyClassName, ClassType.CLASS); annotateGeneratedClass(definedClass); // extending injectionNode definedClass._extends(codeModel.ref(injectionNode.getClassName())); // copy constructor elements and add aop interceptors JMethod constructor = definedClass.constructor(JMod.PUBLIC); // converting exceptions into runtime exceptions proxyConstructorInjectionPoint.addThrows(constructorInjectionPoint.getThrowsTypes()); for (ASTType throwType : constructorInjectionPoint.getThrowsTypes()) { constructor._throws(codeModel.ref(throwType.getName())); } JBlock constructorBody = constructor.body(); List<JVar> superArguments = new ArrayList<JVar>(); for (InjectionNode node : constructorInjectionPoint.getInjectionNodes()) { String paramName = namer.generateName(node); JVar param = constructor.param(codeModel.ref(node.getClassName()), paramName); superArguments.add(param); proxyConstructorInjectionPoint.addInjectionNode(node); } // super construction JInvocation constructorInvocation = constructorBody.invoke(SUPER_REF); for (JVar paramArgument : superArguments) { constructorInvocation.arg(paramArgument); } // method interceptors Map<ASTMethod, Map<InjectionNode, JFieldVar>> interceptorFields = new HashMap<ASTMethod, Map<InjectionNode, JFieldVar>>(); for (Map.Entry<ASTMethod, Set<InjectionNode>> methodInterceptorEntry : aopProxyAspect.getMethodInterceptors().entrySet()) { buildMethodInterceptor( definedClass, proxyConstructorInjectionPoint, constructor, constructorBody, interceptorFields, methodInterceptorEntry); } } catch (JClassAlreadyExistsException e) { logger.error("JClassAlreadyExistsException while building AOP Proxy", e); } catch (ClassNotFoundException e) { logger.error("ClassNotFoundException while building AOP Proxy", e); } return buildProxyInjectionNode( injectionNode, proxyClassName, injectionAspect, proxyConstructorInjectionPoint); }
private JExpression buildInterceptorChain( JDefinedClass definedClass, ASTMethod method, Map<ASTParameter, JVar> parameterMap, Set<InjectionNode> interceptors, Map<InjectionNode, JFieldVar> interceptorNameMap) { try { JDefinedClass methodExecutionClass = definedClass._class( JMod.PRIVATE | JMod.FINAL, namer.generateClassName(MethodInterceptorChain.MethodExecution.class)); methodExecutionClass._implements(MethodInterceptorChain.MethodExecution.class); // setup constructor with needed parameters JMethod constructor = methodExecutionClass.constructor(JMod.PUBLIC); JBlock constructorbody = constructor.body(); List<JExpression> methodParameters = new ArrayList<JExpression>(); for (ASTParameter parameter : method.getParameters()) { JType parameterType = parameterMap.get(parameter).type(); JVar param = constructor.param(parameterType, namer.generateName(parameterType)); JFieldVar field = methodExecutionClass.field( JMod.PRIVATE, parameterType, namer.generateName(parameterType)); constructorbody.assign(field, param); methodParameters.add(field); } // getMethod() JMethod getMethod = methodExecutionClass.method( JMod.PUBLIC, Method.class, MethodInterceptorChain.MethodExecution.GET_METHOD); JInvocation getMethodInvocation = definedClass.dotclass().invoke(CLASS_GET_METHOD).arg(method.getName()); getMethod.body()._return(getMethodInvocation); getMethod._throws(NoSuchMethodException.class); for (ASTParameter astParameter : method.getParameters()) { getMethodInvocation.arg(codeModel.ref(astParameter.getASTType().getName()).dotclass()); } // invoke() JMethod invokeMethod = methodExecutionClass.method( JMod.PUBLIC, Object.class, MethodInterceptorChain.MethodExecution.INVOKE); // add all throws of contained method for (ASTType throwable : method.getThrowsTypes()) { invokeMethod._throws(codeModel.ref(throwable.getName())); } JInvocation superCall = definedClass.staticRef(SUPER_REF).invoke(method.getName()); for (JExpression methodParam : methodParameters) { superCall.arg(methodParam); } if (method.getReturnType().equals(ASTVoidType.VOID)) { invokeMethod.body().add(superCall); invokeMethod.body()._return(JExpr._null()); } else { invokeMethod.body()._return(superCall); } JInvocation methodExecutionInvocation = JExpr._new(methodExecutionClass); for (ASTParameter astParameter : method.getParameters()) { methodExecutionInvocation.arg(parameterMap.get(astParameter)); } JInvocation newInterceptorInvocation = JExpr._new(codeModel.ref(MethodInterceptorChain.class)) .arg(methodExecutionInvocation) .arg(JExpr._this()); for (InjectionNode interceptor : interceptors) { newInterceptorInvocation.arg(interceptorNameMap.get(interceptor)); } return newInterceptorInvocation; } catch (JClassAlreadyExistsException e) { throw new TransfuseAnalysisException("Class already defined while generating inner class", e); } }