Added support for component libraries in plugins

This commit is contained in:
Alex Huang 2012-07-09 10:25:14 -07:00
parent 75184d33ea
commit 1d3a443237
2 changed files with 121 additions and 78 deletions

View File

@ -71,9 +71,42 @@ import com.cloud.utils.mgmt.JmxUtil;
import com.cloud.utils.mgmt.ManagementBean;
/**
* ComponentLocator manages all of the adapters within a system. It operates on
* top of an components.xml and uses reflection to instantiate all of the
* adapters. It also supports rereading of all of the adapters.
* 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")
@ -98,7 +131,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
protected String _serverName;
protected Object _component;
protected HashMap<Class<?>, Class<?>> _factories;
protected HashMap<String, ComponentInfo<PluggableService>> _pluggableServicesMap;
protected HashMap<String, ComponentInfo<PluggableService>> _pluginsMap;
static {
if (s_janitor == null) {
@ -133,7 +166,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
_checkerMap = new LinkedHashMap<String, ComponentInfo<SystemIntegrityChecker>>();
_adapterMap = new HashMap<String, Adapters<? extends Adapter>>();
_factories = new HashMap<Class<?>, Class<?>>();
_pluggableServicesMap = new LinkedHashMap<String, ComponentInfo<PluggableService>>();
_pluginsMap = new LinkedHashMap<String, ComponentInfo<PluggableService>>();
File file = PropertiesUtil.findConfigFile(filename);
if (file == null) {
s_logger.info("Unable to find " + filename);
@ -157,7 +190,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
_daoMap.putAll(parentLocator._daoMap);
_managerMap.putAll(parentLocator._managerMap);
_factories.putAll(parentLocator._factories);
_pluggableServicesMap.putAll(parentLocator._pluggableServicesMap);
_pluginsMap.putAll(parentLocator._pluginsMap);
}
ComponentLibrary library = null;
@ -168,14 +201,14 @@ public class ComponentLocator implements ComponentLocatorMBean {
_managerMap.putAll(library.getManagers());
adapters.putAll(library.getAdapters());
_factories.putAll(library.getFactories());
_pluggableServicesMap.putAll(library.getPluggableServices());
_pluginsMap.putAll(library.getPluggableServices());
}
_daoMap.putAll(handler.daos);
_managerMap.putAll(handler.managers);
_checkerMap.putAll(handler.checkers);
adapters.putAll(handler.adapters);
_pluggableServicesMap.putAll(handler.pluggableServices);
_pluginsMap.putAll(handler.pluggableServices);
return new Pair<XmlHandler, HashMap<String, List<ComponentInfo<Adapter>>>>(handler, adapters);
} catch (ParserConfigurationException e) {
@ -204,6 +237,8 @@ public class ComponentLocator implements ComponentLocatorMBean {
return;
}
instantiatePluggableServices();
XmlHandler handler = result.first();
HashMap<String, List<ComponentInfo<Adapter>>> adapters = result.second();
try {
@ -220,13 +255,12 @@ public class ComponentLocator implements ComponentLocatorMBean {
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?)
instantiatePluggableServices();
} 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);
s_logger.error("Unable to load configuration for " + _serverName + " from " + filename, e);
System.exit(1);
}
}
@ -369,13 +403,13 @@ public class ComponentLocator implements ComponentLocatorMBean {
}
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;
}
}
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) {
@ -641,18 +675,26 @@ public class ComponentLocator implements ComponentLocatorMBean {
}
protected void instantiatePluggableServices() {
Set<Map.Entry<String, ComponentInfo<PluggableService>>> entries = _pluggableServicesMap.entrySet();
Set<Map.Entry<String, ComponentInfo<PluggableService>>> entries = _pluginsMap.entrySet();
for (Map.Entry<String, ComponentInfo<PluggableService>> entry : entries) {
ComponentInfo<PluggableService> 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<PluggableService> getPluggableService(String name) {
ComponentInfo<PluggableService> mgr = _pluggableServicesMap.get(name);
ComponentInfo<PluggableService> mgr = _pluginsMap.get(name);
return mgr;
}
@ -669,7 +711,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
public <T> List<T> getAllPluggableServices() {
List<T> services = new ArrayList<T>();
Set<Map.Entry<String, ComponentInfo<PluggableService>>> entries = _pluggableServicesMap.entrySet();
Set<Map.Entry<String, ComponentInfo<PluggableService>>> entries = _pluginsMap.entrySet();
for (Map.Entry<String, ComponentInfo<PluggableService>> entry : entries) {
ComponentInfo<PluggableService> info = entry.getValue();
if (info.instance == null) {
@ -970,7 +1012,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
throws SAXException {
if (qName.equals("interceptor") && s_interceptors.size() == 0) {
synchronized(s_interceptors){
if (s_interceptors.size() == 0) {
@ -1041,7 +1083,7 @@ public class ComponentLocator implements ComponentLocatorMBean {
checkers.put(info.name, info);
s_logger.info("Adding system integrity checker: " + info.name);
currentInfo = info;
} else if (qName.equals("pluggableservice")) {
} else if (qName.equals("pluggableservice") || qName.equals("plugin")) {
ComponentInfo<PluggableService> info = new ComponentInfo<PluggableService>();
fillInfo(atts, PluggableService.class, info);
s_logger.info("Adding PluggableService: " + info.name);

View File

@ -17,6 +17,7 @@
package com.cloud.utils.component;
/**
* This interface defines methods for pluggable code within the Cloud Stack.
*/