
org.directwebremoting.impl.DefaultContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dwr Show documentation
Show all versions of dwr Show documentation
DWR is easy Ajax for Java. It makes it simple to call Java code directly from Javascript.
It gets rid of almost all the boilerplate code between the web browser and your Java code.
This version 4.0.2 works with Jakarta Servlet 4.0.2.
The newest version!
package org.directwebremoting.impl;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import org.directwebremoting.Container;
import org.directwebremoting.extend.ContainerConfigurationException;
import org.directwebremoting.extend.UninitializingBean;
import org.directwebremoting.util.LocalUtil;
import org.directwebremoting.util.Loggers;
/**
* DefaultContainer is like a mini-IoC container for DWR.
* At least it is an IoC container by interface (check: no params that have
* anything to do with DWR), but it is hard coded specifically for DWR. If we
* want to make more of it we can later, but this is certainly not going to
* become a full blown IoC container.
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class DefaultContainer extends AbstractContainer implements Container {
/**
* Set the class that should be used to implement the given interface
* @param ...
* @param base The interface to implement
* @param bean The new implementation
* @throws ContainerConfigurationException If the specified beans could not be used
*/
public void addBean(Class base, T bean) {
addParameter(LocalUtil.originalDwrClassName(base.getName()), bean);
}
/**
* Set the class that should be used to implement the given interface
* @param ...
* @param base The interface to implement
* @param implementation The new implementation
* @throws ContainerConfigurationException If the specified beans could not be used
*/
public void addImplementation(Class base, Class extends T> implementation) {
addParameter(LocalUtil.originalDwrClassName(base.getName()), implementation.getName());
}
/**
* Set the class that should be used to implement the given interface
* @param ...
* @param base The interface to implement
* @param implementation The new implementation
* @throws ContainerConfigurationException If the specified beans could not be used
*/
public void addImplementationOption(Class base, Class extends T> implementation) {
Object existingOptions = beans.get(base.getName());
if (existingOptions == null) {
beans.put(LocalUtil.originalDwrClassName(base.getName()), implementation.getName());
} else {
beans.put(LocalUtil.originalDwrClassName(base.getName()), existingOptions + " " + implementation.getName());
}
}
/**
* Add a parameter to the container as a possibility for injection
* @param askFor The key that will be looked up
* @param valueParam The value to be returned from the key lookup
* @throws ContainerConfigurationException If the specified beans could not be used
*/
public void addParameter(String askFor, Object valueParam) throws ContainerConfigurationException {
Object value = valueParam;
// Maybe the value is a classname that needs instantiating
if (value instanceof String) {
try {
Class> impl = LocalUtil.classForName((String) value);
value = impl.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException ex) {
// it's not a classname, leave it
} catch (InstantiationException ex) {
throw new ContainerConfigurationException("Unable to instantiate " + value);
} catch (IllegalAccessException ex) {
throw new ContainerConfigurationException("Unable to access " + value);
} catch (InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
// If we have an instantiated value object and askFor is an interface
// then we can check that one implements the other
if (!(value instanceof String)) {
try {
Class> iface = LocalUtil.classForName(askFor);
if (!iface.isAssignableFrom(value.getClass())) {
Loggers.STARTUP.error("Can't cast: " + value + " to " + askFor);
}
} catch (ClassNotFoundException ex) {
// it's not a classname, leave it
}
}
if (Loggers.STARTUP.isDebugEnabled()) {
if (value instanceof String) {
Loggers.STARTUP.debug("- value: " + askFor + " = " + value);
} else {
Loggers.STARTUP.debug("- impl: " + askFor + " = " + value.getClass().getName());
}
}
beans.put(askFor, value);
}
/**
* Retrieve a previously set parameter
* @param name The parameter name to retrieve
* @return The value of the specified parameter, or null if one is not set
*/
public String getParameter(String name) {
Object value = beans.get(name);
return (value == null) ? null : value.toString();
}
/**
* Called to indicate that we finished adding parameters.
* The thread safety of a large part of DWR depends on this function only
* being called from {@link Servlet#init(jakarta.servlet.ServletConfig)},
* where all the setup is done, and where we depend on the undocumented
* feature of all servlet containers that they complete the init process
* of a Servlet before they begin servicing requests.
* @see DefaultContainer#addParameter(String, Object)
*/
public void setupFinished() {
// We try to autowire each bean in turn
for (Object bean : beans.values()) {
initializeBean(bean);
}
callInitializingBeans();
}
public T newInstance(Class type) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
T t = type.getDeclaredConstructor().newInstance();
initializeBean(t);
return t;
}
public void initializeBean(Object bean) {
// HACK: It wouldn't be a good idea to start injecting into objects
// created by the app-server. Currently this is just ServletContext
// and ServletConfig. If it is others in the future then we'll need a
// better way of marking objects that should not be injected into.
// It's worth remembering that the Container is itself in the container
// so there is a vague risk of recursion here if we're not careful
if (bean instanceof ServletContext || bean instanceof ServletConfig) {
Loggers.STARTUP.debug("- skipping injecting into: " + bean.getClass().getName());
return;
}
if (!(bean instanceof String)) {
Loggers.STARTUP.debug("- autowire: " + bean.getClass().getName());
Method[] methods = bean.getClass().getMethods();
methods:
for (Method setter : methods) {
if (setter.getName().startsWith("set") &&
setter.getName().length() > 3 &&
setter.getParameterTypes().length == 1)
{
String name = Character.toLowerCase(setter.getName().charAt(3)) + setter.getName().substring(4);
Class> propertyType = setter.getParameterTypes()[0];
// First we try auto-wire by name
Object setting = beans.get(name);
if (setting != null) {
if (propertyType.isAssignableFrom(setting.getClass())) {
Loggers.STARTUP.debug(" - by name: " + name + " = " + setting);
invoke(setter, bean, setting);
continue methods;
} else if (setting.getClass() == String.class) {
try {
Object value = LocalUtil.simpleConvert((String) setting, propertyType);
Loggers.STARTUP.debug(" - by name: " + name + " = " + value);
invoke(setter, bean, value);
} catch (IllegalArgumentException ex) {
// Ignore - this was a speculative convert anyway
}
continue methods;
}
}
// Next we try autowire-by-type
Object value = beans.get(LocalUtil.originalDwrClassName(propertyType.getName()));
if (value != null) {
Loggers.STARTUP.debug(" - by type: " + name + " = " + value.getClass().getName());
invoke(setter, bean, value);
continue methods;
}
Loggers.STARTUP.debug(" - no properties for: " + name);
}
}
}
}
/**
* A helper to do the reflection.
* This helper throws away all exceptions, preferring to log.
* @param setter The method to invoke
* @param bean The object to invoke the method on
* @param value The value to assign to the property using the setter method
*/
private static void invoke(Method setter, Object bean, Object value) {
try {
setter.invoke(bean, value);
} catch (InvocationTargetException ex) {
Loggers.STARTUP.error(" - Exception during auto-wire: ", ex.getTargetException());
} catch (Exception ex) {
Loggers.STARTUP.error(" - Error calling setter: " + setter, ex);
}
}
public Object getBean(String id)
{
return beans.get(id);
}
public Collection getBeanNames()
{
return Collections.unmodifiableCollection(beans.keySet());
}
public synchronized void destroy() {
if (isDestroyed) {
return;
}
isDestroyed = true;
destroy(getBeanNames());
}
public void destroy(Collection beanNames) {
Loggers.STARTUP.debug("Destroy for container: " + getClass().getSimpleName());
for (String beanName : beanNames) {
Object bean = getBean(beanName);
if (bean instanceof UninitializingBean && !(bean instanceof Container)) {
UninitializingBean scl = (UninitializingBean) bean;
Loggers.STARTUP.debug("- For contained bean: " + beanName);
scl.destroy();
}
}
}
/**
* The beans that we know of indexed by type
*/
protected Map beans = new TreeMap();
/**
* Keep track of whether we have already been destroyed
*/
boolean isDestroyed = false;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy