package org.etk.kernel.container.jmx; import java.lang.reflect.Method; import java.util.List; import org.etk.common.logging.Logger; import org.etk.kernel.container.KernelContainer; import org.etk.kernel.container.component.ComponentLifecycle; import org.etk.kernel.container.component.ComponentPlugin; import org.etk.kernel.container.configuration.ConfigurationManager; import org.etk.kernel.container.xml.Component; import org.etk.kernel.container.xml.ExternalComponentPlugins; import org.etk.kernel.container.xml.InitParams; import org.picocontainer.PicoContainer; import org.picocontainer.defaults.AbstractComponentAdapter; @SuppressWarnings("unchecked") public class MX4JComponentAdapter extends AbstractComponentAdapter { /** * Serial Version ID */ private static final long serialVersionUID = -9001193588034229411L; private volatile Object instance_; private Logger log = Logger.getLogger(MX4JComponentAdapter.class); public MX4JComponentAdapter(Object key, Class implementation) { super(key, implementation); } public Object getComponentInstance(PicoContainer container) { if (instance_ != null) return instance_; // KernelContainer kernelContainer = (KernelContainer) container; Component component = null; ConfigurationManager manager; String componentKey; try { InitParams params = null; boolean debug = false; synchronized (this) { // Avoid to create duplicate instances if it is called at the // same time by several threads if (instance_ != null) return instance_; // Get the component key Object key = getComponentKey(); if (key instanceof String) componentKey = (String) key; else componentKey = ((Class) key).getName(); //Gets the Component configuration information which stores in the ConfigurationManager class. manager = (ConfigurationManager) kernelContainer.getComponentInstanceOfType(ConfigurationManager.class); component = manager.getComponent(componentKey); if (component != null) { params = component.getInitParams(); debug = component.getShowDeployInfo(); } // Please note that we cannot fully initialize the Object // "instance_" before releasing other // threads because it could cause StackOverflowError due to // recursive calls instance_ = kernelContainer.createComponent(getComponentImplementation(), params); } if (debug) log.debug("==> created component : " + instance_); //processing the add ComponentPlugin for current instance_ if (component != null && component.getComponentPlugins() != null) { addComponentPlugin(debug, instance_, component.getComponentPlugins(), kernelContainer); } //processing the add ExternalComponentPlugin for current instance_ ExternalComponentPlugins ecplugins = manager.getConfiguration().getExternalComponentPlugins(componentKey); if (ecplugins != null) { addComponentPlugin(debug, instance_, ecplugins.getComponentPlugins(), kernelContainer); } // check if component implement the ComponentLifecycle if (instance_ instanceof ComponentLifecycle) { ComponentLifecycle lc = (ComponentLifecycle) instance_; lc.initComponent(kernelContainer); } } catch (Exception ex) { String msg = "Cannot instantiate component " + getComponentImplementation(); if (component != null) { msg = "Cannot instantiate component key=" + component.getKey() + " type=" + component.getType() + " found at " + component.getDocumentURL(); } throw new RuntimeException(msg, ex); } return instance_; } /** * Executes the add ComponentPlugin or ExternalComponentPlugin into the current instance_. * @param debug * @param component * @param plugins * @param container * @throws Exception */ private void addComponentPlugin(boolean debug, Object component, List<org.etk.kernel.container.xml.ComponentPlugin> plugins, KernelContainer container) throws Exception { if (plugins == null) return; for (org.etk.kernel.container.xml.ComponentPlugin plugin : plugins) { try { Class clazz = Class.forName(plugin.getType()); ComponentPlugin cplugin = (ComponentPlugin) container.createComponent(clazz, plugin.getInitParams()); cplugin.setName(plugin.getName()); cplugin.setDescription(plugin.getDescription()); clazz = component.getClass(); Method m = getSetMethod(clazz, plugin.getSetMethod()); Object[] params = { cplugin }; m.invoke(component, params); if (debug) log.debug("==> add component plugin: " + cplugin); cplugin.setName(plugin.getName()); cplugin.setDescription(plugin.getDescription()); } catch (Exception ex) { log.error("Failed to instanciate plugin " + plugin.getName() + "for component " + component + ": " + ex.getMessage(), ex); } } } //TODO needs to improvement here for performance. private Method getSetMethod(Class clazz, String name) { //TODO Improvement here Method[] methods = clazz.getMethods(); for (Method m : methods) { if (name.equals(m.getName())) { Class[] types = m.getParameterTypes(); if (types != null && types.length == 1 && ComponentPlugin.class.isAssignableFrom(types[0])) { return m; } } } return null; } public void verify(PicoContainer container) { } }