package org.yajul.micro;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.Scope;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
import java.net.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yajul.util.ReflectionUtil;
/**
* Guice module that uses properties resources to define components.
* Names are key class names (usually interface names), values are implementation class names.
* If a value is a class name that implements Module, the class will be instantiated and
* the module will be installed into the injector immediately.
* <br>
* User: josh
* Date: Dec 30, 2008
* Time: 4:09:31 PM
*/
public class PropertiesResourceModule extends AbstractResourceModule
{
private final static Logger log = LoggerFactory.getLogger(PropertiesResourceModule.class);
private Scope scope = Scopes.SINGLETON;
public PropertiesResourceModule(String resourceName, ClassLoader classLoader, Scope scope)
{
super(resourceName, classLoader);
this.scope = scope;
}
public PropertiesResourceModule(String resourceName)
{
this(resourceName, ReflectionUtil.getCurrentClassLoader(), Scopes.SINGLETON);
}
protected void configureFromResource(InputStream stream, URL url)
throws IOException
{
Properties props = new Properties();
props.load(stream);
addComponentsFromProperties(props, getClassLoader());
}
/**
* Add components from a properties file, where the property names are interfaces/keys, and the
* property values are implementation class names.
*
* @param props the properties
* @param classLoader the class loader to use for looking up class/interface names.
*/
public void addComponentsFromProperties(Properties props, ClassLoader classLoader)
{
Enumeration keyNames = props.propertyNames();
if (log.isDebugEnabled())
log.debug("addComponentsFromProperties() : " + props.size() + " properties.");
while (keyNames.hasMoreElements())
{
String keyName = (String) keyNames.nextElement();
String valueName = props.getProperty(keyName);
// If the key is a class (interface), then use it.
Object key = MicroContainer.processName(keyName, classLoader);
Class<?> impl = (Class<?>) MicroContainer.processName(valueName, classLoader);
// If this is a module, use it to configure other components.
if (ModuleHelper.isModule(impl))
{
ModuleHelper.bindModuleClass(binder(),impl);
}
else if (key instanceof Class)
{
Class keyClass = (Class) key;
if (keyClass.equals(impl))
{
bind(impl).in(scope);
}
else
{
//noinspection unchecked
bind(keyClass).to(impl).in(scope);
}
}
else
{
// The key is a string.
if (log.isDebugEnabled())
log.debug("addComponentsFromProperties() : ignoring [" + keyName + "=" + valueName + "]");
}
}
}
}