/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.ejb3; import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel; import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager; import org.codehaus.aspectwerkz.reflect.ClassInfo; import org.codehaus.aspectwerkz.reflect.MethodInfo; import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; import org.codehaus.aspectwerkz.definition.AspectDefinition; import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer; import org.codehaus.aspectwerkz.definition.SystemDefinition; import org.codehaus.aspectwerkz.definition.AdviceDefinition; import org.codehaus.aspectwerkz.aspect.AdviceType; import org.codehaus.aspectwerkz.expression.ExpressionInfo; import javax.ejb.Interceptor; import javax.ejb.Interceptors; /** * A programmatic deployer for registering SLSB EJBs in the system * * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public class EJBInterceptorDeployer { static { AspectModelManager.registerAspectModels(EJBIsTheAspectModel.class.getName()); AspectModelManager.registerAspectModels(EJBInterceptorModel.class.getName()); } final static AspectModel EJB_ISTHEASPECT_MODEL = AspectModelManager.getModelFor(EJBIsTheAspectModel.TYPE); final static AspectModel EJB_INTERCEPTOR_MODEL = AspectModelManager.getModelFor(EJBInterceptorModel.TYPE); /** * Deploy a new EJB. The EJB gets registered in the AOP model if it is having an @AroundInvoke method. * * @param ejbClassName * @param loader */ public static void deploy(String ejbClassName, ClassLoader loader) { ClassInfo ejbClassInfo = AsmClassInfo.getClassInfo(ejbClassName, loader); SystemDefinition sysDef = SystemDefinitionContainer.getVirtualDefinitionAt(loader); // note: one could handle precedence here // deploy @Interceptor and @Interceptors entries if (ejbClassInfo.getAnnotationReader().isAnnotationPresent("javax.ejb.Interceptor")) { Interceptor interceptor = (Interceptor) ejbClassInfo.getAnnotationReader().getAnnotation("javax.ejb.Interceptor"); String interceptorClassName = interceptor.value(); deployTo(AsmClassInfo.getClassInfo(interceptorClassName, loader), ejbClassInfo, sysDef, false, loader); } if (ejbClassInfo.getAnnotationReader().isAnnotationPresent("javax.ejb.Interceptors")) { Interceptors interceptors = (Interceptors) ejbClassInfo.getAnnotationReader().getAnnotation("javax.ejb.Interceptors"); String[] interceptorClassNames = interceptors.value(); for (int i = 0; i < interceptorClassNames.length; i++) { String interceptorClassName = interceptorClassNames[i]; deployTo(AsmClassInfo.getClassInfo(interceptorClassName, loader), ejbClassInfo, sysDef, false, loader); } } // deploy local interceptors last. deployTo(ejbClassInfo, ejbClassInfo, sysDef, true, loader); } private static void deployTo(ClassInfo interceptorClassInfo, ClassInfo ejbClassInfo, SystemDefinition sysDef, boolean isBeanTheAspect, ClassLoader loader) { System.out.println("AW EJB3 - Deploying " + interceptorClassInfo.getName() + " for " + ejbClassInfo.getName()); //TODO right now limited to support only one local interceptor as per spec for (int i = 0; i < interceptorClassInfo.getMethods().length; i++) { MethodInfo methodInfo = interceptorClassInfo.getMethods()[i]; if ("java.lang.Object".equals(methodInfo.getReturnType().getName()) && methodInfo.getParameterTypes().length == 1 && "javax.ejb.InvocationContext".equals(methodInfo.getParameterTypes()[0].getName()) && interceptorClassInfo.getAnnotationReader().isMethodAnnotationPresent( "javax.ejb.AroundInvoke", methodInfo.getName(), methodInfo.getSignature()) ) { // we found an interceptor AspectDefinition aspect = new AspectDefinition( interceptorClassInfo.getName(), interceptorClassInfo, sysDef ); aspect.addAroundAdviceDefinition( new AdviceDefinition( methodInfo.getName(), AdviceType.AROUND, null, interceptorClassInfo.getName(), interceptorClassInfo.getName(), //TODO ones should exclude EJB bean method / callbacks / whatever spec says. //TODO vendor extension: would be easy to refine the pointcut new ExpressionInfo( buildPointcut(ejbClassInfo.getName(), methodInfo, loader), interceptorClassInfo.getName()), methodInfo, aspect ) ); sysDef.addAspect(aspect); if (isBeanTheAspect) { // register it as er the EJB MODEL aspect.setAspectModel(EJBIsTheAspectModel.TYPE); EJB_ISTHEASPECT_MODEL.defineAspect(interceptorClassInfo, aspect, loader); } else { aspect.setAspectModel(EJBInterceptorModel.TYPE); EJB_INTERCEPTOR_MODEL.defineAspect(interceptorClassInfo, aspect, loader); } } } } private static String buildPointcut(String ejbClassName, MethodInfo interceptorMethod, ClassLoader loader) { StringBuffer pointcut = new StringBuffer(); pointcut.append("execution(!@javax.ejb.AroundInvoke public !static * ").append(ejbClassName).append(".*(..))"); //TODO exclude non business method like life cycle callbacks etc // handles vendor extension @AroundInvokeAOP(..pointcut..) if (interceptorMethod.getDeclaringType().getAnnotationReader().isMethodAnnotationPresent( "org.codehaus.aspectwerkz.ejb3.AroundInvokeAOP", interceptorMethod.getName(), interceptorMethod.getSignature())) { pointcut.append(" && "); pointcut.append( ((AroundInvokeAOP)interceptorMethod.getDeclaringType().getAnnotationReader().getMethodAnnotation( "org.codehaus.aspectwerkz.ejb3.AroundInvokeAOP", interceptorMethod.getName(), interceptorMethod.getSignature(), loader )).value() ); } return pointcut.toString(); } }