/** * */ 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)); } }