package org.etk.kernel.container; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.etk.common.logging.Logger; import org.etk.common.utils.PropertyManager; import org.etk.kernel.container.configuration.ConfigurationManager; import org.etk.kernel.container.management.ManageableContainer; import org.etk.kernel.container.util.ContainerUtil; import org.etk.kernel.container.xml.Configuration; import org.etk.kernel.container.xml.InitParams; import org.picocontainer.PicoContainer; import org.picocontainer.defaults.ComponentAdapterFactory; public class KernelContainer extends ManageableContainer { /** * Serial Version UID */ private static final long serialVersionUID = -8068506531004854036L; /** * Returns an unmodifable set of profiles defined by the value returned by * invoking {@link PropertyManager#getProperty(String)} with the * {@link org.exoplatform.commons.utils.PropertyManager#RUNTIME_PROFILES} * property. * * @return the set of profiles */ public static Set<String> getProfiles() { // Set<String> profiles = new HashSet<String>(); // Obtain profile list by runtime properties String profileList = PropertyManager.getProperty(PropertyManager.RUNTIME_PROFILES); if (profileList != null) { for (String profile : profileList.split(",")) { profiles.add(profile.trim()); } } // return Collections.unmodifiableSet(profiles); } static Logger log = Logger.getLogger(KernelContainer.class); private Map<String, ComponentLifecyclePlugin> componentLifecylePlugin = new HashMap<String, ComponentLifecyclePlugin>(); private List<ContainerLifecyclePlugin> containerLifecyclePlugin_ = new ArrayList<ContainerLifecyclePlugin>(); protected KernelContainerContext context; protected PicoContainer parent; public KernelContainer() { context = new KernelContainerContext(this); context.setName(this.getClass().getName()); registerComponentInstance(context); this.parent = null; } public KernelContainer(PicoContainer parent) { super(parent); context = new KernelContainerContext(this); context.setName(this.getClass().getName()); registerComponentInstance(context); this.parent = parent; } public KernelContainer(ComponentAdapterFactory factory, PicoContainer parent) { super(factory, parent); context = new KernelContainerContext(this); context.setName(this.getClass().getName()); registerComponentInstance(context); this.parent = parent; } public KernelContainerContext getContext() { return context; } /** * @return the name of the plugin if it is not empty, the FQN of the plugin * otherwise */ private static String getPluginName(ContainerLifecyclePlugin plugin) { String name = plugin.getName(); if (name == null || name.length() == 0) { name = plugin.getClass().getName(); } return name; } /** * Explicit calls are not allowed anymore */ @Deprecated public void initContainer() throws Exception { } private void initContainerInternal() { ConfigurationManager manager = (ConfigurationManager) getComponentInstanceOfType(ConfigurationManager.class); ContainerUtil.addContainerLifecyclePlugin(this, manager); ContainerUtil.addComponentLifecyclePlugin(this, manager); for (ContainerLifecyclePlugin plugin : containerLifecyclePlugin_) { try { plugin.initContainer(this); } catch (Exception e) { log.warn("An error occurs with the ContainerLifecyclePlugin '" + getPluginName(plugin) + "'", e); } } ContainerUtil.addComponents(this, manager); } @Override public void dispose() { destroyContainerInternal(); super.dispose(); } /** * Starts the container * * @param init * indicates if the container must be initialized first */ public void start(boolean init) { if (init) { // Initialize the container first initContainerInternal(); } start(); } @Override public void start() { super.start(); startContainerInternal(); } @Override public void stop() { stopContainerInternal(); super.stop(); } /** * Explicit calls are not allowed anymore */ @Deprecated public void startContainer() throws Exception { } private void startContainerInternal() { for (ContainerLifecyclePlugin plugin : containerLifecyclePlugin_) { try { plugin.startContainer(this); } catch (Exception e) { log.warn("An error occurs with the ContainerLifecyclePlugin '" + getPluginName(plugin) + "'", e); } } } /** * Explicit calls are not allowed anymore */ @Deprecated public void stopContainer() throws Exception { } private void stopContainerInternal() { for (ContainerLifecyclePlugin plugin : containerLifecyclePlugin_) { try { plugin.stopContainer(this); } catch (Exception e) { log.warn("An error occurs with the ContainerLifecyclePlugin '" + getPluginName(plugin) + "'", e); } } } /** * Explicit calls are not allowed anymore */ @Deprecated public void destroyContainer() throws Exception { } private void destroyContainerInternal() { for (ContainerLifecyclePlugin plugin : containerLifecyclePlugin_) { try { plugin.destroyContainer(this); } catch (Exception e) { log.warn("An error occurs with the ContainerLifecyclePlugin '" + getPluginName(plugin) + "'", e); } } } public void addComponentLifecylePlugin(ComponentLifecyclePlugin plugin) { List<String> list = plugin.getManageableComponents(); for (String component : list) this.componentLifecylePlugin.put(component, plugin); } public void addContainerLifecylePlugin(ContainerLifecyclePlugin plugin) { containerLifecyclePlugin_.add(plugin); } public <T> T createComponent(Class<T> clazz) throws Exception { return createComponent(clazz, null); } public <T> T createComponent(Class<T> clazz, InitParams params) throws Exception { if (log.isDebugEnabled()) log.debug(clazz.getName() + " " + ((params != null) ? params : "") + " added to " + getContext().getName()); Constructor<?>[] constructors = new Constructor<?>[0]; try { constructors = ContainerUtil.getSortedConstructors(clazz); } catch (NoClassDefFoundError err) { throw new Exception("Cannot resolve constructor for class " + clazz.getName(), err); } Class<?> unknownParameter = null; for (int k = 0; k < constructors.length; k++) { Constructor<?> constructor = constructors[k]; Class<?>[] parameters = constructor.getParameterTypes(); Object[] args = new Object[parameters.length]; boolean satisfied = true; for (int i = 0; i < args.length; i++) { if (parameters[i].equals(InitParams.class)) { args[i] = params; } else { args[i] = getComponentInstanceOfType(parameters[i]); if (args[i] == null) { satisfied = false; unknownParameter = parameters[i]; break; } } } if (satisfied) return clazz.cast(constructor.newInstance(args)); } throw new Exception("Cannot find a satisfying constructor for " + clazz + " with parameter " + unknownParameter); } /** * Gets the {@link ConfigurationManager} from the given {@link ExoContainer} * if it exists, then returns the nested {@link Configuration} otherwise it * returns <code>null</code> */ protected Configuration getConfiguration() { ConfigurationManager cm = (ConfigurationManager) getComponentInstanceOfType(ConfigurationManager.class); return cm == null ? null : cm.getConfiguration(); } }