//$Id: Interceptor.java 10311 2009-04-06 16:14:09Z pete.muir@jboss.org $ package org.jboss.seam.intercept; import static org.jboss.seam.util.EJB.AROUND_INVOKE; import static org.jboss.seam.util.EJB.POST_ACTIVATE; import static org.jboss.seam.util.EJB.POST_CONSTRUCT; import static org.jboss.seam.util.EJB.PRE_DESTROY; import static org.jboss.seam.util.EJB.PRE_PASSIVATE; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import org.jboss.seam.Component; import org.jboss.seam.annotations.intercept.AroundInvoke; import org.jboss.seam.annotations.intercept.InterceptorType; import org.jboss.seam.annotations.intercept.PostActivate; import org.jboss.seam.annotations.intercept.PostConstruct; import org.jboss.seam.annotations.intercept.PrePassivate; import org.jboss.seam.util.Reflections; /** * Wraps and delegates to a Seam interceptor. * * @author Gavin King */ public final class Interceptor extends Reflections { private Class<?> userInterceptorClass; private Object statelessUserInterceptorInstance; private Method aroundInvokeMethod; private Method postConstructMethod; private Method preDestroyMethod; private Method postActivateMethod; private Method prePassivateMethod; private Method componentInjectorMethod; private Method annotationInjectorMethod; private Method interceptorEnabledMethod; private InterceptorType type; private Annotation annotation; private Component component; private boolean optimized; private boolean isStateless() { return userInterceptorClass.isAnnotationPresent(org.jboss.seam.annotations.intercept.Interceptor.class) && userInterceptorClass.getAnnotation(org.jboss.seam.annotations.intercept.Interceptor.class).stateless(); } public Object createUserInterceptor() { if ( isStateless() ) { return statelessUserInterceptorInstance; } else { try { Object userInterceptor = userInterceptorClass.newInstance(); if (componentInjectorMethod!=null) { Reflections.invokeAndWrap(componentInjectorMethod, userInterceptor, component); } if (annotationInjectorMethod!=null) { Reflections.invokeAndWrap(annotationInjectorMethod, userInterceptor, annotation); } return userInterceptor; } catch (Exception e) { throw new RuntimeException(e); } } } public Class getUserInterceptorClass() { return userInterceptorClass; } public InterceptorType getType() { return type; } @Override public String toString() { return "Interceptor(" + userInterceptorClass.getName() + ")"; } public Interceptor(Object interceptor, Component component) { userInterceptorClass = interceptor.getClass(); statelessUserInterceptorInstance = interceptor; this.component = component; init(); } public Interceptor(Class[] classes, Annotation annotation, Component component) { if (classes.length!=1) { //TODO: remove this silly restriction! throw new IllegalArgumentException("Must be exactly one interceptor when used as a meta-annotation"); } userInterceptorClass = classes[0]; try { statelessUserInterceptorInstance = userInterceptorClass.newInstance(); } catch (Exception e) { throw new IllegalArgumentException("could not instantiate interceptor", e); } this.annotation = annotation; this.component = component; init(); } private void init() { for ( Method method : userInterceptorClass.getMethods() ) { if ( !method.isAccessible() ) method.setAccessible(true); if ( method.isAnnotationPresent(AROUND_INVOKE) || method.isAnnotationPresent(AroundInvoke.class) ) { aroundInvokeMethod = method; } if ( method.isAnnotationPresent(POST_CONSTRUCT) || method.isAnnotationPresent(PostConstruct.class)) { postConstructMethod = method; } if ( method.isAnnotationPresent(PRE_DESTROY) ) { preDestroyMethod = method; } if ( method.isAnnotationPresent(PRE_PASSIVATE) || method.isAnnotationPresent(PrePassivate.class) ) { prePassivateMethod = method; } if ( method.isAnnotationPresent(POST_ACTIVATE) || method.isAnnotationPresent(PostActivate.class) ) { postActivateMethod = method; } Class[] params = method.getParameterTypes(); //if there is a method that takes the annotation, call it, to pass initialization info if ( annotation!=null && params.length==1 && params[0]==annotation.annotationType() ) { annotationInjectorMethod = method; Reflections.invokeAndWrap(method, statelessUserInterceptorInstance, annotation); } //if there is a method that takes the component, call it if ( params.length==1 && params[0]==Component.class ) { componentInjectorMethod = method; Reflections.invokeAndWrap(method, statelessUserInterceptorInstance, component); } // if there is an interceptor enabled method, store it if ( "isInterceptorEnabled".equals(method.getName()) && method.getReturnType().equals(boolean.class) ) { interceptorEnabledMethod = method; } } type = userInterceptorClass.isAnnotationPresent(org.jboss.seam.annotations.intercept.Interceptor.class) ? userInterceptorClass.getAnnotation(org.jboss.seam.annotations.intercept.Interceptor.class).type() : InterceptorType.SERVER; optimized = OptimizedInterceptor.class.isAssignableFrom(userInterceptorClass); } public boolean isOptimized() { return optimized; } public Object aroundInvoke(InvocationContext invocation, Object userInterceptor) throws Exception { return aroundInvokeMethod==null ? invocation.proceed() : Reflections.invoke( aroundInvokeMethod, userInterceptor, invocation ); } public Object postConstruct(InvocationContext invocation, Object userInterceptor) throws Exception { return postConstructMethod==null ? invocation.proceed() : Reflections.invoke( postConstructMethod, userInterceptor, invocation ); } public Object preDestroy(InvocationContext invocation, Object userInterceptor) throws Exception { return preDestroyMethod==null ? invocation.proceed() : Reflections.invoke( preDestroyMethod, userInterceptor, invocation ); } public Object prePassivate(InvocationContext invocation, Object userInterceptor) throws Exception { return prePassivateMethod==null ? invocation.proceed() : Reflections.invoke( prePassivateMethod, userInterceptor, invocation ); } public Object postActivate(InvocationContext invocation, Object userInterceptor) throws Exception { return postActivateMethod==null ? invocation.proceed() : Reflections.invoke( postActivateMethod, userInterceptor, invocation ); } /** * Return true if the interceptor should be enabled for the component instance * * Should only be called during deployment */ public boolean isInterceptorEnabled() { if (interceptorEnabledMethod != null) { // Set up component metadata if (componentInjectorMethod!=null) { Reflections.invokeAndWrap(componentInjectorMethod, statelessUserInterceptorInstance, component); } if (annotationInjectorMethod!=null) { Reflections.invokeAndWrap(annotationInjectorMethod, statelessUserInterceptorInstance, annotation); } if (isOptimized()) { return ( (OptimizedInterceptor) statelessUserInterceptorInstance ).isInterceptorEnabled(); } else { return ((Boolean) Reflections.invokeAndWrap(interceptorEnabledMethod, statelessUserInterceptorInstance)); } } else { return true; } } }