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 /**
027 * Script-based webapp composer. Allows to build containers for each webapp
028 * scope from picocontainer scripts, using configurable builder and script
029 * resources, which default to XML scripts.
030 *
031 * @author Mauro Talevi
032 */
033 public class ScriptedWebappComposer implements WebappComposer {
034
035 public final static String DEFAULT_CONTAINER_BUILDER = "org.picocontainer.script.xml.XMLContainerBuilder";
036 public final static String DEFAULT_APPLICATION_SCRIPT = "pico-application.xml";
037 public final static String DEFAULT_SESSION_SCRIPT = "pico-session.xml";
038 public final static String DEFAULT_REQUEST_SCRIPT = "pico-request.xml";
039
040 private String containerBuilderClassName;
041 private String applicationScript;
042 private String sessionScript;
043 private String requestScript;
044
045 public ScriptedWebappComposer() {
046 this(DEFAULT_CONTAINER_BUILDER, DEFAULT_APPLICATION_SCRIPT, DEFAULT_SESSION_SCRIPT, DEFAULT_REQUEST_SCRIPT);
047 }
048
049 public ScriptedWebappComposer(String containerBuilderClassName, String applicationScript, String sessionScript,
050 String requestScript) {
051 this.containerBuilderClassName = containerBuilderClassName;
052 this.applicationScript = applicationScript;
053 this.sessionScript = sessionScript;
054 this.requestScript = requestScript;
055 }
056
057 public void composeApplication(MutablePicoContainer applicationContainer) {
058 populateContainer(applicationScript, applicationContainer);
059 }
060
061 public void composeSession(MutablePicoContainer sessionContainer) {
062 populateContainer(sessionScript, sessionContainer);
063 }
064
065 public void composeRequest(MutablePicoContainer requestContainer) {
066 populateContainer(requestScript, requestContainer);
067 }
068
069 private void populateContainer(String resourcePath, MutablePicoContainer container) {
070 PicoContainer buildContainer = buildContainer(resourcePath, container.getParent());
071 for (ComponentAdapter<?> adapter : buildContainer.getComponentAdapters()) {
072 container.addAdapter(adapter);
073 }
074 }
075
076 private PicoContainer buildContainer(String resourcePath, PicoContainer parent) {
077 ContainerBuilder builder = createContainerBuilder(getResource(resourcePath));
078 return builder.buildContainer(parent, null, false);
079 }
080
081 private ContainerBuilder createContainerBuilder(Reader reader) {
082 ClassLoadingPicoContainer scripted = new DefaultClassLoadingPicoContainer(getClassLoader());
083 Parameter[] parameters = new Parameter[] { new ConstantParameter(reader),
084 new ConstantParameter(getClassLoader()) };
085 scripted.addComponent(containerBuilderClassName, new ClassName(containerBuilderClassName), parameters);
086 return scripted.getComponent(ContainerBuilder.class);
087 }
088
089 private Reader getResource(String resource) {
090 ClassLoader classLoader = getClassLoader();
091 InputStream stream = classLoader.getResourceAsStream(resource);
092 if (stream == null) {
093 throw new PicoCompositionException("Resource " + resource + " not found in classloader " + classLoader);
094 }
095 return new InputStreamReader(stream);
096 }
097
098 private ClassLoader getClassLoader() {
099 return Thread.currentThread().getContextClassLoader();
100 }
101 }