Package org.nanocontainer.nanowar.chain

Source Code of org.nanocontainer.nanowar.chain.ServletChainBuilder

/*****************************************************************************
* Copyright (C) NanoContainer 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.                                                     *
*                                                                           *
* Original code by Konstantin Pribluda                                      *
*****************************************************************************/
package org.nanocontainer.nanowar.chain;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;

import org.nanocontainer.DefaultNanoContainer;
import org.nanocontainer.NanoContainer;
import org.nanocontainer.integrationkit.ContainerBuilder;
import org.nanocontainer.integrationkit.ContainerPopulator;
import org.nanocontainer.integrationkit.ContainerRecorder;
import org.nanocontainer.reflection.DefaultContainerRecorder;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.Parameter;
import org.picocontainer.PicoContainer;
import org.picocontainer.defaults.ConstantParameter;
import org.picocontainer.defaults.DefaultPicoContainer;

/**
* <p>
* ServletChainBuilder builds ContainerChains from servlet path and caches
* container recorders for later use.
* </p>
*
* @author Kontantin Pribluda
* @author Mauro Talevi
*/
public class ServletChainBuilder {

  private Map recorderCache;
  private ServletContext context;
    private String containerBuilderClassName;
    private String containerScriptName;
    private String emptyContainerScript;

  /**
   * Constructor for the ServletChainBuilder object
   *
   * @param context the ServletContext
     * @param containerBuilderClassName the class name of the ContainerBuilder
     * @param containerScriptName the name of the container script resource
     * @param emptyContainerScript the script for empty container if the container config is not found
   */
  public ServletChainBuilder(ServletContext context, String containerBuilderClassName, String containerScriptName, String emptyContainerScript) {
        this.context = context;
        this.containerBuilderClassName = containerBuilderClassName;
        this.containerScriptName = containerScriptName;
        this.emptyContainerScript = emptyContainerScript;
        this.recorderCache = new HashMap();
  }

  /**
   * populate container for given path. cache result in container recorders
   *
   * @param container the MutablePicoContainer used by the recorder
   * @param path the String representing the servlet path used as key for the recorder cache
   * @throws ClassNotFoundException if the container builder class is not found
   */
  public void populateContainerForPath(MutablePicoContainer container,
      String path) throws ClassNotFoundException {
    ContainerRecorder recorder;
    synchronized (recorderCache) {
      recorder = (ContainerRecorder) recorderCache.get(path);
      if (recorder == null) {
        recorder = new DefaultContainerRecorder(new DefaultPicoContainer());
        recorderCache.put(path, recorder);
        ContainerPopulator populator = createContainerPopulator(containerBuilderClassName,
                                    obtainReader(path), Thread.currentThread().getContextClassLoader());
        populator.populateContainer(recorder.getContainerProxy());
      }
    }
    recorder.replay(container);
  }

  /**
   * Build ContainerChain for path elements
   *
   * @param pathElements an array of Objects used as keys for
   *            selecting Application objects
     * @param parent the parent PicoContainer or <code>null</code>
   * @return The configured ContainerChain
   * @throws ClassNotFoundException
   */
  public ContainerChain buildChain(Object[] pathElements, PicoContainer parent) throws ClassNotFoundException {
    ContainerChain chain = new ContainerChain();
    populateRecursively(chain, parent, Arrays.asList(pathElements).iterator());
    return chain;
  }

  /**
   * Create and populate containers in recursive way
   *
     * @param chain the ContainerChain to which the containers are added
   * @param parent the parent PicoContainer
     * @param pathElements the Iterator on the path elements
   * @throws ClassNotFoundException
   */
  public void populateRecursively(ContainerChain chain, PicoContainer parent,
      Iterator pathElements) throws ClassNotFoundException {
    if (pathElements.hasNext()) {
      Object key = pathElements.next();
      DefaultPicoContainer container = new DefaultPicoContainer(parent);

      populateContainerForPath(container, key.toString());
      chain.addContainer(container);
      populateRecursively(chain, container, pathElements);
    }
  }

    /**
     * Instantiates ContainerPopulator for container builder
     *
     * @param containerBuilderClassName the class name of the builder implementing ContainerPopulator
     * @param reader the Reader for the builder
     * @param classLoader the ClassLoader for the builder
     * @return An instance of ContainerPopulator
     * @throws ClassNotFoundException
     */
    private ContainerPopulator createContainerPopulator(String containerBuilderClassName, Reader reader, ClassLoader classLoader)
            throws ClassNotFoundException {
        NanoContainer nano = new DefaultNanoContainer(classLoader);
        Parameter[] parameters = new Parameter[] {
                new ConstantParameter(reader),
                new ConstantParameter(classLoader) };
        nano.registerComponentImplementation(containerBuilderClassName,
                containerBuilderClassName, parameters);
        ContainerBuilder containerBuilder = (ContainerBuilder) nano.getPico()
                .getComponentInstance(containerBuilderClassName);
        //containerBuilder.buildContainer(new SimpleReference(), null, null,
        //        false);
        return (ContainerPopulator) containerBuilder;
    }
   
    /**
     * Obtain reader from servlet context path, by appending container script name to path.
     * If not found, returns reader for empty container instead.
     *
     * @param path the String representing the path in servlet context
     * @return A Reader for corresponding script or for empty container if script not found
     */
    private Reader obtainReader(String path) {
        InputStream is = context.getResourceAsStream(path + containerScriptName);
        if (is != null) {
            return new InputStreamReader(is);
        } else {
            return new StringReader(emptyContainerScript);
        }
    }

}
TOP

Related Classes of org.nanocontainer.nanowar.chain.ServletChainBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.