/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.cache.pojo.interceptors;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;
import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.PojoCacheException;
import org.jboss.cache.pojo.impl.MethodDeclarations;
import org.jboss.cache.pojo.util.MethodCall;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
/**
* Interceptor (done via aop advice) for transaction rollback. This is is attached to the
* operation that needs a corresponding rollback, e.g., attachInterceptor.
*
* @author Ben Wang
* @version $Id: PojoTxUndoInterceptor.java 3937 2007-05-30 06:08:03Z jgreene $
*/
public class PojoTxUndoInterceptor extends AbstractInterceptor
{
/// Just that AOP requires an extra key.
public static final String TAG = "PojoCache";
public Object invoke(Invocation in) throws Throwable
{
if (!(in instanceof MethodInvocation))
{
throw new IllegalArgumentException("TxUndoInterceptor.invoke(): invocation not MethodInvocation");
}
MethodInvocation invocation = (MethodInvocation) in;
PojoTxSynchronizationHandler handler =
PojoTxUndoSynchronizationInterceptor.getSynchronizationHandler();
if (handler == null)
{
return invocation.invokeNext();
// TODO handler is null can mean we are not calling the right interceptor stack. Need to revisit.
// E.g., a fresh getObject or find will trigger this.
// throw new IllegalStateException("PojoTxUndoInterceptor.invoke(): PojoTxSynchronizationHandler is null");
}
// Add to the rollback list
String methodName = invocation.getMethod().getName();
// TODO Needs to handle Collection interceptor as well.
if (methodName.equals(MethodDeclarations.attachInterceptor.getName()))
{
Method method = MethodDeclarations.undoAttachInterceptor;
MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
handler.addToList(mc);
}
else if (methodName.equals(MethodDeclarations.detachInterceptor.getName()))
{
Method method = MethodDeclarations.undoDetachInterceptor;
MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
handler.addToList(mc);
}
else if (methodName.equals(MethodDeclarations.inMemorySubstitution.getName()))
{
Method method = MethodDeclarations.undoInMemorySubstitution;
Object obj = invocation.getArguments()[0];
Field field = (Field) invocation.getArguments()[1];
Object oldValue = field.get(obj);
Object[] args = new Object[]{obj, field, oldValue};
MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
handler.addToList(mc);
}
else if (methodName.equals(MethodDeclarations.incrementReferenceCount.getName()))
{
Method method = MethodDeclarations.undoIncrementReferenceCount;
Fqn fqn = (Fqn) invocation.getArguments()[0];
int count = (Integer) invocation.getArguments()[1];
List referenceList = (List) invocation.getArguments()[2];
Object[] args = new Object[]{fqn, count, referenceList};
MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
handler.addToList(mc);
}
else if (methodName.equals(MethodDeclarations.decrementReferenceCount.getName()))
{
Method method = MethodDeclarations.undoDecrementReferenceCount;
Fqn fqn = (Fqn) invocation.getArguments()[0];
int count = (Integer) invocation.getArguments()[1];
List referenceList = (List) invocation.getArguments()[2];
Object[] args = new Object[]{fqn, count, referenceList};
MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
handler.addToList(mc);
}
else
{
throw new PojoCacheException("PojoTxUndoInterceptor: invalid invocation name: " + methodName);
}
return invocation.invokeNext();
}
}