// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.components;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import fitnesse.ConfigurationParameter;
/**
* Create components for FitNesse.
*
* Components have one of the following constructors:
* <ul>
* <li><code>Component(fitnesse.componentsComponentFactory componentFactory)</code></li>
* <li><code>Component(java.util.Properties properties)</code></li>
* <li><code>Component()</code></li>
* </ul>
*
* Components requested by parameter/type/name are instantiated once for the application.
*/
public class ComponentFactory {
private final Properties properties;
private Map<String, Object> components;
public ComponentFactory(Properties properties) {
this.properties = properties;
this.components = new HashMap<>();
}
public <T> T createComponent(String componentType, Class<T> defaultComponent) throws ComponentInstantiationException {
if (components.containsKey(componentType)) {
return (T) components.get(componentType);
}
String componentClassName = properties.getProperty(componentType);
Class<?> componentClass;
try {
if (componentClassName != null)
componentClass = Class.forName(componentClassName);
else
componentClass = defaultComponent;
} catch (Exception e) {
throw new ComponentInstantiationException("Unable to look up component for type '" + componentType + "' with classname '" + componentClassName + "'", e);
}
if (componentClass != null) {
T component = (T) createComponent(componentClass);
components.put(componentType, component);
return component;
}
return null;
}
public <T> T createComponent(Class<T> componentClass) throws ComponentInstantiationException {
try {
try {
Constructor<?> constructor = componentClass.getConstructor(ComponentFactory.class);
return (T) constructor.newInstance(this);
} catch (NoSuchMethodException e) {
// no problem, we can deal with some other constructors as well
}
try {
Constructor<?> constructor = componentClass.getConstructor(Properties.class);
return (T) constructor.newInstance(properties);
} catch (NoSuchMethodException e) {
Constructor<?> constructor = componentClass.getConstructor();
return (T) constructor.newInstance();
}
} catch (Exception e) {
throw new ComponentInstantiationException("Unable to instantiate component for type " + componentClass.getName(), e);
}
}
public <T> T createComponent(ConfigurationParameter componentType, Class<T> defaultComponent) {
return createComponent(componentType.getKey(), defaultComponent);
}
public <T> T createComponent(ConfigurationParameter componentType) {
return createComponent(componentType, (Class<T>) null);
}
public String getProperty(String key) {
return properties.getProperty(key);
}
public String getProperty(String key, String defaultValue) {
return properties.getProperty(key, defaultValue);
}
}