[jboss-cvs] jboss-seam/src/main/org/jboss/seam/core ...
Gavin King
gavin.king at jboss.com
Mon Jun 25 19:59:31 EDT 2007
User: gavin
Date: 07/06/25 19:59:31
Added: src/main/org/jboss/seam/core BijectionInterceptor.java
ConversationInterceptor.java
ConversationalInterceptor.java
EventInterceptor.java MethodContextInterceptor.java
SynchronizationInterceptor.java
Log:
move builtin interceptors to the packages they relate to
Revision Changes Path
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/BijectionInterceptor.java
Index: BijectionInterceptor.java
===================================================================
//$Id: BijectionInterceptor.java,v 1.1 2007/06/25 23:59:30 gavin Exp $
package org.jboss.seam.core;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
/**
* Before invoking the component, inject all dependencies. After
* invoking, outject dependencies back into their context.
*
* @author Gavin King
*/
@Interceptor
public class BijectionInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = 4686458105931528659L;
private static final LogProvider log = Logging.getLogProvider(BijectionInterceptor.class);
private boolean reentrant; //OK, since all Seam components are single-threaded
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
if (reentrant)
{
if ( log.isTraceEnabled() )
{
log.trace("reentrant call to component: " + getComponent().getName() );
}
return invocation.proceed();
}
else
{
reentrant = true;
try
{
Component component = getComponent();
boolean enforceRequired = !component.isLifecycleMethod( invocation.getMethod() );
component.inject( invocation.getTarget(), enforceRequired );
Object result = invocation.proceed();
component.outject( invocation.getTarget(), enforceRequired );
component.disinject( invocation.getTarget() );
return result;
}
finally
{
reentrant = false;
}
}
}
}
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/ConversationInterceptor.java
Index: ConversationInterceptor.java
===================================================================
//$Id: ConversationInterceptor.java,v 1.1 2007/06/25 23:59:30 gavin Exp $
package org.jboss.seam.core;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.jboss.seam.annotations.ApplicationException;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.bpm.BeginTask;
import org.jboss.seam.annotations.bpm.EndTask;
import org.jboss.seam.annotations.bpm.StartTask;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.bpm.BusinessProcessInterceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.pageflow.Pageflow;
import org.jboss.seam.persistence.PersistenceContexts;
/**
* Implements annotation-based conversation demarcation.
*
* @author Gavin King
*/
@Interceptor(stateless=true,
around=BijectionInterceptor.class,
within=BusinessProcessInterceptor.class)
public class ConversationInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = -5405533438107796414L;
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
try
{
Method method = invocation.getMethod();
if ( getComponent().isConversationManagementMethod(method) ) //performance optimization
{
if ( isMissingJoin(method) )
{
throw new IllegalStateException("begin method invoked from a long running conversation, try using @Begin(join=true) on method: " + method.getName());
}
if ( redirectToExistingConversation(method) )
{
return null;
}
else
{
Object result = invocation.proceed();
beginConversationIfNecessary(method, result);
endConversationIfNecessary(method, result);
return result;
}
}
else
{
return invocation.proceed();
}
}
catch (Exception e)
{
if ( isEndConversationRequired(e) )
{
endConversation(false);
}
throw e;
}
}
private boolean isEndConversationRequired(Exception e)
{
Class<? extends Exception> clazz = e.getClass();
return clazz.isAnnotationPresent(ApplicationException.class)
&& clazz.getAnnotation(ApplicationException.class).end();
}
@SuppressWarnings("deprecation")
public boolean redirectToExistingConversation(Method method)
{
if ( !Manager.instance().isLongRunningConversation() )
{
String id = null;
if ( method.isAnnotationPresent(Begin.class) )
{
id = method.getAnnotation(Begin.class).id();
}
else if ( method.isAnnotationPresent(BeginTask.class) )
{
id = method.getAnnotation(BeginTask.class).id();
}
else if ( method.isAnnotationPresent(StartTask.class) )
{
id = method.getAnnotation(StartTask.class).id();
}
if ( id!=null && !"".equals(id) )
{
id = Interpolator.instance().interpolate(id);
ConversationEntry ce = ConversationEntries.instance().getConversationEntry(id);
if (ce==null)
{
Manager.instance().updateCurrentConversationId(id);
}
else
{
return ce.redirect();
}
}
}
return false;
}
private boolean isMissingJoin(Method method) {
return Manager.instance().isLongRunningOrNestedConversation() && (
(
method.isAnnotationPresent(Begin.class) &&
!method.getAnnotation(Begin.class).join() &&
!method.getAnnotation(Begin.class).nested()
) ||
method.isAnnotationPresent(BeginTask.class) ||
method.isAnnotationPresent(StartTask.class)
);
}
@SuppressWarnings("deprecation")
private void beginConversationIfNecessary(Method method, Object result)
{
boolean simpleBegin =
method.isAnnotationPresent(StartTask.class) ||
method.isAnnotationPresent(BeginTask.class) ||
( method.isAnnotationPresent(Begin.class) && method.getAnnotation(Begin.class).ifOutcome().length==0 );
if ( simpleBegin )
{
if ( result!=null || method.getReturnType().equals(void.class) )
{
boolean nested = false;
if ( method.isAnnotationPresent(Begin.class) )
{
nested = method.getAnnotation(Begin.class).nested();
}
beginConversation( nested, getProcessDefinitionName(method) );
setFlushMode(method); //TODO: what if conversation already exists? Or a nested conversation?
}
}
else if ( method.isAnnotationPresent(Begin.class) )
{
String[] outcomes = method.getAnnotation(Begin.class).ifOutcome();
if ( outcomes.length==0 || Arrays.asList(outcomes).contains(result) )
{
beginConversation(
method.getAnnotation(Begin.class).nested(),
getProcessDefinitionName(method)
);
setFlushMode(method); //TODO: what if conversation already exists? Or a nested conversation?
}
}
}
private void setFlushMode(Method method)
{
FlushModeType flushMode;
if (method.isAnnotationPresent(Begin.class))
{
flushMode = method.getAnnotation(Begin.class).flushMode();
}
else if (method.isAnnotationPresent(BeginTask.class))
{
flushMode = method.getAnnotation(BeginTask.class).flushMode();
}
else if (method.isAnnotationPresent(StartTask.class))
{
flushMode = method.getAnnotation(StartTask.class).flushMode();
}
else
{
return;
}
PersistenceContexts.instance().changeFlushMode(flushMode);
}
private String getProcessDefinitionName(Method method) {
if ( method.isAnnotationPresent(Begin.class) )
{
return method.getAnnotation(Begin.class).pageflow();
}
if ( method.isAnnotationPresent(BeginTask.class) )
{
return method.getAnnotation(BeginTask.class).pageflow();
}
if ( method.isAnnotationPresent(StartTask.class) )
{
return method.getAnnotation(StartTask.class).pageflow();
}
//TODO: let them pass a pageflow name as a request parameter
return "";
}
private void beginConversation(boolean nested, String pageflowName)
{
if ( !Manager.instance().isLongRunningOrNestedConversation() )
{
Manager.instance().beginConversation( );
beginNavigation(pageflowName);
}
else if (nested)
{
Manager.instance().beginNestedConversation( );
beginNavigation(pageflowName);
}
}
private void beginNavigation(String pageflowName)
{
if ( !pageflowName.equals("") )
{
Pageflow.instance().begin(pageflowName);
}
}
@SuppressWarnings("deprecation")
private void endConversationIfNecessary(Method method, Object result)
{
boolean isEndAnnotation = method.isAnnotationPresent(End.class);
boolean isEndTaskAnnotation = method.isAnnotationPresent(EndTask.class);
boolean beforeRedirect = ( isEndAnnotation && method.getAnnotation(End.class).beforeRedirect() ) ||
( isEndTaskAnnotation && method.getAnnotation(EndTask.class).beforeRedirect() );
boolean simpleEnd =
( isEndAnnotation && method.getAnnotation(End.class).ifOutcome().length==0 ) ||
( isEndTaskAnnotation && method.getAnnotation(EndTask.class).ifOutcome().length==0 );
if ( simpleEnd )
{
if ( result!=null || method.getReturnType().equals(void.class) ) //null outcome interpreted as redisplay
{
endConversation(beforeRedirect);
}
}
else if ( isEndAnnotation )
{
String[] outcomes = method.getAnnotation(End.class).ifOutcome();
if ( Arrays.asList(outcomes).contains(result) )
{
endConversation(beforeRedirect);
}
}
else if ( isEndTaskAnnotation )
{
//TODO: fix minor code duplication
String[] outcomes = method.getAnnotation(EndTask.class).ifOutcome();
if ( Arrays.asList(outcomes).contains(result) )
{
endConversation(beforeRedirect);
}
}
}
private void endConversation(boolean beforeRedirect)
{
Manager.instance().endConversation(beforeRedirect);
}
}
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/ConversationalInterceptor.java
Index: ConversationalInterceptor.java
===================================================================
//$Id: ConversationalInterceptor.java,v 1.1 2007/06/25 23:59:30 gavin Exp $
package org.jboss.seam.core;
import java.lang.reflect.Method;
import org.jboss.seam.NoConversationException;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.bpm.BeginTask;
import org.jboss.seam.annotations.bpm.StartTask;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.bpm.BusinessProcessInterceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
/**
* Check that a conversational bean is not being invoked
* outside the scope of a long-running conversation. If
* it is, throw an exception.
*
* @author Gavin King
*/
@Interceptor(stateless=true,
around={BijectionInterceptor.class, BusinessProcessInterceptor.class})
public class ConversationalInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = 1127583515811479385L;
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
Method method = invocation.getMethod();
if ( isNoConversationForConversationalBean(method) )
{
Events.instance().raiseEvent("org.jboss.seam.noConversation");
throw new NoConversationException( "no long-running conversation for @Conversational bean: " + getComponent().getName() );
}
return invocation.proceed();
}
private boolean isNoConversationForConversationalBean(Method method)
{
boolean classlevelViolation = componentIsConversational() &&
!Manager.instance().isLongRunningOrNestedConversation() &&
!method.isAnnotationPresent(Begin.class) &&
!method.isAnnotationPresent(StartTask.class) &&
!method.isAnnotationPresent(BeginTask.class) &&
!method.isAnnotationPresent(Destroy.class) &&
!method.isAnnotationPresent(Create.class); //probably superfluous
if (classlevelViolation) return true;
boolean methodlevelViolation = methodIsConversational(method) &&
!Manager.instance().isLongRunningOrNestedConversation();
return methodlevelViolation;
}
private boolean methodIsConversational(Method method)
{
return method.isAnnotationPresent(Conversational.class);
}
private boolean componentIsConversational()
{
return getComponent().getBeanClass().isAnnotationPresent(Conversational.class);
}
}
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/EventInterceptor.java
Index: EventInterceptor.java
===================================================================
package org.jboss.seam.core;
import java.lang.reflect.Method;
import org.jboss.seam.annotations.RaiseEvent;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.bpm.BusinessProcessInterceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.transaction.RollbackInterceptor;
import org.jboss.seam.transaction.TransactionInterceptor;
/**
* Raises Seam events connected with a bean lifecycle.
*
* @author Gavin King
*
*/
@Interceptor(stateless=true,
around={BijectionInterceptor.class, ConversationInterceptor.class,
TransactionInterceptor.class, BusinessProcessInterceptor.class,
RollbackInterceptor.class})
public class EventInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = -136300200838134612L;
/*@PostConstruct
public void postConstruct(InvocationContext ctx)
{
Events.instance().raiseEvent("org.jboss.seam.postConstruct." + component.getName());
}
@PreDestroy
public void preDestroy(InvocationContext ctx)
{
Events.instance().raiseEvent("org.jboss.seam.preDestroy." + component.getName());
}
@PrePassivate
public void prePassivate(InvocationContext ctx)
{
Events.instance().raiseEvent("org.jboss.seam.prePassivate." + component.getName());
}
@PostActivate
public void postActivate(InvocationContext ctx)
{
Events.instance().raiseEvent("org.jboss.seam.postActivate." + component.getName());
}*/
@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception
{
Object result = ctx.proceed();
Method method = ctx.getMethod();
if ( result!=null || method.getReturnType().equals(void.class) )
{
if ( method.isAnnotationPresent(RaiseEvent.class) )
{
String[] types = method.getAnnotation(RaiseEvent.class).value();
if ( types.length==0 )
{
Events.instance().raiseEvent( method.getName() );
}
else
{
for (String type: types )
{
Events.instance().raiseEvent(type);
}
}
}
}
return result;
}
}
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/MethodContextInterceptor.java
Index: MethodContextInterceptor.java
===================================================================
package org.jboss.seam.core;
import java.lang.reflect.Method;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.security.SecurityInterceptor;
/**
* Sets up the METHOD context and unproxies the SFSB
* for the duration of the call.
*
* @author Gavin King
*
*/
@Interceptor(stateless=true, around={BijectionInterceptor.class, EventInterceptor.class, SecurityInterceptor.class})
public class MethodContextInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = 6833040683938889232L;
@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception
{
Component comp = getComponent();
String name = comp.getName();
Object target = ctx.getTarget();
Method method = ctx.getMethod();
Object[] parameters = ctx.getParameters();
Context outerMethodContext = Lifecycle.beginMethod();
try
{
Contexts.getMethodContext().set(name, target);
Contexts.getMethodContext().set("org.jboss.seam.this", target);
Contexts.getMethodContext().set("org.jboss.seam.method", method);
Contexts.getMethodContext().set("org.jboss.seam.parameters", parameters);
Contexts.getMethodContext().set("org.jboss.seam.component", comp);
return ctx.proceed();
}
finally
{
Lifecycle.endMethod(outerMethodContext);
}
}
}
1.1 date: 2007/06/25 23:59:30; author: gavin; state: Exp;jboss-seam/src/main/org/jboss/seam/core/SynchronizationInterceptor.java
Index: SynchronizationInterceptor.java
===================================================================
//$Id: SynchronizationInterceptor.java,v 1.1 2007/06/25 23:59:30 gavin Exp $
package org.jboss.seam.core;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.annotations.intercept.InterceptorType;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
/**
* Serializes calls to a component.
*
* @author Gavin King
*/
@Interceptor(type=InterceptorType.CLIENT)
public class SynchronizationInterceptor extends AbstractInterceptor
{
private static final long serialVersionUID = -4173880108889358566L;
private ReentrantLock lock = new ReentrantLock(true);
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
if ( lock.tryLock( getComponent().getTimeout(), TimeUnit.MILLISECONDS ) )
{
try
{
return invocation.proceed();
}
finally
{
lock.unlock();
}
}
else
{
throw new IllegalStateException("could not acquire lock on @Synchronized component: " + getComponent().getName());
}
}
}
More information about the jboss-cvs-commits
mailing list