/**
*
*/
package jframe.core.plugin.dispatch;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.WeakHashMap;
import jframe.core.dispatch.DispatchSource;
import jframe.core.dispatch.Dispatcher;
import jframe.core.msg.Msg;
import jframe.core.plugin.Plugin;
import jframe.core.plugin.PluginRef;
import jframe.core.plugin.annotation.DispatchAdd;
import jframe.core.plugin.annotation.DispatchRemove;
import jframe.core.plugin.annotation.MsgSend;
/**
* @author dzh
* @date Oct 9, 2013 4:04:32 PM
* @since 1.0
*/
public class DispatchSourceHandler implements InvocationHandler {
private static final String M_Send = "send";
private static final String M_AddDispatch = "addDispatch";
private static final String M_RemoveDispatch = "removeDispatch";
private PluginRef _ref;
/**
* method cache
*/
private Map<String, WeakReference<Method>> _mc = new WeakHashMap<String, WeakReference<Method>>(6);
public DispatchSourceHandler(PluginRef ref) {
if (ref == null) {
throw new NullPointerException("PluginRef is null");
}
this._ref = ref;
}
/*
* (non-Javadoc)
*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Plugin p = _ref.getPlugin();
if (p == null) // "p==null" is impossible
return null;
if (method.equals(DispatchSource.class.getDeclaredMethod(M_Send, new Class[] { Msg.class }))) {
Method cm = getCacheMethod(M_Send);
if (cm != null)
return cm.invoke(p, args);
Class<?> clazz = p.getClass();
do {
for (Method m : p.getClass().getDeclaredMethods()) {
if (m.getAnnotation(MsgSend.class) != null) {
m.setAccessible(true);
putCacheMethod(M_Send, m);
return m.invoke(p, args);
}
}
} while ((clazz = clazz.getSuperclass()) != null);
} else if (method
.equals(DispatchSource.class.getDeclaredMethod(M_AddDispatch, new Class[] { Dispatcher.class }))) {
Method cm = getCacheMethod(M_AddDispatch);
if (cm != null)
return cm.invoke(p, args);
Class<?> clazz = p.getClass();
do {
for (Method m : clazz.getDeclaredMethods()) {
if (m.getAnnotation(DispatchAdd.class) != null) {
m.setAccessible(true);
putCacheMethod(M_Send, m);
return m.invoke(p, args);
}
}
} while ((clazz = clazz.getSuperclass()) != null);
} else if (method
.equals(DispatchSource.class.getDeclaredMethod(M_RemoveDispatch, new Class[] { Dispatcher.class }))) {
Method cm = getCacheMethod(M_RemoveDispatch);
if (cm != null)
return cm.invoke(p, args);
Class<?> clazz = p.getClass();
do {
for (Method m : clazz.getDeclaredMethods()) {
if (m.getAnnotation(DispatchRemove.class) != null) {
m.setAccessible(true);
putCacheMethod(M_Send, m);
return m.invoke(p, args);
}
}
} while ((clazz = clazz.getSuperclass()) != null);
}
return method.invoke(p, args);
}
private Method getCacheMethod(String name) {
WeakReference<Method> wr = _mc.get(name);
return wr == null ? null : wr.get();
}
private void putCacheMethod(String name, Method m) {
_mc.put(name, new WeakReference<Method>(m));
}
}