package co.codewizards.cloudstore.ls.core.invoke;
import static co.codewizards.cloudstore.core.util.AssertUtil.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import co.codewizards.cloudstore.core.Uid;
public class RemoteObjectProxyInvocationHandler implements InvocationHandler {
private static final Logger logger = LoggerFactory.getLogger(RemoteObjectProxyInvocationHandler.class);
protected final Uid refId = new Uid();
protected final Invoker invoker;
protected final ObjectRef objectRef;
protected final boolean equalsOverridden;
public RemoteObjectProxyInvocationHandler(final Invoker invoker, final ObjectRef objectRef) {
this.invoker = assertNotNull(invoker, "invoker");
this.objectRef = assertNotNull(objectRef, "objectRef");
if (logger.isDebugEnabled())
logger.debug("[{}]<init>: {} refId={}", getThisId(), objectRef, refId);
equalsOverridden = invoker.getClassInfoMap().getClassInfoOrFail(objectRef.getClassId()).isEqualsOverridden();
invoker.incRefCount(objectRef, refId);
}
@Override
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
// BEGIN implement RemoteObjectProxy
if ("getObjectRef".equals(method.getName()) && method.getParameterTypes().length == 0)
return objectRef;
// END implement RemoteObjectProxy
// BEGIN equals(...) + hashCode()
if (! equalsOverridden) {
if ("equals".equals(method.getName()) && method.getParameterTypes().length == 1)
return _equals(proxy, method, args[0]);
if ("hashCode".equals(method.getName()) && method.getParameterTypes().length == 0)
return _hashCode(proxy, method);
}
// END equals(...) + hashCode()
if (logger.isDebugEnabled())
logger.debug("[{}]invoke: method='{}'", getThisId(), method);
return invoker.invoke(objectRef, method.getName(), method.getParameterTypes(), args);
}
@Override
protected void finalize() throws Throwable {
if (logger.isDebugEnabled())
logger.debug("[{}]finalize: {}", getThisId(), objectRef);
invoker.decRefCount(objectRef, refId);
super.finalize();
}
private Object _equals(final Object proxy, final Method method, final Object other) {
if (proxy == other)
return true;
if (null == other)
return false;
if (proxy.getClass() != other.getClass())
return false;
final RemoteObjectProxyInvocationHandler otherHandler = (RemoteObjectProxyInvocationHandler) Proxy.getInvocationHandler(other);
return this.objectRef.equals(otherHandler.objectRef);
}
private int _hashCode(final Object proxy, final Method method) {
return 31 * objectRef.hashCode();
}
protected String getThisId() {
return Integer.toHexString(System.identityHashCode(this));
}
}