/** * */ package jframe.core.plugin; import java.lang.reflect.Proxy; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.TreeSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jframe.core.conf.Config; import jframe.core.conf.ConfigConstants; import jframe.core.dispatch.DefDispatcher; import jframe.core.dispatch.DispatchSource; import jframe.core.dispatch.DispatchTarget; import jframe.core.dispatch.Dispatcher; import jframe.core.plugin.Plugin.PluginStatus; import jframe.core.plugin.annotation.Message; import jframe.core.plugin.dispatch.DispatchSourceHandler; import jframe.core.plugin.dispatch.DispatchTargetHandler; import jframe.core.signal.Signal; /** * @author dzh * @date Sep 27, 2013 2:55:25 PM * @since 1.0 */ public class DefPluginContext implements PluginContext, Dispatchable { private static final Logger _LOG = LoggerFactory.getLogger(DefPluginContext.class); private int plugin_id; private Config _config; private Map<Integer, PluginRef> _plugins; // 注册的插件 private Collection<PluginListener> _listeners; private Dispatcher _dispatcher; public void initContext(Config config) { this._config = config; this.plugin_id = 0; this._plugins = new HashMap<Integer, PluginRef>(); this._listeners = new LinkedList<PluginListener>(); // dispatch if (_dispatcher == null) { _dispatcher = createDefaultDispatcher(); _dispatcher.start(); } } private Dispatcher createDefaultDispatcher() { Dispatcher d = null; try { Class<?> clazz = Class.forName(_config.getConfig(ConfigConstants.CONTEXT_DISPATCHER, DefDispatcher.class.getName())); d = (Dispatcher) clazz.getConstructor(String.class, Config.class) .newInstance(_config.getConfig(ConfigConstants.CONTEXT_DISPATCHER_ID, "PluginContextDispatcher"), _config); } catch (Exception e) { _LOG.warn(e.getMessage(), e.fillInStackTrace()); d = DefDispatcher.newDispatcher("PluginContextDispatcher", getConfig()); } return d; } public PluginRef getPlugin(int id) { synchronized (_plugins) { return _plugins.get(id); } } public Collection<PluginRef> getPlugins() { return Collections.unmodifiableCollection(_plugins.values()); } public PluginRef regPlugin(Plugin plugin) { if (plugin == null) return null; plugin.setID(newPluginID()); try { plugin.init(this); } catch (Exception e) { _LOG.error(e.getMessage()); return null; // TODO } // reg ref before start PluginRef ref = null; synchronized (_plugins) { ref = containRef(plugin); if (ref == null) { ref = new DefPluginRef(this, plugin.getName()); _plugins.put(plugin.getID(), ref); } } ref.setPlugin(plugin); // handleAnnation regDispatch(ref); // set updating false if (ref.isUpdating()) ref.setUpdating(false); // start plugin try { plugin.start(); } catch (Exception e) { unregPlugin(plugin); _LOG.error("Plugin start error: {} {}", plugin.getName(), e.getLocalizedMessage()); return null; } return ref; } /** * @param plugin */ private void regDispatch(PluginRef ref) { Plugin plugin = ref.getPlugin(); Message am = plugin.getClass().getAnnotation(Message.class); if (am == null) { removeDispatchSource(ref); removeDispatchTarget(ref); return; } if (am.isSender()) { createDispatchSource(ref); } else { removeDispatchSource(ref); } if (am.isRecver()) { createDispatchTarget(ref); } else { removeDispatchTarget(ref); } } private void createDispatchTarget(PluginRef ref) { Object pdt = ref.getPolicy(PluginRef.DispatchTarget); if (pdt == null) { pdt = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { DispatchTarget.class }, new DispatchTargetHandler(ref)); ref.regPolicy(PluginRef.DispatchTarget, pdt); if (getDispatcher() != null) getDispatcher().addDispatchTarget((DispatchTarget) pdt); } else { // update previous configuration ((DispatchTargetHandler) Proxy.getInvocationHandler(pdt)).update(ref.getPlugin()); } } /** * @param ref */ private void createDispatchSource(PluginRef ref) { Object pds = ref.getPolicy(PluginRef.DispatchSource); // null is normal if (pds == null) { pds = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { DispatchSource.class }, new DispatchSourceHandler(ref)); ref.regPolicy(PluginRef.DispatchSource, pds); if (getDispatcher() != null) getDispatcher().addDispatchSource((DispatchSource) pds); } } private void removeDispatchSource(PluginRef ref) { Object p = ref.getPolicy(PluginRef.DispatchSource); Dispatcher d = getDispatcher(); if (d != null) { d.removeDispatchSource((DispatchSource) p); } if (p != null) { // 清理上次的内容 ref.unregPolicy(PluginRef.DispatchSource); } } private void removeDispatchTarget(PluginRef ref) { Object p = ref.getPolicy(PluginRef.DispatchTarget); Dispatcher d = getDispatcher(); if (d != null) { d.removeDispatchTarget((DispatchTarget) p); } if (p != null) { ref.unregPolicy(PluginRef.DispatchTarget); } } public PluginRef unregPlugin(Plugin plugin) { try { if (plugin.getStatus() == PluginStatus.START) { plugin.stop(); } if (plugin.getStatus() == PluginStatus.STOP) { plugin.destroy(); } } catch (PluginException e) { _LOG.error(e.getMessage()); } synchronized (_plugins) { PluginRef ref = _plugins.get(plugin.getID()); if (ref != null) { if (!ref.isUpdating()) { removeDispatchTarget(ref); _plugins.remove(plugin.getID()); ref.dispose(); } removeDispatchSource(ref); // ref.setPlugin(null); } return ref; } } public void signal(Signal sig) { _config.getFrame().broadcast(sig); } /** * <p> * 关闭过程: * <li>关闭插件</li> * <li>关闭dispatch</li> * </p> * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#dispose() */ public void dispose() { unregPlugins(getPlugins(), null); _dispatcher.close(); synchronized (_plugins) { _plugins.clear(); } synchronized (_listeners) { _listeners.clear(); } } private int newPluginID() { synchronized (this) { return ++plugin_id; } } /* * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#getConfig() */ public Config getConfig() { return _config; } /* * (non-Javadoc) * * @see * jframe.core.plugin.PluginContext#regPluginListener(jframe.core.plugin * .PluginListener) */ public void regPluginListener(PluginListener l) { synchronized (_listeners) { if (!_listeners.contains(l)) { _listeners.add(l); } } } /* * (non-Javadoc) * * @see * jframe.core.plugin.PluginContext#unregPluginListener(jframe.core.plugin * .PluginListener) */ public void unregPluginListener(PluginListener l) { synchronized (_listeners) { _listeners.remove(l); } } /* * (non-Javadoc) * * @see * jframe.core.plugin.PluginContext#notifyPluginEvent(jframe.core.plugin * .PluginEvent) */ public void notifyPluginEvent(PluginEvent event) { synchronized (_listeners) { Iterator<PluginListener> iter = _listeners.iterator(); while (iter.hasNext()) { iter.next().pluginChanged(event); } } } /** * * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#containRef(jframe.core.plugin.Plugin) * @return if find PluginRef return it, or return null */ private PluginRef containRef(Plugin plugin) { Iterator<PluginRef> iter = _plugins.values().iterator(); PluginRef ref = null; while (iter.hasNext()) { ref = iter.next(); if (ref.getPluginName().equals(plugin.getName())) { return ref; } } return null; } /* * (non-Javadoc) * * @see jframe.core.plugin.IDispatchable#getDispatcher() */ public Dispatcher getDispatcher() { return this._dispatcher; } /* * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#getPlugin(java.lang.String) */ public PluginRef getPlugin(String name) { synchronized (_plugins) { for (PluginRef pr : _plugins.values()) { if (pr.getPluginName().equals(name)) return pr; } } return null; } /* * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#regPlugins(java.util.Collection, * java.util.Comparator) */ public void regPlugins(Collection<Plugin> plugins, Comparator<? super Plugin> comparator) { if (plugins == null || plugins.size() == 0) return; if (comparator == null) { comparator = new PluginComparator(PluginComparator.TYPE.START); } TreeSet<Plugin> set = new TreeSet<Plugin>(comparator); for (Plugin p : plugins) { if (!set.add(p)) _LOG.warn("Found repeated plugin: " + p.getName()); } Iterator<Plugin> iter = set.iterator(); Plugin p = null; while (iter.hasNext()) { p = iter.next(); try { regPlugin(p); } catch (Exception e) { _LOG.error("When invoke pluginContext.regPlugin(), plugin name is " + p.getName() + " " + e.getMessage()); unregPlugin(p); } iter.remove(); } } /* * (non-Javadoc) * * @see jframe.core.plugin.PluginContext#unregPlugins(java.util.Collection, * java.util.Comparator) */ public void unregPlugins(Collection<PluginRef> plugins, Comparator<? super Plugin> comparator) { if (plugins.size() == 0) return; if (comparator == null) comparator = new PluginComparator(PluginComparator.TYPE.STOP); TreeSet<Plugin> set = new TreeSet<Plugin>(comparator); for (PluginRef ref : plugins) { if (ref.getPlugin() != null && !set.add(ref.getPlugin())) _LOG.warn("Found repeated plugin: " + ref.getPlugin().getName()); } Iterator<Plugin> iter = set.iterator(); while (iter.hasNext()) { unregPlugin(iter.next()); iter.remove(); } } public static class PluginComparator implements Comparator<Plugin> { public static enum TYPE { START, STOP } private TYPE type; public PluginComparator(TYPE type) { this.type = type; } /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Plugin o1, Plugin o2) { int v = 0; jframe.core.plugin.annotation.Plugin ap1 = o1.getClass().getAnnotation(jframe.core.plugin.annotation.Plugin.class); jframe.core.plugin.annotation.Plugin ap2 = o2.getClass().getAnnotation(jframe.core.plugin.annotation.Plugin.class); switch (type) { case START: { v = minus(ap1.startOrder(), ap2.startOrder()); break; } case STOP: { v = minus(ap1.stopOrder(), ap2.stopOrder()); break; } } if (v == 0) { v = o1.getName().compareTo(o2.getName()); } return v; } /** * 负数作为最大整数 * * @param minuend * @param subtrahend * @return */ int minus(int minuend, int subtrahend) { if (minuend < 0) { minuend = Integer.MAX_VALUE; } if (subtrahend < 0) { subtrahend = Integer.MAX_VALUE; } return minuend - subtrahend; } } /* * (non-Javadoc) * * @see * jframe.core.plugin.PluginContext#unregPlugin(jframe.core.plugin.PluginRef * ) */ public void unregPlugin(PluginRef ref) { if (ref == null || ref.getPlugin() == null) return; Plugin plugin = ref.getPlugin(); try { if (plugin.getStatus() == PluginStatus.START) { plugin.stop(); } if (plugin.getStatus() == PluginStatus.STOP) { plugin.destroy(); } } catch (PluginException e) { _LOG.error(e.getLocalizedMessage()); } synchronized (_plugins) { if (!ref.isUpdating()) { _plugins.remove(plugin.getID()); ref.dispose(); } removeDispatchSource(ref); ref.setPlugin(null); } } }