Package org.huihoo.willow.core

Source Code of org.huihoo.willow.core.ContainerBase

//----------------------------BEGIN LICENSE----------------------------
/*
* Willow : the Open Source WorkFlow Project
* Distributable under GNU LGPL license by gun.org
*
* Copyright (C) 2004-2010 huihoo.org
* Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com>
*
* ====================================================================
* Project Homepage : http://www.huihoo.org/willow
* Source Forge     : http://sourceforge.net/projects/huihoo
* Mailing list     : willow@lists.sourceforge.net
*/
//----------------------------END  LICENSE-----------------------------
package org.huihoo.willow.core;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.util.ArrayList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.huihoo.willow.Container;
import org.huihoo.willow.Lifecycle;
import org.huihoo.willow.LifecycleException;
import org.huihoo.willow.LifecycleListener;
import org.huihoo.willow.Loader;
import org.huihoo.willow.Logger;
import org.huihoo.willow.util.LifecycleSupport;
import org.huihoo.willow.util.StringManager;


/**
* @author reic
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public abstract class ContainerBase implements Container, Lifecycle, Serializable
{

  protected static Log log =LogFactory.getLog(ContainerBase.class);

  // ----------------------------------------------------- Instance Variables

  /**
   * The debugging detail level for this component.
   */
  protected int debug = 0;

  /**
   * The processor delay for this component.
   */
  protected int backgroundProcessorDelay = 300;

  /**
   * The lifecycle event support for this component.
   */
  protected LifecycleSupport lifecycle = new LifecycleSupport(this);

  /**
   * The container event listeners for this Container.
   */
  protected ArrayList listeners = new ArrayList();

  /**
   * The Loader implementation with which this Container is associated.
   */
  protected Loader loader = null;

  /**
   * The Logger implementation with which this Container is associated.
   */
  protected Logger logger = null;

  /**
   * The human-readable name of this Container.
   */
  protected String name = null;

  /**
   * The parent Container to which this Container is a child.
   */
  protected Container parent = null;

  /**
   * The parent class loader to be configured when we install a Loader.
   */
  protected ClassLoader parentClassLoader = null;
 
  /**
   * The string manager for this package.
   */
  protected static StringManager sm = StringManager.getManager(Constants.PACKAGE);

  /**
   * Has this component been started?
   */
  protected boolean started = false;

  /**
   * The property change support for this component.
   */
  protected PropertyChangeSupport support = new PropertyChangeSupport(this);

  /**
   * The background thread.
   */
  protected Thread thread = null;

  /**
   * The background thread completion semaphore.
   */
  protected boolean threadDone = false;

  // ------------------------------------------------------------- Properties

  /**
   * Return the debugging detail level for this component.
   */
  public int getDebug()
  {

    return (this.debug);

  }

  /**
   * Set the debugging detail level for this component.
   *
   * @param debug The new debugging detail level
   */
  public void setDebug(int debug)
  {

    int oldDebug = this.debug;
    this.debug = debug;
    support.firePropertyChange("debug", new Integer(oldDebug), new Integer(this.debug));

  }

  /**
   * Get the delay between the invocation of the backgroundProcess method on
   * this container and its children. Child containers will not be invoked
   * if their delay value is not negative (which would mean they are using
   * their own thread). Setting this to a positive value will cause
   * a thread to be spawn. After waiting the specified amount of time,
   * the thread will invoke the executePeriodic method on this container
   * and all its children.
   */
  public int getBackgroundProcessorDelay()
  {
    return backgroundProcessorDelay;
  }

  /**
   * Set the delay between the invocation of the execute method on this
   * container and its children.
   *
   * @param delay The delay in seconds between the invocation of
   *              backgroundProcess methods
   */
  public void setBackgroundProcessorDelay(int delay)
  {
    backgroundProcessorDelay = delay;
  }

  /**
   * Return descriptive information about this Container implementation and
   * the corresponding version number, in the format
   * <code>&lt;description&gt;/&lt;version&gt;</code>.
   */
  public String getInfo()
  {
    return this.getClass().getName();
  }

  /**
   * Return the Loader with which this Container is associated.  If there is
   * no associated Loader, return the Loader associated with our parent
   * Container (if any); otherwise, return <code>null</code>.
   */
  public Loader getLoader()
  {

    if (loader != null)
      return (loader);
    if (parent != null)
      return (parent.getLoader());
    return (null);

  }

  /**
   * Set the Loader with which this Container is associated.
   *
   * @param loader The newly associated loader
   */
  public synchronized void setLoader(Loader loader)
  {

    // Change components if necessary
    Loader oldLoader = this.loader;
    if (oldLoader == loader)
      return;
    this.loader = loader;

    // Stop the old component if necessary
    if (started && (oldLoader != null) && (oldLoader instanceof Lifecycle))
    {
      try
      {
        ((Lifecycle) oldLoader).stop();
      }
      catch (LifecycleException e)
      {
        log.error("ContainerBase.setLoader: stop: ", e);
      }
    }

    // Start the new component if necessary
    if (loader != null)
    {
      loader.setContainer(this);
    }
   
    if (started && (loader != null) && (loader instanceof Lifecycle))
    {
      try
      {
        ((Lifecycle) loader).start();
      }
      catch (LifecycleException e)
      {
        log.error("ContainerBase.setLoader: start: ", e);
      }
    }

    // Report this property change to interested listeners
    support.firePropertyChange("loader", oldLoader, this.loader);

  }

  /**
   * Return the Logger with which this Container is associated.  If there is
   * no associated Logger, return the Logger associated with our parent
   * Container (if any); otherwise return <code>null</code>.
   */
  public Logger getLogger()
  {

    if (logger != null)
      return (logger);
    if (parent != null)
      return (parent.getLogger());
    return (null);

  }

  /**
   * Set the Logger with which this Container is associated.
   *
   * @param logger The newly associated Logger
   */
  public synchronized void setLogger(Logger logger)
  {
    // Change components if necessary
    Logger oldLogger = this.logger;
    if (oldLogger == logger)
    {
      return;
    }
   
    this.logger = logger;

    // Stop the old component if necessary
    if (started && (oldLogger != null) && (oldLogger instanceof Lifecycle))
    {
      try
      {
        ((Lifecycle) oldLogger).stop();
      }
      catch (LifecycleException e)
      {
        log.error("ContainerBase.setLogger: stop: ", e);
      }
    }

    // Start the new component if necessary
    if (logger != null)
    {
      logger.setContainer(this);
    }
    if (started && (logger != null) && (logger instanceof Lifecycle))
    {
      try
      {
        ((Lifecycle) logger).start();
      }
      catch (LifecycleException e)
      {
        log.error("ContainerBase.setLogger: start: ", e);
      }
    }

    // Report this property change to interested listeners
    support.firePropertyChange("logger", oldLogger, this.logger);

  }

  /**
   * Return an object which may be utilized for mapping to this component.
   */
  public Object getMappingObject()
  {
    return this;
  }

  /**
   * Return a name string (suitable for use by humans) that describes this
   * Container.  Within the set of child containers belonging to a particular
   * parent, Container names must be unique.
   */
  public String getName()
  {

    return (name);

  }

  /**
   * Set a name string (suitable for use by humans) that describes this
   * Container.  Within the set of child containers belonging to a particular
   * parent, Container names must be unique.
   *
   * @param name New name of this container
   *
   * @exception IllegalStateException if this Container has already been
   *  added to the children of a parent Container (after which the name
   *  may not be changed)
   */
  public void setName(String name)
  {

    String oldName = this.name;
    this.name = name;
    support.firePropertyChange("name", oldName, this.name);
  }

  /**
   * Return the Container for which this Container is a child, if there is
   * one.  If there is no defined parent, return <code>null</code>.
   */
  public Container getParent()
  {

    return (parent);

  }

  /**
   * Set the parent Container to which this Container is being added as a
   * child.  This Container may refuse to become attached to the specified
   * Container by throwing an exception.
   *
   * @param container Container to which this Container is being added
   *  as a child
   *
   * @exception IllegalArgumentException if this Container refuses to become
   *  attached to the specified Container
   */
  public void setParent(Container container)
  {

    Container oldParent = this.parent;
    this.parent = container;
    support.firePropertyChange("parent", oldParent, this.parent);

  }

  /**
   * Return the parent class loader (if any) for this web application.
   * This call is meaningful only <strong>after</strong> a Loader has
   * been configured.
   */
  public ClassLoader getParentClassLoader()
  {
    if (parentClassLoader != null)
      return (parentClassLoader);
    if (parent != null)
    {
      return (parent.getParentClassLoader());
    }
    return (ClassLoader.getSystemClassLoader());

  }

  /**
   * Set the parent class loader (if any) for this web application.
   * This call is meaningful only <strong>before</strong> a Loader has
   * been configured, and the specified value (if non-null) should be
   * passed as an argument to the class loader constructor.
   *
   *
   * @param parent The new parent class loader
   */
  public void setParentClassLoader(ClassLoader parent)
  {
    ClassLoader oldParentClassLoader = this.parentClassLoader;
    this.parentClassLoader = parent;
    support.firePropertyChange("parentClassLoader", oldParentClassLoader, this.parentClassLoader);

  }
  // ------------------------------------------------------ Container Methods

  /**
   * Add a property change listener to this component.
   *
   * @param listener The listener to add
   */
  public void addPropertyChangeListener(PropertyChangeListener listener)
  {

    support.addPropertyChangeListener(listener);

  }

  /**
   * Remove a property change listener from this component.
   *
   * @param listener The listener to remove
   */
  public void removePropertyChangeListener(PropertyChangeListener listener)
  {

    support.removePropertyChangeListener(listener);

  }

  // ------------------------------------------------------ Lifecycle Methods

  /**
   * Add a lifecycle event listener to this component.
   *
   * @param listener The listener to add
   */
  public void addLifecycleListener(LifecycleListener listener)
  {

    lifecycle.addLifecycleListener(listener);

  }

  /**
   * Get the lifecycle listeners associated with this lifecycle. If this
   * Lifecycle has no listeners registered, a zero-length array is returned.
   */
  public LifecycleListener[] findLifecycleListeners()
  {

    return lifecycle.findLifecycleListeners();

  }

  /**
   * Remove a lifecycle event listener from this component.
   *
   * @param listener The listener to remove
   */
  public void removeLifecycleListener(LifecycleListener listener)
  {

    lifecycle.removeLifecycleListener(listener);

  }

  /**
   * Prepare for active use of the public methods of this Component.
   *
   * @exception LifecycleException if this component detects a fatal error
   *  that prevents it from being started
   */
  public synchronized void start() throws LifecycleException
  {   
    // Validate and update our current component state
    if (started)
    {
      log.info(sm.getString("containerBase.alreadyStarted", logName()));
      return;
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

    started = true;
   
    // Start our subordinate components, if any
    if ((loader != null) && (loader instanceof Lifecycle))
    {
      ((Lifecycle) loader).start();
    }
      
    if ((logger != null) && (logger instanceof Lifecycle))
    {     
      ((Lifecycle) logger).start();
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(START_EVENT, null);

    // Start our thread
    threadStart();

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

  }

  /**
   * Gracefully shut down active use of the public methods of this Component.
   *
   * @exception LifecycleException if this component detects a fatal error
   *  that needs to be reported
   */
  public synchronized void stop() throws LifecycleException
  {

    // Validate and update our current component state
    if (!started)
    {
      log.info(sm.getString("containerBase.notStarted", logName()));
      return;
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

    // Stop our thread
    threadStop();

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(STOP_EVENT, null);
    started = false;

    // Stop our subordinate components, if any
    if ((logger != null) && (logger instanceof Lifecycle))
    {
      ((Lifecycle) logger).stop();
    }
   
    if ((loader != null) && (loader instanceof Lifecycle))
    {
      ((Lifecycle) loader).stop();
    }

    // Notify our interested LifecycleListeners
    lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

  }

  /**
   * Execute a periodic task, such as reloading, etc. This method will be
   * invoked inside the classloading context of this container. Unexpected
   * throwables will be caught and logged.
   */
  public void backgroundProcess()
  {
  }

  // ------------------------------------------------------ Protected Methods

  /**
   * Log the specified message to our current Logger (if any).
   *
   * @param message Message to be logged
   */
  protected void log(String message)
  {

     Logger logger = getLogger();
     if (logger != null)
    {
      logger.log(logName() + ": " + message);
    }
     else
      {
        log.info(message);
      }
  }

  /**
   * Log the specified message and exception to our current Logger
   * (if any).
   *
   * @param message Message to be logged
   * @param throwable Related exception
   */
  protected void log(String message, Throwable throwable)
  {

    Logger logger = getLogger();
    if (logger != null)
    {
      logger.log(logName() + ": " + message, throwable);
    }
    else
    {
      log.error(message, throwable);
    }

  }

  /**
   * Return the abbreviated name of this container for logging messsages
   */
  protected String logName()
  {

    String className = this.getClass().getName();
    int period = className.lastIndexOf(".");
    if (period >= 0)
      className = className.substring(period + 1);
    return (className + "[" + getName() + "]");

  }

  /**
   * Start the background thread that will periodically check for
   * session timeouts.
   */
  protected void threadStart()
  {
  }

  /**
   * Stop the background thread that is periodically checking for
   * session timeouts.
   */
  protected void threadStop()
  {
  }
}
TOP

Related Classes of org.huihoo.willow.core.ContainerBase

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.