
org.picocontainer.script.groovy.nodes.ChildContainerNode Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (C) PicoContainer Organization. All rights reserved.
* ---------------------------------------------------------------------------
* The software in this package is published under the terms of the BSD style
* license a copy of which has been included with this distribution in the
* LICENSE.txt file.
******************************************************************************/
package org.picocontainer.script.groovy.nodes;
import java.util.Map;
import org.picocontainer.DefaultPicoContainer;
import java.security.PrivilegedAction;
import org.picocontainer.ComponentFactory;
import java.security.AccessController;
import org.picocontainer.behaviors.Caching;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.PicoContainer;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.monitors.AbstractComponentMonitor;
import org.picocontainer.classname.DefaultClassLoadingPicoContainer;
import org.picocontainer.script.ScriptedPicoContainerMarkupException;
import org.picocontainer.script.NodeBuilderDecorator;
import org.picocontainer.classname.ClassLoadingPicoContainer;
import org.picocontainer.ComponentMonitorStrategy;
/**
* Creates a new PicoContainer node. There may or may not be a parent container
* involved.
*
* @author James Strachan
* @author Paul Hammant
* @author Aslak Hellesøy
* @author Michael Rimov
* @author Mauro Talevi
*/
@SuppressWarnings("serial")
public class ChildContainerNode extends AbstractBuilderNode {
/**
* Node name.
*/
public static final String NODE_NAME = "container";
/**
* Supported Attribute: 'class' Reference to a classname of the container to
* use.
*/
private static final String CLASS = "class";
/**
* The node decorator.
*/
private final NodeBuilderDecorator decorator;
/**
* Attribute: 'componentFactory' a reference to an instance of a component
* factory.
*/
private static final String COMPONENT_ADAPTER_FACTORY = "componentFactory";
/**
* Attribute: 'componentMonitor' a reference to an instance of a component
* monitor.
*/
private static final String COMPONENT_MONITOR = "componentMonitor";
/**
* Attribute that exists in test cases, but not necessarily used?
*/
private static final String SCOPE = "scope";
/**
* Attribute: 'parent' a reference to the parent for this new container.
*/
private static final String PARENT = "parent";
/**
* Constructs a child container node with a given decorator
*
* @param decorator NodeBuilderDecorator
*/
public ChildContainerNode(NodeBuilderDecorator decorator) {
super(NODE_NAME);
this.decorator = decorator;
this.addAttribute(CLASS).addAttribute(COMPONENT_ADAPTER_FACTORY).addAttribute(COMPONENT_MONITOR).addAttribute(
PARENT).addAttribute(SCOPE);
}
/**
* Creates a new container. There may or may not be a parent to this
* container. Supported attributes are
*
* {@inheritDoc}
*
*
* @param current PicoContainer
* @param attributes Map
* @return Object
* @throws ScriptedPicoContainerMarkupException
*/
@SuppressWarnings("unchecked")
public Object createNewNode(Object current, Map attributes) throws ScriptedPicoContainerMarkupException {
return createChildContainer(attributes, (ClassLoadingPicoContainer) current);
}
/**
* Returns the decorator
*
* @return A NodeBuilderDecorator
*/
private NodeBuilderDecorator getDecorator() {
return decorator;
}
/**
* Creates a new container. There may or may not be a parent to this
* container. Supported attributes are:
*
* - componentFactory: The ComponentFactory used for new
* container
* - componentMonitor: The ComponentMonitor used for new
* container
*
*
* @param attributes Map Attributes defined by the builder in the script.
* @param parent The parent container
* @return The PicoContainer
*/
@SuppressWarnings("unchecked")
protected ClassLoadingPicoContainer createChildContainer(Map attributes, ClassLoadingPicoContainer parent) {
ClassLoader parentClassLoader;
MutablePicoContainer childContainer;
if (parent != null) {
parentClassLoader = parent.getComponentClassLoader();
if (isAttribute(attributes, COMPONENT_ADAPTER_FACTORY)) {
ComponentFactory componentFactory = createComponentFactory(attributes);
childContainer = new DefaultPicoContainer(getDecorator()
.decorate(componentFactory, attributes), parent);
if (isAttribute(attributes, COMPONENT_MONITOR)) {
changeComponentMonitor(childContainer, createComponentMonitor(attributes));
}
parent.addChildContainer(childContainer);
} else if (isAttribute(attributes, COMPONENT_MONITOR)) {
ComponentFactory componentFactory = new Caching();
childContainer = new DefaultPicoContainer(getDecorator()
.decorate(componentFactory, attributes), parent);
changeComponentMonitor(childContainer, createComponentMonitor(attributes));
} else {
childContainer = parent.makeChildContainer();
}
} else {
parentClassLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return PicoContainer.class.getClassLoader();
}
});
ComponentFactory componentFactory = createComponentFactory(attributes);
childContainer = new DefaultPicoContainer(getDecorator().decorate(componentFactory, attributes));
if (isAttribute(attributes, COMPONENT_MONITOR)) {
changeComponentMonitor(childContainer, createComponentMonitor(attributes));
}
}
MutablePicoContainer decoratedPico = getDecorator().decorate(childContainer);
if (isAttribute(attributes, CLASS)) {
Class> clazz = (Class>) attributes.get(CLASS);
return createPicoContainer(clazz, decoratedPico, parentClassLoader);
} else {
return new DefaultClassLoadingPicoContainer(parentClassLoader, decoratedPico);
}
}
private void changeComponentMonitor(MutablePicoContainer childContainer, ComponentMonitor monitor) {
if (childContainer instanceof ComponentMonitorStrategy) {
((ComponentMonitorStrategy) childContainer).changeMonitor(monitor);
}
}
private ClassLoadingPicoContainer createPicoContainer(Class> clazz, MutablePicoContainer decoratedPico,
ClassLoader parentClassLoader) {
DefaultPicoContainer instantiatingContainer = new DefaultPicoContainer();
instantiatingContainer.addComponent(ClassLoader.class, parentClassLoader);
instantiatingContainer.addComponent(MutablePicoContainer.class, decoratedPico);
instantiatingContainer.addComponent(ClassLoadingPicoContainer.class, clazz);
Object componentInstance = instantiatingContainer.getComponent(ClassLoadingPicoContainer.class);
return (ClassLoadingPicoContainer) componentInstance;
}
private ComponentFactory createComponentFactory(Map attributes) {
final ComponentFactory factory = (ComponentFactory) attributes.remove(COMPONENT_ADAPTER_FACTORY);
if (factory == null) {
return new Caching();
}
return factory;
}
private ComponentMonitor createComponentMonitor(Map attributes) {
final ComponentMonitor monitor = (ComponentMonitor) attributes.remove(COMPONENT_MONITOR);
if (monitor == null) {
return new AbstractComponentMonitor();
}
return monitor;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy