}
@Override
public Object invoke(InvocationContext ctx) throws Throwable
{
MethodCall m = ctx.getMethodCall();
Object[] args = m.getArgs();
Object result = null;
if (MethodDeclarations.isCrudMethod(m.getMethodId()))
{
GlobalTransaction gtx = getGlobalTransaction(ctx);
TransactionWorkspace workspace = getTransactionWorkspace(gtx);
Fqn fqn = getFqn(args, m.getMethodId());
WorkspaceNode workspaceNode = fetchWorkspaceNode(ctx, fqn, workspace, MethodDeclarations.removeNodeMethodLocal_id != m.getMethodId(), true);
// in the case of a data gravitation cleanup, if the primary Fqn does not exist the backup one may.
if (workspaceNode == null && m.getMethodId() == MethodDeclarations.dataGravitationCleanupMethod_id)
{
workspaceNode = fetchWorkspaceNode(ctx, getBackupFqn(args), workspace, true, true);
}
if (workspaceNode != null)
{
// use explicit versioning
if (ctx.getOptionOverrides() != null && ctx.getOptionOverrides().getDataVersion() != null)
{
// if the method call is a move() then barf. Note that remove calls will set data versions explicitly, regardless.
if (ctx.isOriginLocal() && m.getMethodId() == MethodDeclarations.moveMethodLocal_id)
throw new CacheException("Setting a data version while performing a move() is not supported!!");
workspace.setVersioningImplicit(false);
DataVersion version = ctx.getOptionOverrides().getDataVersion();
workspaceNode.setVersion(version);
if (trace) log.trace("Setting versioning for node " + workspaceNode.getFqn() + " to explicit");
workspaceNode.setVersioningImplicit(false);
}
else
{
if (trace) log.trace("Setting versioning for node " + workspaceNode.getFqn() + " to implicit");
workspaceNode.setVersioningImplicit(true);
}
}
else
{
// "fail-more-silently" patch thanks to Owen Taylor - JBCACHE-767
if ((ctx.getOptionOverrides() == null || !ctx.getOptionOverrides().isFailSilently()) && MethodDeclarations.isPutMethod(m.getMethodId()))
{
throw new CacheException("Unable to set node version for " + fqn + ", node is null.");
}
}
switch (m.getMethodId())
{
case MethodDeclarations.moveMethodLocal_id:
Fqn parentFqn = (Fqn) args[1];
moveNodeAndNotify(parentFqn, workspaceNode, workspace, ctx);
break;
case MethodDeclarations.putDataMethodLocal_id:
putDataMapAndNotify((Map<Object, Object>) args[2], false, workspace, workspaceNode, ctx);
break;
case MethodDeclarations.putDataEraseMethodLocal_id:
putDataMapAndNotify((Map<Object, Object>) args[2], (Boolean) args[args.length - 1], workspace, workspaceNode, ctx);
break;
case MethodDeclarations.putKeyValMethodLocal_id:
case MethodDeclarations.putForExternalReadMethodLocal_id:
Object key = args[2];
Object value = args[3];
result = putDataKeyValueAndNotify(key, value, workspace, workspaceNode, ctx);
break;
case MethodDeclarations.removeNodeMethodLocal_id:
result = removeNode(workspace, workspaceNode, true, ctx);
break;
case MethodDeclarations.removeKeyMethodLocal_id:
Object removeKey = args[2];
result = removeKeyAndNotify(removeKey, workspace, workspaceNode, ctx);
break;
case MethodDeclarations.removeDataMethodLocal_id:
removeDataAndNotify(workspace, workspaceNode, ctx);
break;
case MethodDeclarations.dataGravitationCleanupMethod_id:
result = nextInterceptor(ctx);
default:
if (log.isWarnEnabled()) log.warn("Cannot handle CRUD method " + m);
break;
}
addToModificationList(gtx, m, ctx);
}
else
{
switch (m.getMethodId())
{
case MethodDeclarations.getKeyValueMethodLocal_id:
result = getValueForKeyAndNotify(args, getTransactionWorkspace(getGlobalTransaction(ctx)), ctx);
break;
case MethodDeclarations.getKeysMethodLocal_id: