From 453b31f3f4de584df54a681adf41d273d9391080 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Fri, 2 Nov 2012 17:59:00 -0700 Subject: [PATCH] Refactor ComponentLocator to be based on Spring so that legacy way of loading component can coexist with Spring --- agent/src/com/cloud/agent/AgentShell.java | 4 +- agent/src/com/cloud/agent/VmmAgentShell.java | 4 +- .../AgentComponentLibraryBase.java | 2 +- server/src/com/cloud/test/DatabaseConfig.java | 12 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 1 + .../com/cloud/utils/component/Adapters.java | 2 +- .../utils/component/ComponentContext.java | 2 +- .../utils/component/ComponentLibrary.java | 2 +- .../utils/component/ComponentLibraryBase.java | 2 +- .../utils/component/ComponentLocator.java | 1271 +--------------- .../src/com/cloud/utils/component/Inject.java | 1 + .../component/LegacyComponentLocator.java | 1282 +++++++++++++++++ .../utils/component/MockComponentLocator.java | 2 +- .../utils/testcase/ComponentTestCase.java | 4 +- 14 files changed, 1324 insertions(+), 1267 deletions(-) mode change 100755 => 100644 utils/src/com/cloud/utils/component/ComponentLocator.java create mode 100755 utils/src/com/cloud/utils/component/LegacyComponentLocator.java diff --git a/agent/src/com/cloud/agent/AgentShell.java b/agent/src/com/cloud/agent/AgentShell.java index 05caf8e6cda..5d6a88c488a 100644 --- a/agent/src/com/cloud/agent/AgentShell.java +++ b/agent/src/com/cloud/agent/AgentShell.java @@ -53,7 +53,7 @@ import com.cloud.utils.PropertiesUtil; import com.cloud.utils.backoff.BackoffAlgorithm; import com.cloud.utils.backoff.impl.ConstantTimeBackoff; import com.cloud.utils.component.Adapters; -import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.LegacyComponentLocator; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; import com.cloud.utils.script.Script; @@ -374,7 +374,7 @@ public class AgentShell implements IAgentShell { public void init(String[] args) throws ConfigurationException { - final ComponentLocator locator = ComponentLocator.getLocator("agent"); + final LegacyComponentLocator locator = LegacyComponentLocator.getLocator("agent"); final Class c = this.getClass(); _version = c.getPackage().getImplementationVersion(); diff --git a/agent/src/com/cloud/agent/VmmAgentShell.java b/agent/src/com/cloud/agent/VmmAgentShell.java index ef2ef0f3279..ec2867940a2 100644 --- a/agent/src/com/cloud/agent/VmmAgentShell.java +++ b/agent/src/com/cloud/agent/VmmAgentShell.java @@ -46,7 +46,7 @@ import com.cloud.utils.PropertiesUtil; import com.cloud.utils.backoff.BackoffAlgorithm; import com.cloud.utils.backoff.impl.ConstantTimeBackoff; import com.cloud.utils.component.Adapters; -import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.LegacyComponentLocator; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.MacAddress; import com.cloud.utils.nio.HandlerFactory; @@ -317,7 +317,7 @@ public class VmmAgentShell implements IAgentShell, HandlerFactory { private void init(String[] args) throws ConfigurationException{ - final ComponentLocator locator = ComponentLocator.getLocator("agent"); + final LegacyComponentLocator locator = LegacyComponentLocator.getLocator("agent"); final Class c = this.getClass(); _version = c.getPackage().getImplementationVersion(); diff --git a/agent/src/com/cloud/agent/configuration/AgentComponentLibraryBase.java b/agent/src/com/cloud/agent/configuration/AgentComponentLibraryBase.java index 058aefa9252..4ea101c3951 100755 --- a/agent/src/com/cloud/agent/configuration/AgentComponentLibraryBase.java +++ b/agent/src/com/cloud/agent/configuration/AgentComponentLibraryBase.java @@ -21,7 +21,7 @@ import java.util.Map; import com.cloud.utils.component.Adapter; import com.cloud.utils.component.ComponentLibraryBase; -import com.cloud.utils.component.ComponentLocator.ComponentInfo; +import com.cloud.utils.component.LegacyComponentLocator.ComponentInfo; import com.cloud.utils.component.Manager; import com.cloud.utils.component.PluggableService; import com.cloud.utils.db.GenericDao; diff --git a/server/src/com/cloud/test/DatabaseConfig.java b/server/src/com/cloud/test/DatabaseConfig.java index 4e218701744..dfdea657532 100755 --- a/server/src/com/cloud/test/DatabaseConfig.java +++ b/server/src/com/cloud/test/DatabaseConfig.java @@ -54,7 +54,7 @@ import com.cloud.service.dao.ServiceOfferingDaoImpl; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDaoImpl; import com.cloud.utils.PropertiesUtil; -import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.LegacyComponentLocator; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.net.NfsUtils; @@ -76,10 +76,10 @@ public class DatabaseConfig { private static HashSet fieldNames = new HashSet(); // Maintain an IPRangeConfig object to handle IP related logic - private final IPRangeConfig iprc = ComponentLocator.inject(IPRangeConfig.class); + private final IPRangeConfig iprc = LegacyComponentLocator.inject(IPRangeConfig.class); // Maintain a PodZoneConfig object to handle Pod/Zone related logic - private final PodZoneConfig pzc = ComponentLocator.inject(PodZoneConfig.class); + private final PodZoneConfig pzc = LegacyComponentLocator.inject(PodZoneConfig.class); // Global variables to store network.throttling.rate and multicast.throttling.rate from the configuration table // Will be changed from null to a non-null value if the value existed in the configuration table @@ -359,7 +359,7 @@ public class DatabaseConfig { s_logger.error("error starting database config, missing initial data file"); } else { try { - DatabaseConfig config = ComponentLocator.inject(DatabaseConfig.class, args[0]); + DatabaseConfig config = LegacyComponentLocator.inject(DatabaseConfig.class, args[0]); config.doVersionCheck(); config.doConfig(); System.exit(0); @@ -918,7 +918,7 @@ public class DatabaseConfig { } ServiceOfferingVO serviceOffering = new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, ha, displayText, useLocalStorage, false, null, false, null, false); - ServiceOfferingDaoImpl dao = ComponentLocator.inject(ServiceOfferingDaoImpl.class); + ServiceOfferingDaoImpl dao = LegacyComponentLocator.inject(ServiceOfferingDaoImpl.class); try { dao.persist(serviceOffering); } catch (Exception e) { @@ -967,7 +967,7 @@ public class DatabaseConfig { } DiskOfferingVO diskOffering = new DiskOfferingVO(domainId, name, displayText, diskSpace , tags, false); diskOffering.setUseLocalStorage(local); - DiskOfferingDaoImpl offering = ComponentLocator.inject(DiskOfferingDaoImpl.class); + DiskOfferingDaoImpl offering = LegacyComponentLocator.inject(DiskOfferingDaoImpl.class); try { offering.persist(diskOffering); } catch (Exception e) { diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index b3c45eca9cc..6ec2ca64b63 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -95,6 +95,7 @@ public class MockNetworkManagerImpl implements NetworkManager, Manager{ NetworkServiceMapDao _ntwkSrvcDao; @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; + @com.cloud.utils.component.Inject(adapter = NetworkElement.class) Adapters _networkElements; diff --git a/utils/src/com/cloud/utils/component/Adapters.java b/utils/src/com/cloud/utils/component/Adapters.java index ecf5c4ce18c..00787da1f19 100755 --- a/utils/src/com/cloud/utils/component/Adapters.java +++ b/utils/src/com/cloud/utils/component/Adapters.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.Map; import com.cloud.utils.EnumerationImpl; -import com.cloud.utils.component.ComponentLocator.ComponentInfo; +import com.cloud.utils.component.LegacyComponentLocator.ComponentInfo; /** * the iterator even during dynamic reloading. diff --git a/utils/src/com/cloud/utils/component/ComponentContext.java b/utils/src/com/cloud/utils/component/ComponentContext.java index 6383509a303..a40fa71594d 100644 --- a/utils/src/com/cloud/utils/component/ComponentContext.java +++ b/utils/src/com/cloud/utils/component/ComponentContext.java @@ -45,7 +45,7 @@ public class ComponentContext implements ApplicationContextAware { return s_appContext; } - public static T getCompanent(String name) { + public static T getCompanent(String name) { assert(s_appContext != null); return (T)s_appContext.getBean(name); } diff --git a/utils/src/com/cloud/utils/component/ComponentLibrary.java b/utils/src/com/cloud/utils/component/ComponentLibrary.java index f20c1883954..52c470389c0 100755 --- a/utils/src/com/cloud/utils/component/ComponentLibrary.java +++ b/utils/src/com/cloud/utils/component/ComponentLibrary.java @@ -19,7 +19,7 @@ package com.cloud.utils.component; import java.util.List; import java.util.Map; -import com.cloud.utils.component.ComponentLocator.ComponentInfo; +import com.cloud.utils.component.LegacyComponentLocator.ComponentInfo; import com.cloud.utils.db.GenericDao; /** diff --git a/utils/src/com/cloud/utils/component/ComponentLibraryBase.java b/utils/src/com/cloud/utils/component/ComponentLibraryBase.java index 9a07778f7cf..58649e425d6 100644 --- a/utils/src/com/cloud/utils/component/ComponentLibraryBase.java +++ b/utils/src/com/cloud/utils/component/ComponentLibraryBase.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Map; import com.cloud.utils.Pair; -import com.cloud.utils.component.ComponentLocator.ComponentInfo; +import com.cloud.utils.component.LegacyComponentLocator.ComponentInfo; import com.cloud.utils.db.GenericDao; public abstract class ComponentLibraryBase implements ComponentLibrary { diff --git a/utils/src/com/cloud/utils/component/ComponentLocator.java b/utils/src/com/cloud/utils/component/ComponentLocator.java old mode 100755 new mode 100644 index 23c37eced1b..571daa10a77 --- a/utils/src/com/cloud/utils/component/ComponentLocator.java +++ b/utils/src/com/cloud/utils/component/ComponentLocator.java @@ -16,1267 +16,40 @@ // under the License. package com.cloud.utils.component; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import javax.ejb.Local; -import javax.inject.Inject; -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.naming.ConfigurationException; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import org.springframework.stereotype.Component; -import net.sf.cglib.proxy.Callback; -import net.sf.cglib.proxy.CallbackFilter; -import net.sf.cglib.proxy.Enhancer; -import net.sf.cglib.proxy.Factory; -import net.sf.cglib.proxy.MethodInterceptor; -import net.sf.cglib.proxy.MethodProxy; -import net.sf.cglib.proxy.NoOp; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; -import org.apache.log4j.xml.DOMConfigurator; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import com.cloud.utils.Pair; -import com.cloud.utils.PropertiesUtil; -import com.cloud.utils.db.DatabaseCallback; -import com.cloud.utils.db.DatabaseCallbackFilter; import com.cloud.utils.db.GenericDao; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.mgmt.JmxUtil; -import com.cloud.utils.mgmt.ManagementBean; -/** - * ComponentLocator ties together several different concepts. First, it - * deals with how a system should be put together. It manages different - * types of components: - * - Manager: Singleton implementation of a certain process. - * - Adapter: Different singleton implementations for the same functions. - * - SystemIntegrityChecker: Singletons that are called at the load time. - * - Dao: Data Access Objects. - * - * These components can be declared in several ways: - * - ComponentLibrary - A Java class that declares the above components. The - * advantage of declaring components here is they change automatically - * with any refactoring. - * - components specification - An xml file that overrides the - * ComponentLibrary. The advantage of declaring components here is - * they can change by hand on every deployment. - * - * The two are NOT mutually exclusive. ComponentLocator basically locates - * the components specification, which specifies the ComponentLibrary within. - * Components found in the ComponentLibrary are overridden by components - * found in components specification. - * - * Components specification can also be nested. One components specification - * can point to another components specification and, therefore, "inherits" - * those components but still override one or more components. ComponentLocator - * reads the child components specification first and follow the chain up. - * the child's components overrides the ones in the parent. - * - * ComponentLocator looks for the components specification as follows: - * 1. By following the path specified by "cloud-stack-components-specification" - * within the environment.properties file. - * 2. Look for components.xml in the class path. - * - * ComponentLocator also ties in component injection. Components can specify - * an @Inject annotation to components ComponentLocator knows. When - * instantiating components, ComponentLocator attempts to inject these - * components. - * - **/ -@SuppressWarnings("unchecked") -public class ComponentLocator implements ComponentLocatorMBean { - protected static final Logger s_logger = Logger.getLogger(ComponentLocator.class); - - protected static final ThreadLocal s_tl = new ThreadLocal(); - protected static final ConcurrentHashMap, Singleton> s_singletons = new ConcurrentHashMap, Singleton>(111); - protected static final HashMap s_locators = new HashMap(); - protected static final HashMap, InjectInfo> s_factories = new HashMap, InjectInfo>(); - protected static Boolean s_once = false; - protected static Boolean _hasCheckerRun = false; - protected static Callback[] s_callbacks = new Callback[] { NoOp.INSTANCE, new DatabaseCallback()}; - protected static CallbackFilter s_callbackFilter = new DatabaseCallbackFilter(); - protected static final List> s_interceptors = new ArrayList>(); - protected static CleanupThread s_janitor = null; - - protected HashMap> _adapterMap; - protected HashMap> _managerMap; - protected LinkedHashMap> _checkerMap; - protected LinkedHashMap>> _daoMap; - protected String _serverName; - protected Object _component; - protected HashMap, Class> _factories; - protected HashMap> _pluginsMap; - - static { - if (s_janitor == null) { - s_janitor = new CleanupThread(); - Runtime.getRuntime().addShutdownHook(new CleanupThread()); - } - } - - public ComponentLocator(String server) { - _serverName = server; - if (s_janitor == null) { - s_janitor = new CleanupThread(); - Runtime.getRuntime().addShutdownHook(new CleanupThread()); - } - } - - public String getLocatorName() { - return _serverName; - } - - @Override - public String getName() { - return getLocatorName(); - } - - protected Pair>>> parse2(String filename) { - try { - SAXParserFactory spfactory = SAXParserFactory.newInstance(); - SAXParser saxParser = spfactory.newSAXParser(); - _daoMap = new LinkedHashMap>>(); - _managerMap = new LinkedHashMap>(); - _checkerMap = new LinkedHashMap>(); - _adapterMap = new HashMap>(); - _factories = new HashMap, Class>(); - _pluginsMap = new LinkedHashMap>(); - File file = PropertiesUtil.findConfigFile(filename); - if (file == null) { - s_logger.info("Unable to find " + filename); - return null; - } - s_logger.info("Config file found at " + file.getAbsolutePath() + ". Configuring " + _serverName); - XmlHandler handler = new XmlHandler(_serverName); - saxParser.parse(file, handler); - - HashMap>> adapters = new HashMap>>(); - if (handler.parent != null) { - String[] tokens = handler.parent.split(":"); - String parentFile = filename; - String parentName = handler.parent; - if (tokens.length > 1) { - parentFile = tokens[0]; - parentName = tokens[1]; - } - ComponentLocator parentLocator = new ComponentLocator(parentName); - adapters.putAll(parentLocator.parse2(parentFile).second()); - _daoMap.putAll(parentLocator._daoMap); - _managerMap.putAll(parentLocator._managerMap); - _factories.putAll(parentLocator._factories); - _pluginsMap.putAll(parentLocator._pluginsMap); - } - - ComponentLibrary library = null; - if (handler.library != null) { - Class clazz = Class.forName(handler.library); - library = (ComponentLibrary)clazz.newInstance(); - _daoMap.putAll(library.getDaos()); - _managerMap.putAll(library.getManagers()); - adapters.putAll(library.getAdapters()); - _factories.putAll(library.getFactories()); - _pluginsMap.putAll(library.getPluggableServices()); - } - - _daoMap.putAll(handler.daos); - _managerMap.putAll(handler.managers); - _checkerMap.putAll(handler.checkers); - adapters.putAll(handler.adapters); - _pluginsMap.putAll(handler.pluggableServices); - - return new Pair>>>(handler, adapters); - } catch (ParserConfigurationException e) { - s_logger.error("Unable to load " + _serverName + " due to errors while parsing " + filename, e); - System.exit(1); - } catch (SAXException e) { - s_logger.error("Unable to load " + _serverName + " due to errors while parsing " + filename, e); - System.exit(1); - } catch (IOException e) { - s_logger.error("Unable to load " + _serverName + " due to errors while reading from " + filename, e); - System.exit(1); - } catch (CloudRuntimeException e) { - s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); - System.exit(1); - } catch (Exception e) { - s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); - System.exit(1); - } - return null; - } - - protected void parse(String filename) { - Pair>>> result = parse2(filename); - if (result == null) { - s_logger.info("Skipping configuration using " + filename); - return; - } - - instantiatePluggableServices(); - - XmlHandler handler = result.first(); - HashMap>> adapters = result.second(); - try { - runCheckers(); - startDaos(); // daos should not be using managers and adapters. - instantiateAdapters(adapters); - instantiateManagers(); - if (handler.componentClass != null) { - _component = createInstance(handler.componentClass, true, true); - } - configureManagers(); - configureAdapters(); - startManagers(); - startAdapters(); - //TODO do we need to follow the instantiate -> inject -> configure -> start -> stop flow of singletons like managers/adapters? - //TODO do we need to expose pluggableServices to MBean (provide getNames?) - } catch (CloudRuntimeException e) { - s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); - System.exit(1); - } catch (Exception e) { - s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); - System.exit(1); - } - } - - protected void runCheckers() { - Set>> entries = _checkerMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - try { - info.instance = (SystemIntegrityChecker)createInstance(info.clazz, false, info.singleton); - info.instance.check(); - } catch (Exception e) { - s_logger.error("Problems with running checker:" + info.name, e); - System.exit(1); - } - } - } - /** - * Daos should not refer to any other components so it is safe to start them - * here. - */ - protected void startDaos() { - Set>>> entries = _daoMap.entrySet(); - - for (Map.Entry>> entry : entries) { - ComponentInfo> info = entry.getValue(); - try { - info.instance = (GenericDao)createInstance(info.clazz, true, info.singleton); - if (info.singleton) { - s_logger.info("Starting singleton DAO: " + info.name); - Singleton singleton = s_singletons.get(info.clazz); - if (singleton.state == Singleton.State.Instantiated) { - inject(info.clazz, info.instance); - singleton.state = Singleton.State.Injected; - } - if (singleton.state == Singleton.State.Injected) { - if (!info.instance.configure(info.name, info.params)) { - s_logger.error("Unable to configure DAO: " + info.name); - System.exit(1); - } - singleton.state = Singleton.State.Started; - } - } else { - s_logger.info("Starting DAO: " + info.name); - inject(info.clazz, info.instance); - if (!info.instance.configure(info.name, info.params)) { - s_logger.error("Unable to configure DAO: " + info.name); - System.exit(1); - } - } - } catch (ConfigurationException e) { - s_logger.error("Unable to configure DAO: " + info.name, e); - System.exit(1); - } catch (Exception e) { - s_logger.error("Problems while configuring DAO: " + info.name, e); - System.exit(1); - } - if (info.instance instanceof ManagementBean) { - registerMBean((ManagementBean) info.instance); - } - } - } - - private static Object createInstance(Class clazz, boolean inject, boolean singleton, Object... args) { - Factory factory = null; - Singleton entity = null; - synchronized(s_factories) { - if (singleton) { - entity = s_singletons.get(clazz); - if (entity != null) { - s_logger.debug("Found singleton instantiation for " + clazz.toString()); - return entity.singleton; - } - } - InjectInfo info = s_factories.get(clazz); - if (info == null) { - Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(clazz); - enhancer.setCallbackFilter(s_callbackFilter); - enhancer.setCallbacks(s_callbacks); - factory = (Factory)enhancer.create(); - info = new InjectInfo(enhancer, factory); - s_factories.put(clazz, info); - } else { - factory = info.factory; - } - } - - - Class[] argTypes = null; - if (args != null && args.length > 0) { - Constructor[] constructors = clazz.getConstructors(); - for (Constructor constructor : constructors) { - Class[] paramTypes = constructor.getParameterTypes(); - if (paramTypes.length == args.length) { - boolean found = true; - for (int i = 0; i < paramTypes.length; i++) { - if (!paramTypes[i].isAssignableFrom(args[i].getClass()) && !paramTypes[i].isPrimitive()) { - found = false; - break; - } - } - if (found) { - argTypes = paramTypes; - break; - } - } - } - - if (argTypes == null) { - throw new CloudRuntimeException("Unable to find constructor to match parameters given: " + clazz.getName()); - } - - entity = new Singleton(factory.newInstance(argTypes, args, s_callbacks)); - } else { - entity = new Singleton(factory.newInstance(s_callbacks)); - } - - if (inject) { - inject(clazz, entity.singleton); - entity.state = Singleton.State.Injected; - } - - if (singleton) { - synchronized(s_factories) { - s_singletons.put(clazz, entity); - } - } - - return entity.singleton; - } - - - protected ComponentInfo> getDao(String name) { - ComponentInfo> info = _daoMap.get(name); - if (info == null) { - throw new CloudRuntimeException("Unable to find DAO " + name); - } - - return info; - } - - public static synchronized Object getComponent(String componentName) { - synchronized(_hasCheckerRun) { - /* System Integrity checker will run before all components really loaded */ - if (!_hasCheckerRun && !componentName.equalsIgnoreCase(SystemIntegrityChecker.Name)) { - ComponentLocator.getComponent(SystemIntegrityChecker.Name); - _hasCheckerRun = true; - } - } - - ComponentLocator locator = s_locators.get(componentName); - if (locator == null) { - locator = ComponentLocator.getLocator(componentName); - } - return locator._component; - } - - public > T getDao(Class clazz) { - ComponentInfo> info = getDao(clazz.getName()); - return info != null ? (T)info.instance : null; - } - - protected void instantiateManagers() { - Set>> entries = _managerMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.instance == null) { - s_logger.info("Instantiating Manager: " + info.name); - info.instance = (Manager)createInstance(info.clazz, false, info.singleton); - } - } - } - - protected void configureManagers() { - Set>> entries = _managerMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.singleton) { - Singleton s = s_singletons.get(info.clazz); - if (s.state == Singleton.State.Instantiated) { - s_logger.debug("Injecting singleton Manager: " + info.name); - inject(info.clazz, info.instance); - s.state = Singleton.State.Injected; - } - } else { - s_logger.info("Injecting Manager: " + info.name); - inject(info.clazz, info.instance); - } - } - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.singleton) { - Singleton s = s_singletons.get(info.clazz); - if (s.state == Singleton.State.Injected) { - s_logger.info("Configuring singleton Manager: " + info.name); - try { - info.instance.configure(info.name, info.params); - } catch (ConfigurationException e) { - s_logger.error("Unable to configure manager: " + info.name, e); - System.exit(1); - } - s.state = Singleton.State.Configured; - } - } else { - s_logger.info("Configuring Manager: " + info.name); - try { - info.instance.configure(info.name, info.params); - } catch (ConfigurationException e) { - s_logger.error("Unable to configure manager: " + info.name, e); - System.exit(1); - } - } - } - } - - protected static void inject(Class clazz, Object entity) { - ComponentLocator locator = ComponentLocator.getCurrentLocator(); - - do { - Field[] fields = clazz.getDeclaredFields(); - for (Field field : fields) { - Inject inject = field.getAnnotation(Inject.class); - if (inject == null) { - com.cloud.utils.component.Inject oldInject = field.getAnnotation(com.cloud.utils.component.Inject.class); - if(inject != null) { - Class fc = field.getType(); - Object instance = null; - if (Manager.class.isAssignableFrom(fc)) { - s_logger.trace("Manager: " + fc.getName()); - instance = locator.getManager(fc); - } else if (GenericDao.class.isAssignableFrom(fc)) { - s_logger.trace("Dao:" + fc.getName()); - instance = locator.getDao((Class>)fc); - } else if (Adapters.class.isAssignableFrom(fc)) { - s_logger.trace("Adapter" + fc.getName()); - instance = locator.getAdapters(oldInject.adapter()); - } else { - s_logger.trace("Other:" + fc.getName()); - instance = locator.getManager(fc); - } - } - - continue; - } - - Class fc = field.getType(); - Object instance = null; - if (Manager.class.isAssignableFrom(fc)) { - s_logger.trace("Manager: " + fc.getName()); - instance = locator.getManager(fc); - } else if (GenericDao.class.isAssignableFrom(fc)) { - s_logger.trace("Dao:" + fc.getName()); - instance = locator.getDao((Class>)fc); - } else { - s_logger.trace("Other:" + fc.getName()); - instance = locator.getManager(fc); - } - - if (instance == null) { - throw new CloudRuntimeException("Unable to inject " + fc.getSimpleName() + " in " + clazz.getSimpleName()); - } - - try { - field.setAccessible(true); - field.set(entity, instance); - } catch (IllegalArgumentException e) { - throw new CloudRuntimeException("hmmm....is it really illegal?", e); - } catch (IllegalAccessException e) { - throw new CloudRuntimeException("what! what ! what!", e); - } - } - clazz = clazz.getSuperclass(); - } while (clazz != Object.class && clazz != null); - } - - protected void startManagers() { - Set>> entries = _managerMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.singleton) { - Singleton s = s_singletons.get(info.clazz); - if (s.state == Singleton.State.Configured) { - s_logger.info("Starting singleton Manager: " + info.name); - if (!info.instance.start()) { - throw new CloudRuntimeException("Incorrect Configuration: " + info.name); - } - if (info.instance instanceof ManagementBean) { - registerMBean((ManagementBean) info.instance); - } - s_logger.info("Started Manager: " + info.name); - s.state = Singleton.State.Started; - } - } else { - s_logger.info("Starting Manager: " + info.name); - if (!info.instance.start()) { - throw new CloudRuntimeException("Incorrect Configuration: " + info.name); - } - if (info.instance instanceof ManagementBean) { - registerMBean((ManagementBean) info.instance); - } - s_logger.info("Started Manager: " + info.name); - } - } - } - - protected void registerMBean(ManagementBean mbean) { - try { - JmxUtil.registerMBean(mbean); - } catch (MalformedObjectNameException e) { - s_logger.warn("Unable to register MBean: " + mbean.getName(), e); - } catch (InstanceAlreadyExistsException e) { - s_logger.warn("Unable to register MBean: " + mbean.getName(), e); - } catch (MBeanRegistrationException e) { - s_logger.warn("Unable to register MBean: " + mbean.getName(), e); - } catch (NotCompliantMBeanException e) { - s_logger.warn("Unable to register MBean: " + mbean.getName(), e); - } - s_logger.info("Registered MBean: " + mbean.getName()); - } - - protected ComponentInfo getManager(String name) { - ComponentInfo mgr = _managerMap.get(name); - return mgr; - } - - public T getManager(Class clazz) { - ComponentInfo info = getManager(clazz.getName()); - if (info == null) { - return null; - } - if (info.instance == null) { - info.instance = (Manager)createInstance(info.clazz, false, info.singleton); - } - return (T)info.instance; - } - - protected void configureAdapters() { - for (Adapters adapters : _adapterMap.values()) { - List> infos = adapters._infos; - for (ComponentInfo info : infos) { - try { - if (info.singleton) { - Singleton singleton = s_singletons.get(info.clazz); - if (singleton.state == Singleton.State.Instantiated) { - s_logger.info("Injecting singleton Adapter: " + info.getName()); - inject(info.clazz, info.instance); - singleton.state = Singleton.State.Injected; - } - if (singleton.state == Singleton.State.Injected) { - s_logger.info("Configuring singleton Adapter: " + info.getName()); - if (!info.instance.configure(info.name, info.params)) { - s_logger.error("Unable to configure adapter: " + info.name); - System.exit(1); - } - singleton.state = Singleton.State.Configured; - } - } else { - s_logger.info("Injecting Adapter: " + info.getName()); - inject(info.clazz, info.instance); - s_logger.info("Configuring singleton Adapter: " + info.getName()); - if (!info.instance.configure(info.name, info.params)) { - s_logger.error("Unable to configure adapter: " + info.name); - System.exit(1); - } - } - } catch (ConfigurationException e) { - s_logger.error("Unable to configure adapter: " + info.name, e); - System.exit(1); - } catch (Exception e) { - s_logger.error("Unable to configure adapter: " + info.name, e); - System.exit(1); - } - } - } - } - - protected void populateAdapters(Map>> map) { - Set>>> entries = map.entrySet(); - for (Map.Entry>> entry : entries) { - for (ComponentInfo info : entry.getValue()) { - s_logger.info("Instantiating Adapter: " + info.name); - info.instance = (Adapter)createInstance(info.clazz, false, info.singleton); - } - Adapters adapters = new Adapters(entry.getKey(), entry.getValue()); - _adapterMap.put(entry.getKey(), adapters); - } - } - - protected void instantiateAdapters(Map>> map) { - Set>>> entries = map.entrySet(); - for (Map.Entry>> entry : entries) { - for (ComponentInfo info : entry.getValue()) { - s_logger.info("Instantiating Adapter: " + info.name); - info.instance = (Adapter)createInstance(info.clazz, false, info.singleton); - } - Adapters adapters = new Adapters(entry.getKey(), entry.getValue()); - _adapterMap.put(entry.getKey(), adapters); - } - } - - protected void startAdapters() { - for (Map.Entry> entry : _adapterMap.entrySet()) { - for (ComponentInfo adapter : entry.getValue()._infos) { - if (adapter.singleton) { - Singleton s = s_singletons.get(adapter.clazz); - if (s.state == Singleton.State.Configured) { - s_logger.info("Starting singleton Adapter: " + adapter.getName()); - if (!adapter.instance.start()) { - throw new CloudRuntimeException("Unable to start adapter: " + adapter.getName()); - } - if (adapter.instance instanceof ManagementBean) { - registerMBean((ManagementBean)adapter.instance); - } - s_logger.info("Started Adapter: " + adapter.instance.getName()); - } - s.state = Singleton.State.Started; - } else { - s_logger.info("Starting Adapter: " + adapter.getName()); - if (!adapter.instance.start()) { - throw new CloudRuntimeException("Unable to start adapter: " + adapter.getName()); - } - if (adapter.instance instanceof ManagementBean) { - registerMBean((ManagementBean)adapter.instance); - } - s_logger.info("Started Adapter: " + adapter.instance.getName()); - } - } - } - } - - protected void instantiatePluggableServices() { - Set>> entries = _pluginsMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.instance == null) { - s_logger.info("Instantiating PluggableService: " + info.name); - info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); - - if (info.instance instanceof Plugin) { - Plugin plugin = (Plugin)info.instance; - - ComponentLibrary lib = plugin.getComponentLibrary(); - _managerMap.putAll(lib.getManagers()); - _daoMap.putAll(lib.getDaos()); - } - } - } - } - - protected ComponentInfo getPluggableService(String name) { - ComponentInfo mgr = _pluginsMap.get(name); - return mgr; - } - - public T getPluggableService(Class clazz) { - ComponentInfo info = getPluggableService(clazz.getName()); - if (info == null) { - return null; - } - if (info.instance == null) { - info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); - } - return (T)info.instance; - } - - public List getAllPluggableServices() { - List services = new ArrayList(); - Set>> entries = _pluginsMap.entrySet(); - for (Map.Entry> entry : entries) { - ComponentInfo info = entry.getValue(); - if (info.instance == null) { - s_logger.info("Instantiating PluggableService: " + info.name); - info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); - } - services.add((T) info.instance); - } - return services; - } - - public static T inject(Class clazz) { - return (T)createInstance(clazz, true, false); - } - - public T createInstance(Class clazz) { - Class impl = (Class)_factories.get(clazz); - if (impl == null) { - throw new CloudRuntimeException("Unable to find a factory for " + clazz); - } - return inject(impl); - } - - public static T inject(Class clazz, Object... args) { - return (T)createInstance(clazz, true, false, args); - } - - @Override - public Map> getAdapterNames() { - HashMap> result = new HashMap>(); - for (Map.Entry> entry : _adapterMap.entrySet()) { - Adapters adapters = entry.getValue(); - Enumeration en = adapters.enumeration(); - List lst = new ArrayList(); - while (en.hasMoreElements()) { - Adapter adapter = en.nextElement(); - lst.add(adapter.getName() + "-" + adapter.getClass().getName()); - } - result.put(entry.getKey(), lst); - } - return result; - } - - public Map> getAllAccessibleAdapters() { - Map> parentResults = new HashMap>(); - Map> results = getAdapterNames(); - parentResults.putAll(results); - return parentResults; - } - - @Override - public Collection getManagerNames() { - Collection names = new HashSet(); - for (Map.Entry> entry : _managerMap.entrySet()) { - names.add(entry.getValue().name); - } - return names; - } - - @Override - public Collection getDaoNames() { - Collection names = new HashSet(); - for (Map.Entry>> entry : _daoMap.entrySet()) { - names.add(entry.getValue().name); - } - return names; - } - - public Adapters getAdapters(Class clazz) { - return (Adapters)getAdapters(clazz.getName()); - } - - public Adapters getAdapters(String key) { - Adapters adapters = _adapterMap.get(key); - if (adapters != null) { - return adapters; - } - return new Adapters(key, new ArrayList>()); - } - - protected void resetInterceptors(InterceptorLibrary library) { - library.addInterceptors(s_interceptors); - if (s_interceptors.size() > 0) { - s_callbacks = new Callback[s_interceptors.size() + 2]; - int i = 0; - s_callbacks[i++] = NoOp.INSTANCE; - s_callbacks[i++] = new InterceptorDispatcher(); - for (AnnotationInterceptor interceptor : s_interceptors) { - s_callbacks[i++] = interceptor.getCallback(); - } - s_callbackFilter = new InterceptorFilter(); - } - } - - protected static ComponentLocator getLocatorInternal(String server, boolean setInThreadLocal, String configFileName, String log4jFilename) { - synchronized(s_once) { - if (!s_once) { - File file = PropertiesUtil.findConfigFile(log4jFilename + ".xml"); - if (file != null) { - s_logger.info("log4j configuration found at " + file.getAbsolutePath()); - DOMConfigurator.configureAndWatch(file.getAbsolutePath()); - } else { - file = PropertiesUtil.findConfigFile(log4jFilename + ".properties"); - if (file != null) { - s_logger.info("log4j configuration found at " + file.getAbsolutePath()); - PropertyConfigurator.configureAndWatch(file.getAbsolutePath()); - } - } - s_once = true; - } - } - - ComponentLocator locator; - synchronized (s_locators) { - locator = s_locators.get(server); - if (locator == null) { - locator = new ComponentLocator(server); - s_locators.put(server, locator); - if (setInThreadLocal) { - s_tl.set(locator); - } - locator.parse(configFileName); - } else { - if (setInThreadLocal) { - s_tl.set(locator); - } - } - } - - return locator; - } - - public static ComponentLocator getLocator(String server, String configFileName, String log4jFilename) { - return getLocatorInternal(server, true, configFileName, log4jFilename); - } - - public static ComponentLocator getLocator(String server) { - String configFile = null; - try { - final File propsFile = PropertiesUtil.findConfigFile("environment.properties"); - if (propsFile == null) { - s_logger.debug("environment.properties could not be opened"); - } else { - final FileInputStream finputstream = new FileInputStream(propsFile); - final Properties props = new Properties(); - props.load(finputstream); - finputstream.close(); - configFile = props.getProperty("cloud-stack-components-specification"); - } - } catch (IOException e) { - s_logger.debug("environment.properties could not be loaded:" + e.toString()); - } - - if (configFile == null || PropertiesUtil.findConfigFile(configFile) == null) { - configFile = "components.xml"; - if (PropertiesUtil.findConfigFile(configFile) == null){ - s_logger.debug("Can not find components.xml"); - } - } - return getLocatorInternal(server, true, configFile, "log4j-cloud"); - } +@Component +public class ComponentLocator { public static ComponentLocator getCurrentLocator() { - return s_tl.get(); + return ComponentContext.getCompanent(ComponentLocator.class); } - - public static class ComponentInfo { - Class clazz; - HashMap params = new HashMap(); - String name; - List keys = new ArrayList(); - T instance; - boolean singleton = true; - - protected ComponentInfo() { - } - - public List getKeys() { - return keys; - } - - public String getName() { - return name; - } - - public ComponentInfo(String name, Class clazz) { - this(name, clazz, new ArrayList>(0)); - } - - public ComponentInfo(String name, Class clazz, T instance) { - this(name, clazz); - this.instance = instance; - } - - public ComponentInfo(String name, Class clazz, List> params) { - this(name, clazz, params, true); - } - - public ComponentInfo(String name, Class clazz, List> params, boolean singleton) { - this.name = name; - this.clazz = clazz; - this.singleton = singleton; - for (Pair param : params) { - this.params.put(param.first(), param.second()); - } - fillInfo(); - } - - protected void fillInfo() { - String clazzName = clazz.getName(); - - Local local = clazz.getAnnotation(Local.class); - if (local == null) { - throw new CloudRuntimeException("Unable to find Local annotation for class " + clazzName); - } - - // Verify that all interfaces specified in the Local annotation is implemented by the class. - Class[] classes = local.value(); - for (int i = 0; i < classes.length; i++) { - if (!classes[i].isInterface()) { - throw new CloudRuntimeException(classes[i].getName() + " is not an interface"); - } - if (classes[i].isAssignableFrom(clazz)) { - keys.add(classes[i].getName()); - s_logger.info("Found component: " + classes[i].getName() + " in " + clazzName + " - " + name); - } else { - throw new CloudRuntimeException(classes[i].getName() + " is not implemented by " + clazzName); - } - } - } - - public void addParameter(String name, String value) { - params.put(name, value); - } + + public static ComponentLocator getLocator(String server) { + return ComponentContext.getCompanent(ComponentLocator.class); } - - /** - * XmlHandler is used by AdapterManager to handle the SAX parser callbacks. - * It builds a hash map of lists of adapters and a hash map of managers. - **/ - protected class XmlHandler extends DefaultHandler { - public HashMap>> adapters; - public HashMap> managers; - public LinkedHashMap> checkers; - public LinkedHashMap>> daos; - public HashMap> pluggableServices; - public String parent; - public String library; - - List> lst; - String paramName; - StringBuilder value; - String serverName; - boolean parse; - ComponentInfo currentInfo; - Class componentClass; - - public XmlHandler(String serverName) { - this.serverName = serverName; - parse = false; - adapters = new HashMap>>(); - managers = new HashMap>(); - checkers = new LinkedHashMap>(); - daos = new LinkedHashMap>>(); - pluggableServices = new HashMap>(); - value = null; - parent = null; - } - - protected void fillInfo(Attributes atts, Class interphace, ComponentInfo info) { - String clazzName = getAttribute(atts, "class"); - if (clazzName == null) { - throw new CloudRuntimeException("Missing class attribute for " + interphace.getName()); - } - info.name = getAttribute(atts, "name"); - if (info.name == null) { - throw new CloudRuntimeException("Missing name attribute for " + interphace.getName()); - } - s_logger.debug("Looking for class " + clazzName); - try { - info.clazz = Class.forName(clazzName); - } catch (ClassNotFoundException e) { - throw new CloudRuntimeException("Unable to find class: " + clazzName); - } catch (Throwable e) { - throw new CloudRuntimeException("Caught throwable: ", e); - } - - if (!interphace.isAssignableFrom(info.clazz)) { - throw new CloudRuntimeException("Class " + info.clazz.toString() + " does not implment " + interphace); - } - String singleton = getAttribute(atts, "singleton"); - if (singleton != null) { - info.singleton = Boolean.parseBoolean(singleton); - } - - info.fillInfo(); - } - - @Override - public void startElement(String namespaceURI, String localName, String qName, Attributes atts) - throws SAXException { - if (qName.equals("interceptor") && s_interceptors.size() == 0) { - synchronized(s_interceptors){ - if (s_interceptors.size() == 0) { - String libraryName = getAttribute(atts, "library"); - try { - Class libraryClazz = Class.forName(libraryName); - InterceptorLibrary library = (InterceptorLibrary)libraryClazz.newInstance(); - resetInterceptors(library); - } catch (ClassNotFoundException e) { - throw new CloudRuntimeException("Unable to find " + libraryName, e); - } catch (InstantiationException e) { - throw new CloudRuntimeException("Unable to instantiate " + libraryName, e); - } catch (IllegalAccessException e) { - throw new CloudRuntimeException("Illegal access " + libraryName, e); - } - } - } - } - if (!parse) { - if (qName.equals(_serverName)) { - parse = true; - parent = getAttribute(atts, "extends"); - String implementationClass = getAttribute(atts, "class"); - if (implementationClass != null) { - try { - componentClass = Class.forName(implementationClass); - } catch (ClassNotFoundException e) { - throw new CloudRuntimeException("Unable to find " + implementationClass, e); - } - } - - library = getAttribute(atts, "library"); - } - } else if (qName.equals("adapters")) { - lst = new ArrayList>(); - String key = getAttribute(atts, "key"); - if (key == null) { - throw new CloudRuntimeException("Missing key attribute for adapters"); - } - adapters.put(key, lst); - } else if (qName.equals("adapter")) { - ComponentInfo info = new ComponentInfo(); - fillInfo(atts, Adapter.class, info); - lst.add(info); - currentInfo = info; - } else if (qName.equals("manager")) { - ComponentInfo info = new ComponentInfo(); - fillInfo(atts, Manager.class, info); - s_logger.info("Adding Manager: " + info.name); - for (String key : info.keys) { - s_logger.info("Linking " + key + " to " + info.name); - managers.put(key, info); - } - currentInfo = info; - } else if (qName.equals("param")) { - paramName = getAttribute(atts, "name"); - value = new StringBuilder(); - } else if (qName.equals("dao")) { - ComponentInfo> info = new ComponentInfo>(); - fillInfo(atts, GenericDao.class, info); - for (String key : info.keys) { - daos.put(key, info); - } - currentInfo = info; - } else if (qName.equals("checker")) { - ComponentInfo info = new ComponentInfo(); - fillInfo(atts, SystemIntegrityChecker.class, info); - checkers.put(info.name, info); - s_logger.info("Adding system integrity checker: " + info.name); - currentInfo = info; - } else if (qName.equals("pluggableservice") || qName.equals("plugin")) { - ComponentInfo info = new ComponentInfo(); - fillInfo(atts, PluggableService.class, info); - s_logger.info("Adding PluggableService: " + info.name); - String key = getAttribute(atts, "key"); - if (key == null) { - throw new CloudRuntimeException("Missing key attribute for pluggableservice: "+info.name); - } - s_logger.info("Linking " + key + " to " + info.name); - pluggableServices.put(key, info); - currentInfo = info; - } else { - // ignore - } - } - - protected String getAttribute(Attributes atts, String name) { - for (int att = 0; att < atts.getLength(); att++) { - String attName = atts.getQName(att); - if (attName.equals(name)) { - return atts.getValue(att); - } - } - return null; - } - - @Override - public void endElement(String namespaceURI, String localName, String qName) throws SAXException { - if (!parse) { - return; - } - - if (qName.equals(_serverName)) { - parse = false; - } else if (qName.equals("adapters")) { - } else if (qName.equals("adapter")) { - } else if (qName.equals("manager")) { - } else if (qName.equals("dao")) { - } else if (qName.equals("pluggableservice")) { - } else if (qName.equals("param")) { - currentInfo.params.put(paramName, value.toString()); - paramName = null; - value = null; - } else { - // ignore - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - if (parse && value != null) { - value.append(ch, start, length); - } - } + + public static Object getComponent(String componentName) { + return ComponentContext.getCompanent(componentName); } - - protected static class InjectInfo { - public Factory factory; - public Enhancer enhancer; - - public InjectInfo(Enhancer enhancer, Factory factory) { - this.factory = factory; - this.enhancer = enhancer; - } + + public > T getDao(Class clazz) { + return ComponentContext.getCompanent(clazz); } - - protected static class CleanupThread extends Thread { - @Override - public void run() { - synchronized (CleanupThread.class) { - for (ComponentLocator locator : s_locators.values()) { - Iterator> itAdapters = locator._adapterMap.values().iterator(); - while (itAdapters.hasNext()) { - Adapters adapters = itAdapters.next(); - itAdapters.remove(); - for (ComponentInfo adapter : adapters._infos) { - if (adapter.singleton) { - Singleton singleton = s_singletons.get(adapter.clazz); - if (singleton.state == Singleton.State.Started) { - s_logger.info("Asking " + adapter.getName() + " to shutdown."); - adapter.instance.stop(); - singleton.state = Singleton.State.Stopped; - } else { - s_logger.debug("Skippng " + adapter.getName() + " because it has already stopped"); - } - } else { - s_logger.info("Asking " + adapter.getName() + " to shutdown."); - adapter.instance.stop(); - } - } - } - } - - for (ComponentLocator locator : s_locators.values()) { - Iterator> itManagers = locator._managerMap.values().iterator(); - while (itManagers.hasNext()) { - ComponentInfo manager = itManagers.next(); - itManagers.remove(); - if (manager.singleton == true) { - Singleton singleton = s_singletons.get(manager.clazz); - if (singleton != null && singleton.state == Singleton.State.Started) { - s_logger.info("Asking Manager " + manager.getName() + " to shutdown."); - manager.instance.stop(); - singleton.state = Singleton.State.Stopped; - } else { - s_logger.info("Skipping Manager " + manager.getName() + " because it is not in a state to shutdown."); - } - } - } - } - } - } + + public T getManager(Class clazz) { + return ComponentContext.getCompanent(clazz); } - - static class Singleton { - public enum State { - Instantiated, - Injected, - Configured, - Started, - Stopped - } - - public Object singleton; - public State state; - - public Singleton(Object singleton) { - this.singleton = singleton; - this.state = State.Instantiated; - } + + public T getPluggableService(Class clazz) { + return ComponentContext.getCompanent(clazz); } - - protected class InterceptorDispatcher implements MethodInterceptor { - - @Override - public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { - ArrayList, Object>> interceptors = new ArrayList, Object>>(); - for (AnnotationInterceptor interceptor : s_interceptors) { - if (interceptor.needToIntercept(method)) { - Object obj = interceptor.interceptStart(method); - interceptors.add(new Pair, Object>((AnnotationInterceptor)interceptor, obj)); - } - } - boolean success = false; - try { - Object obj = methodProxy.invokeSuper(object, args); - success = true; - return obj; - } finally { - for (Pair, Object> interceptor : interceptors) { - if (success) { - interceptor.first().interceptComplete(method, interceptor.second()); - } else { - interceptor.first().interceptException(method, interceptor.second()); - } - } - } - } - } - - protected static class InterceptorFilter implements CallbackFilter { - @Override - public int accept(Method method) { - int index = 0; - for (int i = 2; i < s_callbacks.length; i++) { - AnnotationInterceptor interceptor = (AnnotationInterceptor)s_callbacks[i]; - if (interceptor.needToIntercept(method)) { - if (index == 0) { - index = i; - } else { - return 1; - } - } - } - - return index; - } + + public static T inject(Class clazz) { + return ComponentContext.inject(clazz); } } diff --git a/utils/src/com/cloud/utils/component/Inject.java b/utils/src/com/cloud/utils/component/Inject.java index 6711591c8cd..50c890da75b 100644 --- a/utils/src/com/cloud/utils/component/Inject.java +++ b/utils/src/com/cloud/utils/component/Inject.java @@ -27,3 +27,4 @@ import java.lang.annotation.Target; public @interface Inject { Class adapter() default Adapter.class; } + diff --git a/utils/src/com/cloud/utils/component/LegacyComponentLocator.java b/utils/src/com/cloud/utils/component/LegacyComponentLocator.java new file mode 100755 index 00000000000..719f5601456 --- /dev/null +++ b/utils/src/com/cloud/utils/component/LegacyComponentLocator.java @@ -0,0 +1,1282 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.utils.component; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.MalformedObjectNameException; +import javax.management.NotCompliantMBeanException; +import javax.naming.ConfigurationException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.CallbackFilter; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.Factory; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; +import net.sf.cglib.proxy.NoOp; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.xml.DOMConfigurator; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.cloud.utils.Pair; +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.db.DatabaseCallback; +import com.cloud.utils.db.DatabaseCallbackFilter; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.mgmt.JmxUtil; +import com.cloud.utils.mgmt.ManagementBean; + +/** + * ComponentLocator ties together several different concepts. First, it + * deals with how a system should be put together. It manages different + * types of components: + * - Manager: Singleton implementation of a certain process. + * - Adapter: Different singleton implementations for the same functions. + * - SystemIntegrityChecker: Singletons that are called at the load time. + * - Dao: Data Access Objects. + * + * These components can be declared in several ways: + * - ComponentLibrary - A Java class that declares the above components. The + * advantage of declaring components here is they change automatically + * with any refactoring. + * - components specification - An xml file that overrides the + * ComponentLibrary. The advantage of declaring components here is + * they can change by hand on every deployment. + * + * The two are NOT mutually exclusive. ComponentLocator basically locates + * the components specification, which specifies the ComponentLibrary within. + * Components found in the ComponentLibrary are overridden by components + * found in components specification. + * + * Components specification can also be nested. One components specification + * can point to another components specification and, therefore, "inherits" + * those components but still override one or more components. ComponentLocator + * reads the child components specification first and follow the chain up. + * the child's components overrides the ones in the parent. + * + * ComponentLocator looks for the components specification as follows: + * 1. By following the path specified by "cloud-stack-components-specification" + * within the environment.properties file. + * 2. Look for components.xml in the class path. + * + * ComponentLocator also ties in component injection. Components can specify + * an @Inject annotation to components ComponentLocator knows. When + * instantiating components, ComponentLocator attempts to inject these + * components. + * + **/ +@SuppressWarnings("unchecked") +public class LegacyComponentLocator implements ComponentLocatorMBean { + protected static final Logger s_logger = Logger.getLogger(LegacyComponentLocator.class); + + protected static final ThreadLocal s_tl = new ThreadLocal(); + protected static final ConcurrentHashMap, Singleton> s_singletons = new ConcurrentHashMap, Singleton>(111); + protected static final HashMap s_locators = new HashMap(); + protected static final HashMap, InjectInfo> s_factories = new HashMap, InjectInfo>(); + protected static Boolean s_once = false; + protected static Boolean _hasCheckerRun = false; + protected static Callback[] s_callbacks = new Callback[] { NoOp.INSTANCE, new DatabaseCallback()}; + protected static CallbackFilter s_callbackFilter = new DatabaseCallbackFilter(); + protected static final List> s_interceptors = new ArrayList>(); + protected static CleanupThread s_janitor = null; + + protected HashMap> _adapterMap; + protected HashMap> _managerMap; + protected LinkedHashMap> _checkerMap; + protected LinkedHashMap>> _daoMap; + protected String _serverName; + protected Object _component; + protected HashMap, Class> _factories; + protected HashMap> _pluginsMap; + + static { + if (s_janitor == null) { + s_janitor = new CleanupThread(); + Runtime.getRuntime().addShutdownHook(new CleanupThread()); + } + } + + public LegacyComponentLocator(String server) { + _serverName = server; + if (s_janitor == null) { + s_janitor = new CleanupThread(); + Runtime.getRuntime().addShutdownHook(new CleanupThread()); + } + } + + public String getLocatorName() { + return _serverName; + } + + @Override + public String getName() { + return getLocatorName(); + } + + protected Pair>>> parse2(String filename) { + try { + SAXParserFactory spfactory = SAXParserFactory.newInstance(); + SAXParser saxParser = spfactory.newSAXParser(); + _daoMap = new LinkedHashMap>>(); + _managerMap = new LinkedHashMap>(); + _checkerMap = new LinkedHashMap>(); + _adapterMap = new HashMap>(); + _factories = new HashMap, Class>(); + _pluginsMap = new LinkedHashMap>(); + File file = PropertiesUtil.findConfigFile(filename); + if (file == null) { + s_logger.info("Unable to find " + filename); + return null; + } + s_logger.info("Config file found at " + file.getAbsolutePath() + ". Configuring " + _serverName); + XmlHandler handler = new XmlHandler(_serverName); + saxParser.parse(file, handler); + + HashMap>> adapters = new HashMap>>(); + if (handler.parent != null) { + String[] tokens = handler.parent.split(":"); + String parentFile = filename; + String parentName = handler.parent; + if (tokens.length > 1) { + parentFile = tokens[0]; + parentName = tokens[1]; + } + LegacyComponentLocator parentLocator = new LegacyComponentLocator(parentName); + adapters.putAll(parentLocator.parse2(parentFile).second()); + _daoMap.putAll(parentLocator._daoMap); + _managerMap.putAll(parentLocator._managerMap); + _factories.putAll(parentLocator._factories); + _pluginsMap.putAll(parentLocator._pluginsMap); + } + + ComponentLibrary library = null; + if (handler.library != null) { + Class clazz = Class.forName(handler.library); + library = (ComponentLibrary)clazz.newInstance(); + _daoMap.putAll(library.getDaos()); + _managerMap.putAll(library.getManagers()); + adapters.putAll(library.getAdapters()); + _factories.putAll(library.getFactories()); + _pluginsMap.putAll(library.getPluggableServices()); + } + + _daoMap.putAll(handler.daos); + _managerMap.putAll(handler.managers); + _checkerMap.putAll(handler.checkers); + adapters.putAll(handler.adapters); + _pluginsMap.putAll(handler.pluggableServices); + + return new Pair>>>(handler, adapters); + } catch (ParserConfigurationException e) { + s_logger.error("Unable to load " + _serverName + " due to errors while parsing " + filename, e); + System.exit(1); + } catch (SAXException e) { + s_logger.error("Unable to load " + _serverName + " due to errors while parsing " + filename, e); + System.exit(1); + } catch (IOException e) { + s_logger.error("Unable to load " + _serverName + " due to errors while reading from " + filename, e); + System.exit(1); + } catch (CloudRuntimeException e) { + s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); + System.exit(1); + } catch (Exception e) { + s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); + System.exit(1); + } + return null; + } + + protected void parse(String filename) { + Pair>>> result = parse2(filename); + if (result == null) { + s_logger.info("Skipping configuration using " + filename); + return; + } + + instantiatePluggableServices(); + + XmlHandler handler = result.first(); + HashMap>> adapters = result.second(); + try { + runCheckers(); + startDaos(); // daos should not be using managers and adapters. + instantiateAdapters(adapters); + instantiateManagers(); + if (handler.componentClass != null) { + _component = createInstance(handler.componentClass, true, true); + } + configureManagers(); + configureAdapters(); + startManagers(); + startAdapters(); + //TODO do we need to follow the instantiate -> inject -> configure -> start -> stop flow of singletons like managers/adapters? + //TODO do we need to expose pluggableServices to MBean (provide getNames?) + } catch (CloudRuntimeException e) { + s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); + System.exit(1); + } catch (Exception e) { + s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e); + System.exit(1); + } + } + + protected void runCheckers() { + Set>> entries = _checkerMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + try { + info.instance = (SystemIntegrityChecker)createInstance(info.clazz, false, info.singleton); + info.instance.check(); + } catch (Exception e) { + s_logger.error("Problems with running checker:" + info.name, e); + System.exit(1); + } + } + } + /** + * Daos should not refer to any other components so it is safe to start them + * here. + */ + protected void startDaos() { + Set>>> entries = _daoMap.entrySet(); + + for (Map.Entry>> entry : entries) { + ComponentInfo> info = entry.getValue(); + try { + info.instance = (GenericDao)createInstance(info.clazz, true, info.singleton); + if (info.singleton) { + s_logger.info("Starting singleton DAO: " + info.name); + Singleton singleton = s_singletons.get(info.clazz); + if (singleton.state == Singleton.State.Instantiated) { + inject(info.clazz, info.instance); + singleton.state = Singleton.State.Injected; + } + if (singleton.state == Singleton.State.Injected) { + if (!info.instance.configure(info.name, info.params)) { + s_logger.error("Unable to configure DAO: " + info.name); + System.exit(1); + } + singleton.state = Singleton.State.Started; + } + } else { + s_logger.info("Starting DAO: " + info.name); + inject(info.clazz, info.instance); + if (!info.instance.configure(info.name, info.params)) { + s_logger.error("Unable to configure DAO: " + info.name); + System.exit(1); + } + } + } catch (ConfigurationException e) { + s_logger.error("Unable to configure DAO: " + info.name, e); + System.exit(1); + } catch (Exception e) { + s_logger.error("Problems while configuring DAO: " + info.name, e); + System.exit(1); + } + if (info.instance instanceof ManagementBean) { + registerMBean((ManagementBean) info.instance); + } + } + } + + private static Object createInstance(Class clazz, boolean inject, boolean singleton, Object... args) { + Factory factory = null; + Singleton entity = null; + synchronized(s_factories) { + if (singleton) { + entity = s_singletons.get(clazz); + if (entity != null) { + s_logger.debug("Found singleton instantiation for " + clazz.toString()); + return entity.singleton; + } + } + InjectInfo info = s_factories.get(clazz); + if (info == null) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(clazz); + enhancer.setCallbackFilter(s_callbackFilter); + enhancer.setCallbacks(s_callbacks); + factory = (Factory)enhancer.create(); + info = new InjectInfo(enhancer, factory); + s_factories.put(clazz, info); + } else { + factory = info.factory; + } + } + + + Class[] argTypes = null; + if (args != null && args.length > 0) { + Constructor[] constructors = clazz.getConstructors(); + for (Constructor constructor : constructors) { + Class[] paramTypes = constructor.getParameterTypes(); + if (paramTypes.length == args.length) { + boolean found = true; + for (int i = 0; i < paramTypes.length; i++) { + if (!paramTypes[i].isAssignableFrom(args[i].getClass()) && !paramTypes[i].isPrimitive()) { + found = false; + break; + } + } + if (found) { + argTypes = paramTypes; + break; + } + } + } + + if (argTypes == null) { + throw new CloudRuntimeException("Unable to find constructor to match parameters given: " + clazz.getName()); + } + + entity = new Singleton(factory.newInstance(argTypes, args, s_callbacks)); + } else { + entity = new Singleton(factory.newInstance(s_callbacks)); + } + + if (inject) { + inject(clazz, entity.singleton); + entity.state = Singleton.State.Injected; + } + + if (singleton) { + synchronized(s_factories) { + s_singletons.put(clazz, entity); + } + } + + return entity.singleton; + } + + + protected ComponentInfo> getDao(String name) { + ComponentInfo> info = _daoMap.get(name); + if (info == null) { + throw new CloudRuntimeException("Unable to find DAO " + name); + } + + return info; + } + + public static synchronized Object getComponent(String componentName) { + synchronized(_hasCheckerRun) { + /* System Integrity checker will run before all components really loaded */ + if (!_hasCheckerRun && !componentName.equalsIgnoreCase(SystemIntegrityChecker.Name)) { + LegacyComponentLocator.getComponent(SystemIntegrityChecker.Name); + _hasCheckerRun = true; + } + } + + LegacyComponentLocator locator = s_locators.get(componentName); + if (locator == null) { + locator = LegacyComponentLocator.getLocator(componentName); + } + return locator._component; + } + + public > T getDao(Class clazz) { + ComponentInfo> info = getDao(clazz.getName()); + return info != null ? (T)info.instance : null; + } + + protected void instantiateManagers() { + Set>> entries = _managerMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.instance == null) { + s_logger.info("Instantiating Manager: " + info.name); + info.instance = (Manager)createInstance(info.clazz, false, info.singleton); + } + } + } + + protected void configureManagers() { + Set>> entries = _managerMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.singleton) { + Singleton s = s_singletons.get(info.clazz); + if (s.state == Singleton.State.Instantiated) { + s_logger.debug("Injecting singleton Manager: " + info.name); + inject(info.clazz, info.instance); + s.state = Singleton.State.Injected; + } + } else { + s_logger.info("Injecting Manager: " + info.name); + inject(info.clazz, info.instance); + } + } + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.singleton) { + Singleton s = s_singletons.get(info.clazz); + if (s.state == Singleton.State.Injected) { + s_logger.info("Configuring singleton Manager: " + info.name); + try { + info.instance.configure(info.name, info.params); + } catch (ConfigurationException e) { + s_logger.error("Unable to configure manager: " + info.name, e); + System.exit(1); + } + s.state = Singleton.State.Configured; + } + } else { + s_logger.info("Configuring Manager: " + info.name); + try { + info.instance.configure(info.name, info.params); + } catch (ConfigurationException e) { + s_logger.error("Unable to configure manager: " + info.name, e); + System.exit(1); + } + } + } + } + + protected static void inject(Class clazz, Object entity) { + LegacyComponentLocator locator = LegacyComponentLocator.getCurrentLocator(); + + do { + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + Inject inject = field.getAnnotation(Inject.class); + if (inject == null) { + com.cloud.utils.component.Inject oldInject = field.getAnnotation(com.cloud.utils.component.Inject.class); + if(inject != null) { + Class fc = field.getType(); + Object instance = null; + if (Manager.class.isAssignableFrom(fc)) { + s_logger.trace("Manager: " + fc.getName()); + instance = locator.getManager(fc); + } else if (GenericDao.class.isAssignableFrom(fc)) { + s_logger.trace("Dao:" + fc.getName()); + instance = locator.getDao((Class>)fc); + } else if (Adapters.class.isAssignableFrom(fc)) { + s_logger.trace("Adapter" + fc.getName()); + instance = locator.getAdapters(oldInject.adapter()); + } else { + s_logger.trace("Other:" + fc.getName()); + instance = locator.getManager(fc); + } + } + + continue; + } + + Class fc = field.getType(); + Object instance = null; + if (Manager.class.isAssignableFrom(fc)) { + s_logger.trace("Manager: " + fc.getName()); + instance = locator.getManager(fc); + } else if (GenericDao.class.isAssignableFrom(fc)) { + s_logger.trace("Dao:" + fc.getName()); + instance = locator.getDao((Class>)fc); + } else { + s_logger.trace("Other:" + fc.getName()); + instance = locator.getManager(fc); + } + + if (instance == null) { + throw new CloudRuntimeException("Unable to inject " + fc.getSimpleName() + " in " + clazz.getSimpleName()); + } + + try { + field.setAccessible(true); + field.set(entity, instance); + } catch (IllegalArgumentException e) { + throw new CloudRuntimeException("hmmm....is it really illegal?", e); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("what! what ! what!", e); + } + } + clazz = clazz.getSuperclass(); + } while (clazz != Object.class && clazz != null); + } + + protected void startManagers() { + Set>> entries = _managerMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.singleton) { + Singleton s = s_singletons.get(info.clazz); + if (s.state == Singleton.State.Configured) { + s_logger.info("Starting singleton Manager: " + info.name); + if (!info.instance.start()) { + throw new CloudRuntimeException("Incorrect Configuration: " + info.name); + } + if (info.instance instanceof ManagementBean) { + registerMBean((ManagementBean) info.instance); + } + s_logger.info("Started Manager: " + info.name); + s.state = Singleton.State.Started; + } + } else { + s_logger.info("Starting Manager: " + info.name); + if (!info.instance.start()) { + throw new CloudRuntimeException("Incorrect Configuration: " + info.name); + } + if (info.instance instanceof ManagementBean) { + registerMBean((ManagementBean) info.instance); + } + s_logger.info("Started Manager: " + info.name); + } + } + } + + protected void registerMBean(ManagementBean mbean) { + try { + JmxUtil.registerMBean(mbean); + } catch (MalformedObjectNameException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (InstanceAlreadyExistsException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (MBeanRegistrationException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } catch (NotCompliantMBeanException e) { + s_logger.warn("Unable to register MBean: " + mbean.getName(), e); + } + s_logger.info("Registered MBean: " + mbean.getName()); + } + + protected ComponentInfo getManager(String name) { + ComponentInfo mgr = _managerMap.get(name); + return mgr; + } + + public T getManager(Class clazz) { + ComponentInfo info = getManager(clazz.getName()); + if (info == null) { + return null; + } + if (info.instance == null) { + info.instance = (Manager)createInstance(info.clazz, false, info.singleton); + } + return (T)info.instance; + } + + protected void configureAdapters() { + for (Adapters adapters : _adapterMap.values()) { + List> infos = adapters._infos; + for (ComponentInfo info : infos) { + try { + if (info.singleton) { + Singleton singleton = s_singletons.get(info.clazz); + if (singleton.state == Singleton.State.Instantiated) { + s_logger.info("Injecting singleton Adapter: " + info.getName()); + inject(info.clazz, info.instance); + singleton.state = Singleton.State.Injected; + } + if (singleton.state == Singleton.State.Injected) { + s_logger.info("Configuring singleton Adapter: " + info.getName()); + if (!info.instance.configure(info.name, info.params)) { + s_logger.error("Unable to configure adapter: " + info.name); + System.exit(1); + } + singleton.state = Singleton.State.Configured; + } + } else { + s_logger.info("Injecting Adapter: " + info.getName()); + inject(info.clazz, info.instance); + s_logger.info("Configuring singleton Adapter: " + info.getName()); + if (!info.instance.configure(info.name, info.params)) { + s_logger.error("Unable to configure adapter: " + info.name); + System.exit(1); + } + } + } catch (ConfigurationException e) { + s_logger.error("Unable to configure adapter: " + info.name, e); + System.exit(1); + } catch (Exception e) { + s_logger.error("Unable to configure adapter: " + info.name, e); + System.exit(1); + } + } + } + } + + protected void populateAdapters(Map>> map) { + Set>>> entries = map.entrySet(); + for (Map.Entry>> entry : entries) { + for (ComponentInfo info : entry.getValue()) { + s_logger.info("Instantiating Adapter: " + info.name); + info.instance = (Adapter)createInstance(info.clazz, false, info.singleton); + } + Adapters adapters = new Adapters(entry.getKey(), entry.getValue()); + _adapterMap.put(entry.getKey(), adapters); + } + } + + protected void instantiateAdapters(Map>> map) { + Set>>> entries = map.entrySet(); + for (Map.Entry>> entry : entries) { + for (ComponentInfo info : entry.getValue()) { + s_logger.info("Instantiating Adapter: " + info.name); + info.instance = (Adapter)createInstance(info.clazz, false, info.singleton); + } + Adapters adapters = new Adapters(entry.getKey(), entry.getValue()); + _adapterMap.put(entry.getKey(), adapters); + } + } + + protected void startAdapters() { + for (Map.Entry> entry : _adapterMap.entrySet()) { + for (ComponentInfo adapter : entry.getValue()._infos) { + if (adapter.singleton) { + Singleton s = s_singletons.get(adapter.clazz); + if (s.state == Singleton.State.Configured) { + s_logger.info("Starting singleton Adapter: " + adapter.getName()); + if (!adapter.instance.start()) { + throw new CloudRuntimeException("Unable to start adapter: " + adapter.getName()); + } + if (adapter.instance instanceof ManagementBean) { + registerMBean((ManagementBean)adapter.instance); + } + s_logger.info("Started Adapter: " + adapter.instance.getName()); + } + s.state = Singleton.State.Started; + } else { + s_logger.info("Starting Adapter: " + adapter.getName()); + if (!adapter.instance.start()) { + throw new CloudRuntimeException("Unable to start adapter: " + adapter.getName()); + } + if (adapter.instance instanceof ManagementBean) { + registerMBean((ManagementBean)adapter.instance); + } + s_logger.info("Started Adapter: " + adapter.instance.getName()); + } + } + } + } + + protected void instantiatePluggableServices() { + Set>> entries = _pluginsMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.instance == null) { + s_logger.info("Instantiating PluggableService: " + info.name); + info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); + + if (info.instance instanceof Plugin) { + Plugin plugin = (Plugin)info.instance; + + ComponentLibrary lib = plugin.getComponentLibrary(); + _managerMap.putAll(lib.getManagers()); + _daoMap.putAll(lib.getDaos()); + } + } + } + } + + protected ComponentInfo getPluggableService(String name) { + ComponentInfo mgr = _pluginsMap.get(name); + return mgr; + } + + public T getPluggableService(Class clazz) { + ComponentInfo info = getPluggableService(clazz.getName()); + if (info == null) { + return null; + } + if (info.instance == null) { + info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); + } + return (T)info.instance; + } + + public List getAllPluggableServices() { + List services = new ArrayList(); + Set>> entries = _pluginsMap.entrySet(); + for (Map.Entry> entry : entries) { + ComponentInfo info = entry.getValue(); + if (info.instance == null) { + s_logger.info("Instantiating PluggableService: " + info.name); + info.instance = (PluggableService)createInstance(info.clazz, false, info.singleton); + } + services.add((T) info.instance); + } + return services; + } + + public static T inject(Class clazz) { + return (T)createInstance(clazz, true, false); + } + + public T createInstance(Class clazz) { + Class impl = (Class)_factories.get(clazz); + if (impl == null) { + throw new CloudRuntimeException("Unable to find a factory for " + clazz); + } + return inject(impl); + } + + public static T inject(Class clazz, Object... args) { + return (T)createInstance(clazz, true, false, args); + } + + @Override + public Map> getAdapterNames() { + HashMap> result = new HashMap>(); + for (Map.Entry> entry : _adapterMap.entrySet()) { + Adapters adapters = entry.getValue(); + Enumeration en = adapters.enumeration(); + List lst = new ArrayList(); + while (en.hasMoreElements()) { + Adapter adapter = en.nextElement(); + lst.add(adapter.getName() + "-" + adapter.getClass().getName()); + } + result.put(entry.getKey(), lst); + } + return result; + } + + public Map> getAllAccessibleAdapters() { + Map> parentResults = new HashMap>(); + Map> results = getAdapterNames(); + parentResults.putAll(results); + return parentResults; + } + + @Override + public Collection getManagerNames() { + Collection names = new HashSet(); + for (Map.Entry> entry : _managerMap.entrySet()) { + names.add(entry.getValue().name); + } + return names; + } + + @Override + public Collection getDaoNames() { + Collection names = new HashSet(); + for (Map.Entry>> entry : _daoMap.entrySet()) { + names.add(entry.getValue().name); + } + return names; + } + + public Adapters getAdapters(Class clazz) { + return (Adapters)getAdapters(clazz.getName()); + } + + public Adapters getAdapters(String key) { + Adapters adapters = _adapterMap.get(key); + if (adapters != null) { + return adapters; + } + return new Adapters(key, new ArrayList>()); + } + + protected void resetInterceptors(InterceptorLibrary library) { + library.addInterceptors(s_interceptors); + if (s_interceptors.size() > 0) { + s_callbacks = new Callback[s_interceptors.size() + 2]; + int i = 0; + s_callbacks[i++] = NoOp.INSTANCE; + s_callbacks[i++] = new InterceptorDispatcher(); + for (AnnotationInterceptor interceptor : s_interceptors) { + s_callbacks[i++] = interceptor.getCallback(); + } + s_callbackFilter = new InterceptorFilter(); + } + } + + protected static LegacyComponentLocator getLocatorInternal(String server, boolean setInThreadLocal, String configFileName, String log4jFilename) { + synchronized(s_once) { + if (!s_once) { + File file = PropertiesUtil.findConfigFile(log4jFilename + ".xml"); + if (file != null) { + s_logger.info("log4j configuration found at " + file.getAbsolutePath()); + DOMConfigurator.configureAndWatch(file.getAbsolutePath()); + } else { + file = PropertiesUtil.findConfigFile(log4jFilename + ".properties"); + if (file != null) { + s_logger.info("log4j configuration found at " + file.getAbsolutePath()); + PropertyConfigurator.configureAndWatch(file.getAbsolutePath()); + } + } + s_once = true; + } + } + + LegacyComponentLocator locator; + synchronized (s_locators) { + locator = s_locators.get(server); + if (locator == null) { + locator = new LegacyComponentLocator(server); + s_locators.put(server, locator); + if (setInThreadLocal) { + s_tl.set(locator); + } + locator.parse(configFileName); + } else { + if (setInThreadLocal) { + s_tl.set(locator); + } + } + } + + return locator; + } + + public static LegacyComponentLocator getLocator(String server, String configFileName, String log4jFilename) { + return getLocatorInternal(server, true, configFileName, log4jFilename); + } + + public static LegacyComponentLocator getLocator(String server) { + String configFile = null; + try { + final File propsFile = PropertiesUtil.findConfigFile("environment.properties"); + if (propsFile == null) { + s_logger.debug("environment.properties could not be opened"); + } else { + final FileInputStream finputstream = new FileInputStream(propsFile); + final Properties props = new Properties(); + props.load(finputstream); + finputstream.close(); + configFile = props.getProperty("cloud-stack-components-specification"); + } + } catch (IOException e) { + s_logger.debug("environment.properties could not be loaded:" + e.toString()); + } + + if (configFile == null || PropertiesUtil.findConfigFile(configFile) == null) { + configFile = "components.xml"; + if (PropertiesUtil.findConfigFile(configFile) == null){ + s_logger.debug("Can not find components.xml"); + } + } + return getLocatorInternal(server, true, configFile, "log4j-cloud"); + } + + public static LegacyComponentLocator getCurrentLocator() { + return s_tl.get(); + } + + public static class ComponentInfo { + Class clazz; + HashMap params = new HashMap(); + String name; + List keys = new ArrayList(); + T instance; + boolean singleton = true; + + protected ComponentInfo() { + } + + public List getKeys() { + return keys; + } + + public String getName() { + return name; + } + + public ComponentInfo(String name, Class clazz) { + this(name, clazz, new ArrayList>(0)); + } + + public ComponentInfo(String name, Class clazz, T instance) { + this(name, clazz); + this.instance = instance; + } + + public ComponentInfo(String name, Class clazz, List> params) { + this(name, clazz, params, true); + } + + public ComponentInfo(String name, Class clazz, List> params, boolean singleton) { + this.name = name; + this.clazz = clazz; + this.singleton = singleton; + for (Pair param : params) { + this.params.put(param.first(), param.second()); + } + fillInfo(); + } + + protected void fillInfo() { + String clazzName = clazz.getName(); + + Local local = clazz.getAnnotation(Local.class); + if (local == null) { + throw new CloudRuntimeException("Unable to find Local annotation for class " + clazzName); + } + + // Verify that all interfaces specified in the Local annotation is implemented by the class. + Class[] classes = local.value(); + for (int i = 0; i < classes.length; i++) { + if (!classes[i].isInterface()) { + throw new CloudRuntimeException(classes[i].getName() + " is not an interface"); + } + if (classes[i].isAssignableFrom(clazz)) { + keys.add(classes[i].getName()); + s_logger.info("Found component: " + classes[i].getName() + " in " + clazzName + " - " + name); + } else { + throw new CloudRuntimeException(classes[i].getName() + " is not implemented by " + clazzName); + } + } + } + + public void addParameter(String name, String value) { + params.put(name, value); + } + } + + /** + * XmlHandler is used by AdapterManager to handle the SAX parser callbacks. + * It builds a hash map of lists of adapters and a hash map of managers. + **/ + protected class XmlHandler extends DefaultHandler { + public HashMap>> adapters; + public HashMap> managers; + public LinkedHashMap> checkers; + public LinkedHashMap>> daos; + public HashMap> pluggableServices; + public String parent; + public String library; + + List> lst; + String paramName; + StringBuilder value; + String serverName; + boolean parse; + ComponentInfo currentInfo; + Class componentClass; + + public XmlHandler(String serverName) { + this.serverName = serverName; + parse = false; + adapters = new HashMap>>(); + managers = new HashMap>(); + checkers = new LinkedHashMap>(); + daos = new LinkedHashMap>>(); + pluggableServices = new HashMap>(); + value = null; + parent = null; + } + + protected void fillInfo(Attributes atts, Class interphace, ComponentInfo info) { + String clazzName = getAttribute(atts, "class"); + if (clazzName == null) { + throw new CloudRuntimeException("Missing class attribute for " + interphace.getName()); + } + info.name = getAttribute(atts, "name"); + if (info.name == null) { + throw new CloudRuntimeException("Missing name attribute for " + interphace.getName()); + } + s_logger.debug("Looking for class " + clazzName); + try { + info.clazz = Class.forName(clazzName); + } catch (ClassNotFoundException e) { + throw new CloudRuntimeException("Unable to find class: " + clazzName); + } catch (Throwable e) { + throw new CloudRuntimeException("Caught throwable: ", e); + } + + if (!interphace.isAssignableFrom(info.clazz)) { + throw new CloudRuntimeException("Class " + info.clazz.toString() + " does not implment " + interphace); + } + String singleton = getAttribute(atts, "singleton"); + if (singleton != null) { + info.singleton = Boolean.parseBoolean(singleton); + } + + info.fillInfo(); + } + + @Override + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) + throws SAXException { + if (qName.equals("interceptor") && s_interceptors.size() == 0) { + synchronized(s_interceptors){ + if (s_interceptors.size() == 0) { + String libraryName = getAttribute(atts, "library"); + try { + Class libraryClazz = Class.forName(libraryName); + InterceptorLibrary library = (InterceptorLibrary)libraryClazz.newInstance(); + resetInterceptors(library); + } catch (ClassNotFoundException e) { + throw new CloudRuntimeException("Unable to find " + libraryName, e); + } catch (InstantiationException e) { + throw new CloudRuntimeException("Unable to instantiate " + libraryName, e); + } catch (IllegalAccessException e) { + throw new CloudRuntimeException("Illegal access " + libraryName, e); + } + } + } + } + if (!parse) { + if (qName.equals(_serverName)) { + parse = true; + parent = getAttribute(atts, "extends"); + String implementationClass = getAttribute(atts, "class"); + if (implementationClass != null) { + try { + componentClass = Class.forName(implementationClass); + } catch (ClassNotFoundException e) { + throw new CloudRuntimeException("Unable to find " + implementationClass, e); + } + } + + library = getAttribute(atts, "library"); + } + } else if (qName.equals("adapters")) { + lst = new ArrayList>(); + String key = getAttribute(atts, "key"); + if (key == null) { + throw new CloudRuntimeException("Missing key attribute for adapters"); + } + adapters.put(key, lst); + } else if (qName.equals("adapter")) { + ComponentInfo info = new ComponentInfo(); + fillInfo(atts, Adapter.class, info); + lst.add(info); + currentInfo = info; + } else if (qName.equals("manager")) { + ComponentInfo info = new ComponentInfo(); + fillInfo(atts, Manager.class, info); + s_logger.info("Adding Manager: " + info.name); + for (String key : info.keys) { + s_logger.info("Linking " + key + " to " + info.name); + managers.put(key, info); + } + currentInfo = info; + } else if (qName.equals("param")) { + paramName = getAttribute(atts, "name"); + value = new StringBuilder(); + } else if (qName.equals("dao")) { + ComponentInfo> info = new ComponentInfo>(); + fillInfo(atts, GenericDao.class, info); + for (String key : info.keys) { + daos.put(key, info); + } + currentInfo = info; + } else if (qName.equals("checker")) { + ComponentInfo info = new ComponentInfo(); + fillInfo(atts, SystemIntegrityChecker.class, info); + checkers.put(info.name, info); + s_logger.info("Adding system integrity checker: " + info.name); + currentInfo = info; + } else if (qName.equals("pluggableservice") || qName.equals("plugin")) { + ComponentInfo info = new ComponentInfo(); + fillInfo(atts, PluggableService.class, info); + s_logger.info("Adding PluggableService: " + info.name); + String key = getAttribute(atts, "key"); + if (key == null) { + throw new CloudRuntimeException("Missing key attribute for pluggableservice: "+info.name); + } + s_logger.info("Linking " + key + " to " + info.name); + pluggableServices.put(key, info); + currentInfo = info; + } else { + // ignore + } + } + + protected String getAttribute(Attributes atts, String name) { + for (int att = 0; att < atts.getLength(); att++) { + String attName = atts.getQName(att); + if (attName.equals(name)) { + return atts.getValue(att); + } + } + return null; + } + + @Override + public void endElement(String namespaceURI, String localName, String qName) throws SAXException { + if (!parse) { + return; + } + + if (qName.equals(_serverName)) { + parse = false; + } else if (qName.equals("adapters")) { + } else if (qName.equals("adapter")) { + } else if (qName.equals("manager")) { + } else if (qName.equals("dao")) { + } else if (qName.equals("pluggableservice")) { + } else if (qName.equals("param")) { + currentInfo.params.put(paramName, value.toString()); + paramName = null; + value = null; + } else { + // ignore + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + if (parse && value != null) { + value.append(ch, start, length); + } + } + } + + protected static class InjectInfo { + public Factory factory; + public Enhancer enhancer; + + public InjectInfo(Enhancer enhancer, Factory factory) { + this.factory = factory; + this.enhancer = enhancer; + } + } + + protected static class CleanupThread extends Thread { + @Override + public void run() { + synchronized (CleanupThread.class) { + for (LegacyComponentLocator locator : s_locators.values()) { + Iterator> itAdapters = locator._adapterMap.values().iterator(); + while (itAdapters.hasNext()) { + Adapters adapters = itAdapters.next(); + itAdapters.remove(); + for (ComponentInfo adapter : adapters._infos) { + if (adapter.singleton) { + Singleton singleton = s_singletons.get(adapter.clazz); + if (singleton.state == Singleton.State.Started) { + s_logger.info("Asking " + adapter.getName() + " to shutdown."); + adapter.instance.stop(); + singleton.state = Singleton.State.Stopped; + } else { + s_logger.debug("Skippng " + adapter.getName() + " because it has already stopped"); + } + } else { + s_logger.info("Asking " + adapter.getName() + " to shutdown."); + adapter.instance.stop(); + } + } + } + } + + for (LegacyComponentLocator locator : s_locators.values()) { + Iterator> itManagers = locator._managerMap.values().iterator(); + while (itManagers.hasNext()) { + ComponentInfo manager = itManagers.next(); + itManagers.remove(); + if (manager.singleton == true) { + Singleton singleton = s_singletons.get(manager.clazz); + if (singleton != null && singleton.state == Singleton.State.Started) { + s_logger.info("Asking Manager " + manager.getName() + " to shutdown."); + manager.instance.stop(); + singleton.state = Singleton.State.Stopped; + } else { + s_logger.info("Skipping Manager " + manager.getName() + " because it is not in a state to shutdown."); + } + } + } + } + } + } + } + + static class Singleton { + public enum State { + Instantiated, + Injected, + Configured, + Started, + Stopped + } + + public Object singleton; + public State state; + + public Singleton(Object singleton) { + this.singleton = singleton; + this.state = State.Instantiated; + } + } + + protected class InterceptorDispatcher implements MethodInterceptor { + + @Override + public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { + ArrayList, Object>> interceptors = new ArrayList, Object>>(); + for (AnnotationInterceptor interceptor : s_interceptors) { + if (interceptor.needToIntercept(method)) { + Object obj = interceptor.interceptStart(method); + interceptors.add(new Pair, Object>((AnnotationInterceptor)interceptor, obj)); + } + } + boolean success = false; + try { + Object obj = methodProxy.invokeSuper(object, args); + success = true; + return obj; + } finally { + for (Pair, Object> interceptor : interceptors) { + if (success) { + interceptor.first().interceptComplete(method, interceptor.second()); + } else { + interceptor.first().interceptException(method, interceptor.second()); + } + } + } + } + } + + protected static class InterceptorFilter implements CallbackFilter { + @Override + public int accept(Method method) { + int index = 0; + for (int i = 2; i < s_callbacks.length; i++) { + AnnotationInterceptor interceptor = (AnnotationInterceptor)s_callbacks[i]; + if (interceptor.needToIntercept(method)) { + if (index == 0) { + index = i; + } else { + return 1; + } + } + } + + return index; + } + } +} diff --git a/utils/test/com/cloud/utils/component/MockComponentLocator.java b/utils/test/com/cloud/utils/component/MockComponentLocator.java index f7adf0640c3..d95d2629d06 100755 --- a/utils/test/com/cloud/utils/component/MockComponentLocator.java +++ b/utils/test/com/cloud/utils/component/MockComponentLocator.java @@ -33,7 +33,7 @@ import com.cloud.utils.db.GenericDao; /** * defining mock components. */ -public class MockComponentLocator extends ComponentLocator { +public class MockComponentLocator extends LegacyComponentLocator { MockComponentLibrary _library = new MockComponentLibrary(); public MockComponentLocator(String server) { diff --git a/utils/test/com/cloud/utils/testcase/ComponentTestCase.java b/utils/test/com/cloud/utils/testcase/ComponentTestCase.java index 9e79da34dd2..6fe7af10200 100644 --- a/utils/test/com/cloud/utils/testcase/ComponentTestCase.java +++ b/utils/test/com/cloud/utils/testcase/ComponentTestCase.java @@ -18,7 +18,7 @@ package com.cloud.utils.testcase; import java.lang.annotation.Annotation; -import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.component.LegacyComponentLocator; public class ComponentTestCase extends Log4jEnabledTestCase { @Override @@ -29,7 +29,7 @@ public class ComponentTestCase extends Log4jEnabledTestCase { if(annotations != null) { for(Annotation annotation : annotations) { if(annotation instanceof ComponentSetup) { - ComponentLocator.getLocator( + LegacyComponentLocator.getLocator( ((ComponentSetup)annotation).managerName(), ((ComponentSetup)annotation).setupXml(), ((ComponentSetup)annotation).log4j()