001package co.codewizards.cloudstore.ls.core.invoke; 002 003import static java.util.Objects.*; 004 005import java.lang.reflect.InvocationHandler; 006import java.lang.reflect.Method; 007import java.lang.reflect.Proxy; 008 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011 012import co.codewizards.cloudstore.core.Uid; 013 014public class RemoteObjectProxyInvocationHandler implements InvocationHandler { 015 016 private static final Logger logger = LoggerFactory.getLogger(RemoteObjectProxyInvocationHandler.class); 017 018 protected final Uid refId = new Uid(); 019 protected final Invoker invoker; 020 protected final ObjectRef objectRef; 021 protected final boolean equalsOverridden; 022 023 public RemoteObjectProxyInvocationHandler(final Invoker invoker, final ObjectRef objectRef) { 024 this.invoker = requireNonNull(invoker, "invoker"); 025 this.objectRef = requireNonNull(objectRef, "objectRef"); 026 027 if (logger.isDebugEnabled()) 028 logger.debug("[{}]<init>: {} refId={}", getThisId(), objectRef, refId); 029 030 equalsOverridden = invoker.getClassInfoMap().getClassInfoOrFail(objectRef.getClassId()).isEqualsOverridden(); 031 invoker.incRefCount(objectRef, refId); 032 } 033 034 @Override 035 public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { 036 // BEGIN implement RemoteObjectProxy 037 if ("getObjectRef".equals(method.getName()) && method.getParameterTypes().length == 0) 038 return objectRef; 039 // END implement RemoteObjectProxy 040 041 // BEGIN equals(...) + hashCode() 042 if (! equalsOverridden) { 043 if ("equals".equals(method.getName()) && method.getParameterTypes().length == 1) 044 return _equals(proxy, method, args[0]); 045 046 if ("hashCode".equals(method.getName()) && method.getParameterTypes().length == 0) 047 return _hashCode(proxy, method); 048 } 049 // END equals(...) + hashCode() 050 051 if (logger.isDebugEnabled()) 052 logger.debug("[{}]invoke: method='{}'", getThisId(), method); 053 054 return invoker.invoke(objectRef, method.getName(), method.getParameterTypes(), args); 055 } 056 057 @Override 058 protected void finalize() throws Throwable { 059 if (logger.isDebugEnabled()) 060 logger.debug("[{}]finalize: {}", getThisId(), objectRef); 061 062 invoker.decRefCount(objectRef, refId); 063 super.finalize(); 064 } 065 066 private Object _equals(final Object proxy, final Method method, final Object other) { 067 if (proxy == other) 068 return true; 069 070 if (null == other) 071 return false; 072 073 if (proxy.getClass() != other.getClass()) 074 return false; 075 076 final RemoteObjectProxyInvocationHandler otherHandler = (RemoteObjectProxyInvocationHandler) Proxy.getInvocationHandler(other); 077 return this.objectRef.equals(otherHandler.objectRef); 078 } 079 080 private int _hashCode(final Object proxy, final Method method) { 081 return 31 * objectRef.hashCode(); 082 } 083 084 protected String getThisId() { 085 return Integer.toHexString(System.identityHashCode(this)); 086 } 087}