/**
* EasyBeans
* Copyright (C) 2006-2007 Bull S.A.S.
* Contact: easybeans@ow2.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: ComponentManager.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.easybeans.component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.ow2.easybeans.api.components.EZBComponentManager;
import org.ow2.easybeans.api.components.EZBComponentRegistry;
import org.ow2.easybeans.component.api.EZBComponent;
import org.ow2.easybeans.component.api.EZBComponentException;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;
/**
* Create and destroy components.
* @author Florent Benoit
*/
public class ComponentManager implements EZBComponentManager {
/**
* If Component classname ends with "Component", safely remove it.
*/
private static final String COMPONENT_STR = "Component";
/**
* Logger.
*/
private Log logger = LogFactory.getLog(ComponentManager.class);
/**
* Components names that are managed.
*/
private List<String> componentNames = null;
/**
* Components objects. (that were set by configuration).
*/
private Components components = null;
/**
* Link to the registry of components (key=component name/value=EZB component).
*/
private ComponentRegistry componentRegistry = null;
/**
* Build a component manager.
*/
public ComponentManager() {
this.componentRegistry = new ComponentRegistry();
this.componentNames = new ArrayList<String>();
}
/**
* Build a new component manager with the given set of components.
* @param components the given set of components
*/
public ComponentManager(final Components components) {
this();
setComponents(components);
}
/**
* Gets the set of components.
* @return the set of components.
*/
public Components getComponents() {
return this.components;
}
/**
* Sets the components object.
* @param components the set of components.
*/
public void setComponents(final Components components) {
this.components = components;
}
/**
* Add the given component.
* @param component the component to register.
* @throws EZBComponentException if the component is not added.
*/
public void addComponent(final EZBComponent component) throws EZBComponentException {
// Add component
addComponent(getComponentName(component), component);
}
/**
* Remove the given component.
* @param component the component to unregister.
* @throws EZBComponentException if the component is not removed.
*/
public void removeComponent(final EZBComponent component) throws EZBComponentException {
// Remove component
String componentName = this.componentRegistry.getComponentName(component);
this.componentNames.remove(componentName);
this.componentRegistry.unregister(componentName);
}
/**
* Gets the name for a given component.
* @param component the component instance.
* @return the name of the component.
*/
private String getComponentName(final EZBComponent component) {
// get name
String componentName = component.getClass().getCanonicalName();
// exist ? (increment counter to get an unique id)
int index = 2;
if (this.componentNames.contains(componentName)) {
while (this.componentNames.contains(componentName)) {
componentName = componentName + (index++);
}
}
return componentName;
}
/**
* Add a component.
* @param componentName the name of the component to add
* @param component the component to add.
* @throws EZBComponentException if adds fails.
*/
private void addComponent(final String componentName, final EZBComponent component) throws EZBComponentException {
// register component
this.componentRegistry.register(componentName, component);
// add to manage list
this.componentNames.add(componentName);
}
/**
* Init the components by calling init() method.
* @param registerComponents if components should be registered or not.
* @throws EZBComponentException if initialization fails
*/
public void initComponents(final boolean registerComponents) throws EZBComponentException {
// Exit soon if there is no components
if (this.components == null) {
return;
}
// Register component
List<EZBComponent> componentList = this.components.getEZBComponents();
if (componentList != null) {
if (registerComponents) {
for (EZBComponent component : componentList) {
addComponent(component);
}
}
// Call init method if any on each component
for (String componentName : this.componentNames) {
EZBComponent component = this.componentRegistry.getComponent(componentName);
component.init();
}
}
}
/**
* Start the components.
* @throws EZBComponentException if starting is failing
*/
public void startComponents() throws EZBComponentException {
StringBuilder sb = new StringBuilder();
sb.append("[ Component(s) started : ");
// Call init method if any on each component
for (String componentName : this.componentNames) {
EZBComponent component = this.componentRegistry.getComponent(componentName);
component.start();
// append the component name
String name = component.getClass().getSimpleName();
// remove "Component" substring if any
if (name.endsWith(COMPONENT_STR)) {
name = name.substring(0, name.lastIndexOf(COMPONENT_STR));
}
sb.append(name);
sb.append(" ");
}
sb.append("]");
this.logger.info(sb.toString());
}
/**
* Stop the components.
*/
public void stopComponents() {
// Call stop method if any on each component in the reverse order of the start.
int size = this.componentNames.size();
for (int i = size - 1; i >= 0; i--) {
String componentName = this.componentNames.get(i);
EZBComponent component = this.componentRegistry.getComponent(componentName);
try {
component.stop();
} catch (EZBComponentException e) {
this.logger.error("Cannot stop component with name '" + componentName + "'.", e);
}
}
}
/**
* @return the component registry used by this manager.
*/
public EZBComponentRegistry getComponentRegistry() {
return this.componentRegistry;
}
/**
* Get a reference to the first component matching the interface.
* @param <T> The interface type.
* @param itf The interface class.
* @return The component.
*/
public <T extends EZBComponent> T getComponent(final Class<T> itf) {
try {
return getComponentRegistry().getComponents(itf).get(0);
} catch (IndexOutOfBoundsException e) {
return getAndRegisterComponent(itf);
}
}
/**
* Allows to get and register a component.
* @param <T> the generics
* @param itf the itf of the component.
* @return the first component that matches the <code>itf</code> component.
*/
@SuppressWarnings("unchecked")
private <T extends EZBComponent> T getAndRegisterComponent(final Class<T> itf) {
// Check not null
if (itf == null) {
throw new IllegalArgumentException("Cannot find component with a null interface");
}
// Check interface
if (!itf.isInterface()) {
throw new IllegalArgumentException("The given class '" + itf + "' is not an interface");
}
// Iterates over the components to find a matching component
List<T> matchComponents = new ArrayList<T>();
try {
for (EZBComponent component : this.components.getEZBComponents()) {
// Component is implemeting the given interface ?
if (Arrays.asList(component.getClass().getInterfaces()).contains(itf)) {
matchComponents.add((T) component);
try {
addComponent(component);
} catch (EZBComponentException e) {
this.logger.debug("Exception in component manager: ", e);
}
}
}
return matchComponents.get(0);
} catch (Exception e) {
this.logger.debug("Exception in component manager", e);
return null;
}
}
/**
* Allow to get a reference on another component.
* @param componentName the name of the component
* @return the component.
*/
public EZBComponent getComponent(final String componentName) {
return this.componentRegistry.getComponent(componentName);
}
}