001 /*******************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved.
003 * --------------------------------------------------------------------------
004 * The software in this package is published under the terms of the BSD style
005 * license a copy of which has been included with this distribution in the
006 * LICENSE.txt file.
007 ******************************************************************************/
008 package org.picocontainer.web.script;
009
010 import java.io.InputStream;
011 import java.io.InputStreamReader;
012 import java.io.Reader;
013
014 import org.picocontainer.ComponentAdapter;
015 import org.picocontainer.MutablePicoContainer;
016 import org.picocontainer.Parameter;
017 import org.picocontainer.PicoCompositionException;
018 import org.picocontainer.PicoContainer;
019 import org.picocontainer.classname.ClassLoadingPicoContainer;
020 import org.picocontainer.parameters.ConstantParameter;
021 import org.picocontainer.classname.ClassName;
022 import org.picocontainer.script.ContainerBuilder;
023 import org.picocontainer.classname.DefaultClassLoadingPicoContainer;
024 import org.picocontainer.web.WebappComposer;
025
026 import javax.servlet.ServletContext;
027
028 /**
029 * Script-based webapp composer. Allows to build containers for each webapp
030 * scope from picocontainer scripts, using configurable builder and script
031 * resources, which default to XML scripts.
032 *
033 * @author Mauro Talevi
034 */
035 public class ScriptedWebappComposer implements WebappComposer {
036
037 public final static String DEFAULT_CONTAINER_BUILDER = "org.picocontainer.script.xml.XMLContainerBuilder";
038 public final static String DEFAULT_APPLICATION_SCRIPT = "pico-application.xml";
039 public final static String DEFAULT_SESSION_SCRIPT = "pico-session.xml";
040 public final static String DEFAULT_REQUEST_SCRIPT = "pico-request.xml";
041
042 private String containerBuilderClassName;
043 private String applicationScript;
044 private String sessionScript;
045 private String requestScript;
046
047 public ScriptedWebappComposer() {
048 this(DEFAULT_CONTAINER_BUILDER, DEFAULT_APPLICATION_SCRIPT, DEFAULT_SESSION_SCRIPT, DEFAULT_REQUEST_SCRIPT);
049 }
050
051 public ScriptedWebappComposer(String containerBuilderClassName, String applicationScript, String sessionScript,
052 String requestScript) {
053 this.containerBuilderClassName = containerBuilderClassName;
054 this.applicationScript = applicationScript;
055 this.sessionScript = sessionScript;
056 this.requestScript = requestScript;
057 }
058
059 public void composeApplication(MutablePicoContainer applicationContainer, ServletContext context) {
060 populateContainer(applicationScript, applicationContainer);
061 }
062
063 public void composeSession(MutablePicoContainer sessionContainer) {
064 populateContainer(sessionScript, sessionContainer);
065 }
066
067 public void composeRequest(MutablePicoContainer requestContainer) {
068 populateContainer(requestScript, requestContainer);
069 }
070
071 private void populateContainer(String resourcePath, MutablePicoContainer container) {
072 PicoContainer buildContainer = buildContainer(resourcePath, container.getParent());
073 for (ComponentAdapter<?> adapter : buildContainer.getComponentAdapters()) {
074 container.addAdapter(adapter);
075 }
076 }
077
078 private PicoContainer buildContainer(String resourcePath, PicoContainer parent) {
079 ContainerBuilder builder = createContainerBuilder(getResource(resourcePath));
080 return builder.buildContainer(parent, null, false);
081 }
082
083 private ContainerBuilder createContainerBuilder(Reader reader) {
084 ClassLoadingPicoContainer scripted = new DefaultClassLoadingPicoContainer(getClassLoader());
085 Parameter[] parameters = new Parameter[] { new ConstantParameter(reader),
086 new ConstantParameter(getClassLoader()) };
087 scripted.addComponent(containerBuilderClassName, new ClassName(containerBuilderClassName), parameters);
088 return scripted.getComponent(ContainerBuilder.class);
089 }
090
091 private Reader getResource(String resource) {
092 ClassLoader classLoader = getClassLoader();
093 InputStream stream = classLoader.getResourceAsStream(resource);
094 if (stream == null) {
095 throw new PicoCompositionException("Resource " + resource + " not found in classloader " + classLoader);
096 }
097 return new InputStreamReader(stream);
098 }
099
100 private ClassLoader getClassLoader() {
101 return Thread.currentThread().getContextClassLoader();
102 }
103 }