[jboss-cvs] jboss-seam/src/main/org/jboss/seam/intercept ...
Gavin King
gavin.king at jboss.com
Tue Oct 10 02:43:16 EDT 2006
User: gavin
Date: 06/10/10 02:43:16
Added: src/main/org/jboss/seam/intercept
ClientSideInterceptor.java EventType.java
Interceptor.java JavaBeanInterceptor.java
JavaBeanInvocationContext.java RootInterceptor.java
SeamInvocationContext.java
SessionBeanInterceptor.java
Log:
refactored interceptor fwk, fixed serialization problems
Revision Changes Path
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/ClientSideInterceptor.java
Index: ClientSideInterceptor.java
===================================================================
//$Id: ClientSideInterceptor.java,v 1.1 2006/10/10 06:43:16 gavin Exp $
package org.jboss.seam.intercept;
import java.io.Serializable;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.jboss.seam.Component;
import org.jboss.seam.InterceptorType;
import org.jboss.seam.ejb.SeamInterceptor;
/**
* Controller interceptor for client-side interceptors of
* EJB3 session bean components
*
* @author Gavin King
*/
public class ClientSideInterceptor extends RootInterceptor
implements MethodInterceptor, Serializable
{
private final Object bean;
public ClientSideInterceptor(Object bean, Component component)
{
super(InterceptorType.CLIENT);
this.bean = bean;
init(component);
}
public Object intercept(final Object proxy, final Method method, final Object[] params,
final MethodProxy methodProxy) throws Throwable
{
return aroundInvoke( new JavaBeanInvocationContext(bean, method, params)
{
public Object proceed() throws Exception
{
SeamInterceptor.COMPONENT.set( getComponent() );
try
{
return methodProxy.invoke(bean, params);
}
catch (Error e)
{
throw e;
}
catch (Exception e)
{
throw e;
}
catch (Throwable t)
{
//only extremely wierd stuff!
throw new Exception(t);
}
finally
{
SeamInterceptor.COMPONENT.set(null);
}
}
});
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/EventType.java
Index: EventType.java
===================================================================
package org.jboss.seam.intercept;
public enum EventType
{
AROUND_INVOKE,
PRE_DESTORY,
POST_CONSTRUCT,
PRE_PASSIVATE,
POST_ACTIVATE
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/Interceptor.java
Index: Interceptor.java
===================================================================
//$Id: Interceptor.java,v 1.1 2006/10/10 06:43:16 gavin Exp $
package org.jboss.seam.intercept;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptors;
import javax.interceptor.InvocationContext;
import org.jboss.seam.Component;
import org.jboss.seam.InterceptorType;
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 InterceptorType type;
private Annotation annotation;
private Component component;
private boolean isStateless()
{
return userInterceptorClass.isAnnotationPresent(org.jboss.seam.annotations.Interceptor.class) &&
userInterceptorClass.getAnnotation(org.jboss.seam.annotations.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;
}
public String toString()
{
return "Interceptor(" + userInterceptorClass.getName() + ")";
}
public Interceptor(Object interceptor, Component component)
{
userInterceptorClass = interceptor.getClass();
statelessUserInterceptorInstance = interceptor;
this.component = component;
init();
}
public Interceptor(Annotation annotation, Component component)
{
Interceptors interceptorAnnotation = annotation.annotationType()
.getAnnotation(Interceptors.class);
Class[] classes = interceptorAnnotation.value();
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(AroundInvoke.class) )
{
aroundInvokeMethod = method;
}
if ( method.isAnnotationPresent(PostConstruct.class) )
{
postConstructMethod = method;
}
if ( method.isAnnotationPresent(PreDestroy.class) )
{
preDestroyMethod = method;
}
if ( method.isAnnotationPresent(PrePassivate.class) )
{
prePassivateMethod = method;
}
if ( 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, userInterceptorClass, 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);
}
}
type = userInterceptorClass.isAnnotationPresent(org.jboss.seam.annotations.Interceptor.class) ?
userInterceptorClass.getAnnotation(org.jboss.seam.annotations.Interceptor.class).type() :
InterceptorType.SERVER;
}
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 );
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/JavaBeanInterceptor.java
Index: JavaBeanInterceptor.java
===================================================================
//$Id: JavaBeanInterceptor.java,v 1.1 2006/10/10 06:43:16 gavin Exp $
package org.jboss.seam.intercept;
import java.io.Serializable;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.jboss.seam.Component;
import org.jboss.seam.InterceptorType;
/**
* Controller interceptor for JavaBean components
*
* @author Gavin King
*/
public class JavaBeanInterceptor extends RootInterceptor
implements MethodInterceptor, Serializable
{
private boolean recursive = false;
public JavaBeanInterceptor(Component component)
{
super(InterceptorType.ANY);
init(component);
}
public Object intercept(final Object target, final Method method, final Object[] params,
final MethodProxy methodProxy) throws Throwable
{
if (recursive)
{
return methodProxy.invokeSuper(target, params);
}
recursive = true;
try
{
String methodName = method.getName();
if ( "finalize".equals(methodName) )
{
return methodProxy.invokeSuper(target, params);
}
else if ( "sessionDidActivate".equals(methodName) )
{
callPostActivate(target);
return null;
}
else if ( "sessionWillPassivate".equals(methodName) )
{
callPrePassivate(target);
return null;
}
else
{
return interceptInvocation(target, method, params, methodProxy);
}
}
finally
{
recursive = false;
}
}
private void callPrePassivate(final Object target)
{
prePassivate( new JavaBeanInvocationContext(target, getComponent().getPrePassivateMethod(), new Object[0])
{
public Object proceed() throws Exception
{
getComponent().callPrePassivateMethod(target);
return null;
}
} );
}
private void callPostActivate( final Object target)
{
postActivate( new JavaBeanInvocationContext(target, getComponent().getPostActivateMethod(), new Object[0])
{
public Object proceed() throws Exception
{
getComponent().callPostActivateMethod(target);
return null;
}
} );
}
private Object interceptInvocation(final Object target, final Method method, final Object[] params,
final MethodProxy methodProxy) throws Exception
{
return aroundInvoke( new JavaBeanInvocationContext(target, method, params)
{
public Object proceed() throws Exception
{
try
{
return methodProxy.invokeSuper(target, params);
}
catch (Error e)
{
throw e;
}
catch (Exception e)
{
throw e;
}
catch (Throwable t)
{
//only extremely wierd stuff!
throw new Exception(t);
}
}
} );
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/JavaBeanInvocationContext.java
Index: JavaBeanInvocationContext.java
===================================================================
package org.jboss.seam.intercept;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.interceptor.InvocationContext;
/**
* InvocationContext for use with CGLIB-based interceptors.
*
* @author Gavin King
*
*/
public abstract class JavaBeanInvocationContext implements InvocationContext
{
private final Object bean;
private final Method method;
private Object[] params;
private final Map contextData = new HashMap();
public JavaBeanInvocationContext(Object bean, Method method, Object[] params)
{
this.bean = bean;
this.method = method;
this.params = params;
}
public abstract Object proceed() throws Exception;
public Object getTarget()
{
return bean;
}
public Map getContextData()
{
return contextData;
}
public Method getMethod()
{
return method;
}
public Object[] getParameters()
{
return params;
}
public void setParameters(Object[] newParams)
{
params = newParams;
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/RootInterceptor.java
Index: RootInterceptor.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.intercept;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.Component;
import org.jboss.seam.InterceptorType;
import org.jboss.seam.Seam;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
/**
* Abstract superclass of all controller interceptors
*
* @author Gavin King
*/
public class RootInterceptor implements Serializable
{
private static final Log log = LogFactory.getLog(RootInterceptor.class);
private final InterceptorType type;
private boolean isSeamComponent;
private String componentName;
private List<Object> userInterceptors;
private transient Component component; //a cache of the Component reference for performance
/**
* Called when instatiated by EJB container.
* (In this case it might be a Seam component,
* but we won't know until postConstruct() is
* called.)
*/
public RootInterceptor(InterceptorType type)
{
this.type = type;
}
protected void init(Component component)
{
isSeamComponent = true;
componentName = component.getName();
userInterceptors = component.createUserInterceptors(type);
this.component = component;
}
protected void initNonSeamComponent()
{
isSeamComponent = false;
}
@PostConstruct
public void postConstruct(InvocationContext invocation)
{
// initialize the bean instance
if (isSeamComponent)
{
try
{
getComponent().initialize( invocation.getTarget() );
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException("exception initializing EJB component", e);
}
}
invokeAndHandle(invocation, EventType.POST_CONSTRUCT);
}
@PreDestroy
public void preDestroy(InvocationContext invocation)
{
invokeAndHandle(invocation, EventType.PRE_DESTORY);
}
@PrePassivate
public void prePassivate(InvocationContext invocation)
{
invokeAndHandle(invocation, EventType.PRE_PASSIVATE);
}
@PostActivate
public void postActivate(InvocationContext invocation)
{
invokeAndHandle(invocation, EventType.POST_ACTIVATE);
}
private void invokeAndHandle(InvocationContext invocation, EventType invocationType)
{
try
{
invoke(invocation, invocationType);
}
catch (RuntimeException e)
{
throw e;
}
catch (Exception e)
{
throw new RuntimeException("exception in EJB lifecycle callback", e);
}
}
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
return invoke(invocation, EventType.AROUND_INVOKE);
}
private Object invoke(InvocationContext invocation, EventType invocationType) throws Exception
{
if ( !isSeamComponent )
{
//not a Seam component
return invocation.proceed();
}
else if ( Contexts.isEventContextActive() || Contexts.isApplicationContextActive() ) //not sure about the second bit (only needed at init time!)
{
//a Seam component, and Seam contexts exist
return invokeInContexts(invocation, invocationType);
}
else
{
//if invoked outside of a set of Seam contexts,
//set up temporary Seam EVENT and APPLICATION
//contexts just for this call
Lifecycle.beginCall();
try
{
return invokeInContexts(invocation, invocationType);
}
finally
{
Lifecycle.endCall();
}
}
}
private Object invokeInContexts(InvocationContext invocation, EventType eventType) throws Exception
{
if ( isProcessInterceptors(getComponent()) )
{
if ( log.isTraceEnabled() )
{
log.trace("intercepted: " + getComponent().getName() + '.' + invocation.getMethod().getName());
}
return new SeamInvocationContext( invocation, eventType, userInterceptors, getComponent().getInterceptors(type) ).proceed();
}
else {
if ( log.isTraceEnabled() )
{
log.trace("not intercepted: " + getComponent().getName() + '.' + invocation.getMethod().getName());
}
return invocation.proceed();
}
}
private boolean isProcessInterceptors(final Component component)
{
return component!=null && component.getInterceptionType().isActive();
}
protected Component getComponent()
{
if (isSeamComponent && component==null)
{
component = Seam.componentForName(componentName);
}
return component;
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/SeamInvocationContext.java
Index: SeamInvocationContext.java
===================================================================
//$Id: SeamInvocationContext.java,v 1.1 2006/10/10 06:43:16 gavin Exp $
package org.jboss.seam.intercept;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import javax.interceptor.InvocationContext;
/**
* Adapts from EJB interception to Seam component interceptors
*
* @author Gavin King
*/
public class SeamInvocationContext implements InvocationContext
{
private final EventType eventType;
private final InvocationContext ejbInvocationContext;
private final List<Interceptor> interceptors;
private final List<Object> userInterceptors;
int location = 0;
public SeamInvocationContext(InvocationContext ejbInvocationContext, EventType type, List<Object> userInterceptors, List<Interceptor> interceptors)
{
this.ejbInvocationContext = ejbInvocationContext;
this.interceptors = interceptors;
this.userInterceptors = userInterceptors;
this.eventType = type;
}
public Object getTarget()
{
return ejbInvocationContext.getTarget();
}
public Map getContextData()
{
return ejbInvocationContext.getContextData();
}
public Method getMethod()
{
return ejbInvocationContext.getMethod();
}
public Object[] getParameters()
{
return ejbInvocationContext.getParameters();
}
public Object proceed() throws Exception
{
if ( location==interceptors.size() )
{
return ejbInvocationContext.proceed();
}
else
{
Object userInterceptor = userInterceptors.get(location);
Interceptor interceptor = interceptors.get(location);
location++;
switch(eventType)
{
case AROUND_INVOKE: return interceptor.aroundInvoke(this, userInterceptor);
case POST_CONSTRUCT: return interceptor.postConstruct(this, userInterceptor);
case PRE_DESTORY: return interceptor.preDestroy(this, userInterceptor);
case PRE_PASSIVATE: return interceptor.prePassivate(this, userInterceptor);
case POST_ACTIVATE: return interceptor.postActivate(this, userInterceptor);
default: throw new IllegalArgumentException("no InvocationType");
}
}
}
public void setParameters(Object[] params)
{
ejbInvocationContext.setParameters(params);
}
}
1.1 date: 2006/10/10 06:43:16; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/intercept/SessionBeanInterceptor.java
Index: SessionBeanInterceptor.java
===================================================================
/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.intercept;
import javax.annotation.PostConstruct;
import javax.interceptor.InvocationContext;
import org.jboss.seam.Component;
import org.jboss.seam.InterceptorType;
import org.jboss.seam.Seam;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.intercept.RootInterceptor;
/**
* Controller interceptor for server-side interceptors of
* EJB3 session bean components.
*
* @author Gavin King
*/
public class SessionBeanInterceptor extends RootInterceptor
{
public static ThreadLocal<Component> COMPONENT = new ThreadLocal<Component>();
/**
* Called when instatiated by EJB container.
* (In this case it might be a Seam component,
* but we won't know until postConstruct() is
* called.)
*/
public SessionBeanInterceptor()
{
super(InterceptorType.SERVER);
}
@PostConstruct
public void postConstruct(InvocationContext invocation)
{
Component invokingComponent = SessionBeanInterceptor.COMPONENT.get();
if ( invokingComponent!=null )
{
//the session bean was obtained by the application by
//calling Component.getInstance(), could be a role
//other than the default role
init(invokingComponent);
}
else if ( invocation.getTarget().getClass().isAnnotationPresent(Name.class) )
{
//the session bean was obtained by the application from
//JNDI, so assume the default role
String defaultComponentName = invocation.getTarget().getClass().getAnnotation(Name.class).value();
init( Seam.componentForName( defaultComponentName ) );
}
else
{
initNonSeamComponent();
}
super.postConstruct(invocation);
}
}
More information about the jboss-cvs-commits
mailing list