Package jfun.yan.web

Source Code of jfun.yan.web.YanLoader

package jfun.yan.web;

import java.io.InputStream;
import javax.servlet.ServletContext;

import jfun.util.ClassLoaderUtils;
import jfun.yan.Container;
import jfun.yan.YanException;
import jfun.yan.lifecycle.DefaultLifecycleManager;
import jfun.yan.lifecycle.LifecycleManager;
import jfun.yan.util.resource.ClassLoader2ResourceLoader;
import jfun.yan.util.resource.ResourceLoader;
import jfun.yan.xml.NutsProcessor;
import jfun.yan.xml.nuts.spring.SpringNuts;
/**
* This class is responsible for setting up web integration for Yan.
* <p>
* @author Ben Yu
* Jan 17, 2006 1:27:59 PM
*/
public class YanLoader {

  /**
   * Name of servlet context parameter that can specify the configuration file
   * for the root container, falling back to {@link #DEFAULT_CONFIG_FILE}
   * otherwise.
   */
  public static final String CONFIG_FILE_PARAM = "yanConfigFile";
  /**
   * Name of the servlet context parameter that specifies whether Spring
   * framework integration is required. The default is "false".
   */
  public static final String USE_SPRING = "yanSpringIntegration";
  /**
   * The value "true" that should be specified for {@link #USE_SPRING}
   * if Spring framework integration is desired.
   */
  public static final String TRUE = Boolean.valueOf(true).toString();
  /**
   * The default location of the yan configuration file.
   */
  public static final String DEFAULT_CONFIG_FILE = "/WEB-INF/yan.xml";
  /**
   * The service key for the ServletContext object.
   */
  public static final String SERVLET_CONTEXT_KEY = "jfun.yan.web.ServletContext";
  /**
   * The name of the servlet context attribut that holds the Container instance.
   * Equal to the fully qualified class name of {@link Container}.
   */
  public static final String CONTAINER_ROOT = Container.class.getName();
  /**
   * The name of the servlet context attribute that holds the life cycle manager
   * instance. Equal to the fully qualified name of {@link LifecycleManager}.
   */
  public static final String LIFECYCLE_MANAGER_ROOT = LifecycleManager.class.getName();
  /**
   * The default xml file that configures the non-spring nut classes.
   */
  public static final String DEFAULT_NUTS_FILE = "jfun/yan/web/webnuts.xml";
  /**
   * The default xml file that configures spring aware nut classes.
   */
  public static final String DEFAULT_SPRING_NUTS_FILE = "jfun/yan/web/webspringnuts.xml";
 
  private NutsProcessor processor;
  private Container yan;
  private DefaultLifecycleManager lifecycle_manager;
  /**
   * Initialize this object by instantiating container and life cycle manager.
   * Relevant servlet context parameters are read.
   * @param ctxt the servlet context object.
   * @return the Container object instantiated.
   */
  public Container initContainer(ServletContext ctxt){
    return initContainer(
        ClassLoaderUtils.guessClassLoader(getClass().getClassLoader()),
        ctxt);
  }
  /**
   * Call start on the life cycle manager.
   */
  public synchronized void start()
  throws Throwable{
    if(lifecycle_manager!=null)
      lifecycle_manager.start();
  }
  /**
   * Call stop on the life cycle manager.
   */
  public synchronized void stop()throws Throwable{
    if(lifecycle_manager != null)
      lifecycle_manager.stop();
  }
  /**
   * Initialize this object by instantiating container and life cycle manager.
   * Relevant servlet context parameters are read.
   * <p>
   * This implementation calls {@link #process(ClassLoader, ServletContext)}
   * for interpreting the configuration file and obtaining the Container instance
   * and LifecycleManager instance.
   * </p>
   * @param cloader the ClassLoader used to load component classes.
   * @param servletContext the servlet context object.
   * @return the Container object instantiated.
   * null is returned if configuration file not found.
   */
  public synchronized Container initContainer(ClassLoader cloader, ServletContext servletContext){
    servletContext.log("Loading Nuts container");
    if(processor!=null){
      throw new IllegalStateException("YanLoader already initialized.");
    }
    try {
      this.processor = process(cloader, servletContext);
      if(this.processor==null){
        return null;
      }
     
      Container parent = loadParentContainer(servletContext);
      this.yan = parent!=null?processor.getContainer().inherit(parent)
        : processor.getContainer();
      this.lifecycle_manager = processor.getLifecycleManager();
      servletContext.setAttribute(CONTAINER_ROOT, this.yan);
      servletContext.setAttribute(LIFECYCLE_MANAGER_ROOT, this.yan);
      processor.preInstantiate(this.yan);
      return this.yan;
    }
    catch (RuntimeException ex) {
      servletContext.log("Container initialization failed", ex);
      servletContext.setAttribute(CONTAINER_ROOT, ex);
      throw ex;
    }
    catch(Exception e){
      servletContext.log("Container initialization failed", e);
      servletContext.setAttribute(CONTAINER_ROOT, e);
      throw new YanException(e);
    }
    catch (Error err) {
      servletContext.log("Container initialization error", err);
      servletContext.setAttribute(CONTAINER_ROOT, err);
      throw err;
    }
  }

  /**
   * Load the parent Container object that's shared among web applications.
   * @param servletContext the servlet context.
   * @return the Container object. or null if not found.
   */
  protected Container loadParentContainer(ServletContext servletContext)
  throws Exception{
    return null;
  }
  /**
   * Create a NutsProcessor object based on the configuration in ServletContext.
   * The configuration file is also parsed and interpreted.
   * <p>
   * This default implementation delegates to {@link #getNutsProcessor(ClassLoader, ResourceLoader, ServletContext)}
   * for constructing the NutsProcessor object.
   * </p>
   * <p>
   * If no ServletContext component is registered, the current ServletContext object
   * is registered as a component in the container.
   * </p>
   * @param cloader the ClassLoader object used to load component classes.
   * @param ctxt the ServletContext object.
   * @return the populated NutsProcessor object.
   * @throws Exception any error.
   */
  protected NutsProcessor process(ClassLoader cloader, ServletContext ctxt)
  throws Exception{
    String config_file = ctxt.getInitParameter(CONFIG_FILE_PARAM);
    if(config_file==null){
      ctxt.log(CONFIG_FILE_PARAM
          +" not specified, looking for default "+DEFAULT_CONFIG_FILE);
      config_file = DEFAULT_CONFIG_FILE;
    }

    final ResourceLoader rloader = new ServletContextResourceLoader(ctxt,
        new ClassLoader2ResourceLoader(cloader));
    final InputStream in = rloader.getResourceAsStream(config_file);
    if(in == null){
      ctxt.log("yan configuration file "+config_file+" not found.");
      return null;
    }
    try{
      final NutsProcessor proc = getNutsProcessor(cloader, rloader, ctxt);
      proc.process(rloader.getResource(config_file), in);
      registerServletContext(proc.getContainer(), ctxt);
      return proc;
    }
    finally{
      in.close();
    }
  }
  /**
   * Register the ServletContext into the container using
   * either {@link WebUtils#DEFAULT_SERVLET_CONTEXT_PROPERTY} or
   * else ServletContext.class as long as there's no ServletContext
   * component already registered.
   * @param container the Yan container object.
   * @param ctxt the ServletContext object.
   */
  protected static void registerServletContext(Container container, ServletContext ctxt){
    if(!container.containsType(ServletContext.class)){
      if(container.containsKey(WebUtils.DEFAULT_SERVLET_CONTEXT_PROPERTY)){
        container.registerValue(ServletContext.class, ctxt);
      }
      else{
        container.registerValue(WebUtils.DEFAULT_SERVLET_CONTEXT_PROPERTY, ctxt);
      }
    }
  }
  /**
   * Construct a NutsProcessor object based on the configuration information
   * stored in ServletContext. And then call {@link #decorateProcessor(NutsProcessor, ServletContext)}
   * to decorate it.
   * @param cloader the ClassLoader object used to load component class.
   * @param rloader the ResourceLoader object used to load resource.
   * @param ctxt the ServletContext object.
   * @return the result NutsProcessor object.
   * @throws Exception any error.
   */
  protected NutsProcessor getNutsProcessor(ClassLoader cloader, ResourceLoader rloader,
      ServletContext ctxt)throws Exception{
    final NutsProcessor proc = new NutsProcessor(cloader, rloader);
    decorateProcessor(proc, ctxt);
    return proc;
  }
  /**
   * Decorate a NutsProcessor object by adding or removing features.
   * <p>
   * This default implementation replaces &lt;bean&gt;, &lt;ctor&gt;
   * and &lt;method&gt; tags with the ones that're aware of the ServletContext.
   * </p>
   * <p>
   * It does so by registering the ServletContext as a service under {@link #SERVLET_CONTEXT_KEY}.
   * The customized tags then look up this service and call "setServletContext()" or
   * any other specified receiver method to set this dependency.
   * </p>
   * <p>
   * Based on whether {@link #USE_SPRING} parameter is set in ServletContext,
   * this implementation calls either {@link #setSpringAware(NutsProcessor, ServletContext)}
   * or {@link #setWebAware(NutsProcessor, ServletContext)} to do the decoration.
   * </p>
   * <p>
   * Subclasses can override this method to provide customized decoration.
   * </p>
   * @param processor the NutsProcessor object to decorate.
   * @param ctxt the ServletContext object.
   * @throws Exception any error.
   */
  protected void decorateProcessor(NutsProcessor processor, ServletContext ctxt)
  throws Exception{
    processor.registerService(SERVLET_CONTEXT_KEY, ctxt);
    String spring_integration = ctxt.getInitParameter(USE_SPRING);
    if(spring_integration!=null && TRUE.equals(spring_integration)){
      setSpringAware(processor, ctxt);
    }
    else{
      setWebAware(processor, ctxt);
    }
  }
  /**
   * Decorate NutsProcessor object with nut classes that integrates Spring framework
   * and also aware of the web infrastructure, i.e. ServletContext.
   * @param processor the NutsProcessor object to decorate.
   * @param ctxt the ServletContext object.
   * @throws Exception any error.
   */
  protected void setSpringAware(NutsProcessor processor, ServletContext ctxt)
  throws Exception{
    SpringNuts.setSpringAware("yan_web_spring", processor, DEFAULT_SPRING_NUTS_FILE);
  }
  /**
   * Decorate NutsProcessor object with nut classes that are aware of the web infrastructure, i.e. ServletContext.
   * @param processor the NutsProcessor object to decorate.
   * @param ctxt the ServletContext object.
   * @throws Exception any error.
   */
  protected void setWebAware(NutsProcessor processor, ServletContext ctxt)
  throws Exception{
    processor.loadNutsMetaResource(DEFAULT_NUTS_FILE);
  }
  /**
   * Destroy the container.
   * @param servletContext the servlet context.
   */
  public synchronized void destroy(ServletContext servletContext){
    if(lifecycle_manager==null) return;
    servletContext.log("Closing Yan root container");
    try{
      lifecycle_manager.dispose();
      this.lifecycle_manager = null;
      this.yan = null;
      this.processor = null;
    }
    catch(Error e){
      servletContext.log("error in container shutdown", e);
      throw e;
    }
    catch(Throwable e){
      servletContext.log("error in container shutdown", e);
    }
  }

}
TOP

Related Classes of jfun.yan.web.YanLoader

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.