You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by le...@apache.org on 2002/08/21 08:03:16 UTC

cvs commit: jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet AbstractReferenceProxy.java AbstractReferenceProxyLatch.java ComponentManagerReferenceProxy.java ExcaliburComponentManagerServlet.java InstrumentManagerReferenceProxy.java LoggerManagerReferenceProxy.java ReferenceProxy.java package.html

leif        2002/08/20 23:03:16

  Modified:    component build.xml default.properties
  Added:       component/src/java/org/apache/avalon/excalibur/component/servlet
                        AbstractReferenceProxy.java
                        AbstractReferenceProxyLatch.java
                        ComponentManagerReferenceProxy.java
                        ExcaliburComponentManagerServlet.java
                        InstrumentManagerReferenceProxy.java
                        LoggerManagerReferenceProxy.java
                        ReferenceProxy.java package.html
  Log:
  Added an ExcaliburComponentManagerServlet utility class.  It is only built if
  servlet.jar is present and then stored in its own jar file.  See the javadocs for
  details on its use.
  
  Revision  Changes    Path
  1.25      +71 -4     jakarta-avalon-excalibur/component/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/component/build.xml,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- build.xml	10 Aug 2002 21:14:33 -0000	1.24
  +++ build.xml	21 Aug 2002 06:03:15 -0000	1.25
  @@ -22,6 +22,10 @@
           <pathelement location="${excalibur-instrument-manager-interfaces.jar}"/>
           <pathelement location="${excalibur-pool.jar}"/>
           <pathelement location="${checkstyle.jar}"/>
  +
  +        <!-- Optional jars -->
  +        <pathelement location="${servlet.jar}"/>
  +        
           <pathelement path="${java.class.path}"/>
       </path>
   
  @@ -47,7 +51,28 @@
       <target name="main" depends="jar" description="Build the project"/>
       <target name="rebuild" depends="clean,main" description="Rebuild the project"/>
   
  -    <target name="dependencies" description="Check dependencies" unless="skip.dependencies">
  +    <!-- Checks the environment for existing resources -->
  +    <target name="check-environment">
  +        <available property="servlet.present" classname="javax.servlet.Servlet">
  +            <classpath refid="project.class.path"/>
  +        </available>
  +    </target>
  +    
  +    <!-- Check that if we want servlet logging support, our logkit.jar has it enabled too -->
  +    <target name="dependencies.servlet" if="servlet.present">
  +            <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkRequiredClass">
  +                <property name="proj.jar.name" value="logkit.jar"/>
  +                <property name="class" value="org.apache.log.output.ServletOutputLogTarget"/>
  +                <property name="classpath" value="${cp}"/>
  +                <property name="remedy" value="Recompile ${Name} with servlet support enabled, or disable servlet support in ${Name} by setting a blank 'servlet.jar' property in ant.properties"/>
  +            </ant>
  +        </target>
  +
  +    <target name="dependencies.optional"
  +        depends="check-environment,dependencies.servlet"
  +        description="Checks if dependencies for optional components are present"/>
  +
  +    <target name="dependencies" depends="dependencies.optional" description="Check dependencies" unless="skip.dependencies">
           <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkCommon"/>
           <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkLogkit"/>
           <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkFramework"/>
  @@ -67,10 +92,25 @@
           <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkTestcase"/>
           <ant antfile="${depchecker.prefix}/depchecker.xml" target="checkInstrument"/>
       </target>
  -
  +    
  +    <target name="servlet-warn" unless="servlet.present"
  +        description="Outputs a warning if javax.servlet.* classes are missing during compilation">
  +        <echo>*********************************************************************************</echo>
  +        <echo>*</echo>
  +        <echo>*  Classes needed to compile servlet classe are not available.</echo>
  +        <echo>*  Excalibur Component should still build without them.</echo>
  +        <echo>*</echo>
  +        <echo>*  Recovery:</echo>
  +        <echo>*  Get servlet.jar from http://jakarta.apache.org/builds/jakarta-tomcat/release/,</echo>
  +        <echo>*  or from http://gump.covalent.net/jars/latest/jakarta-servletapi-4/servlet.jar,</echo>
  +        <echo>*  and place them in ${lib.repo}</echo>
  +        <echo>*</echo>
  +        <echo>*********************************************************************************</echo>
  +        <echo/>
  +    </target>
   
       <!-- Compiles the source code -->
  -    <target name="compile" depends="dependencies" description="Compiles the source code">
  +    <target name="compile" depends="dependencies, servlet-warn" description="Compiles the source code">
   
           <mkdir dir="${build.classes}"/>
   
  @@ -83,6 +123,8 @@
               target="1.2">
               <classpath refid="project.class.path" />
               <include name="**/*.java"/>
  +            <exclude name="org/apache/avalon/excalibur/component/servlet/**"
  +                     unless="servlet.present"/>
           </javac>
   
           <!-- copy resources to same location as .class files -->
  @@ -137,8 +179,32 @@
           </copy>
       </target>
   
  +    <!-- Creates all the servlet .jar file -->
  +    <target name="jar-servlet" depends="compile, prepare-conf" if="servlet.present"
  +        description="Generates the servlet jar file">
  +
  +        <mkdir dir="${build.lib}"/>
  +
  +        <jar jarfile="${build.lib}/${jar.servlet.name}"
  +            basedir="${build.classes}"
  +            compress="${build.compress}">
  +            <manifest>
  +              <attribute name="Extension-Name" value="${name.servlet}"/>
  +              <attribute name="Specification-Vendor" value="Apache Software Foundation"/>
  +              <attribute name="Specification-Version" value="1.0"/>
  +              <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
  +              <attribute name="Implementation-Version" value="${package-version}"/>
  +            </manifest>
  +            <include name="**/component/servlet/**"/>
  +            <exclude name="**/test/**"/>
  +            <zipfileset dir="${build.conf}" prefix="META-INF/">
  +                <include name="LICENSE.txt"/>
  +            </zipfileset>
  +        </jar>
  +    </target>
  +    
       <!-- Creates all the .jar file -->
  -    <target name="jar" depends="compile, prepare-conf" description="Generates the jar files">
  +    <target name="jar" depends="compile, prepare-conf, jar-servlet" description="Generates the jar files">
   
           <mkdir dir="${build.lib}"/>
   
  @@ -152,6 +218,7 @@
                 <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
                 <attribute name="Implementation-Version" value="${package-version}"/>
               </manifest>
  +            <exclude name="**/component/servlet/**"/>
               <exclude name="**/test/**"/>
               <zipfileset dir="${build.conf}" prefix="META-INF/">
                   <include name="LICENSE.txt"/>
  
  
  
  1.12      +4 -0      jakarta-avalon-excalibur/component/default.properties
  
  Index: default.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-avalon-excalibur/component/default.properties,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- default.properties	14 Aug 2002 14:58:23 -0000	1.11
  +++ default.properties	21 Aug 2002 06:03:16 -0000	1.12
  @@ -6,6 +6,7 @@
   # Not user-editable; use ant.properties files instead
   
   name=excalibur-component
  +name.servlet=excalibur-component-servlet
   Name=Excalibur Component
   dir-name=component
   version=1.0
  @@ -67,6 +68,8 @@
   # --------------------------------------------------
   #                OPTIONAL LIBRARIES
   # --------------------------------------------------
  +# For optional ComponentManagerCreatorServlet support.
  +servlet.jar=${lib.repo}/servletapi-2.2.jar
   
   # For unit testing:
   
  @@ -129,6 +132,7 @@
   
   #  name of jar file
   jar.name = ${name}-${version}.jar
  +jar.servlet.name = ${name}-servlet-${version}.jar
   
   #  property indicating directory where all distribution archives are placed
   dist.base = distributions
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractReferenceProxy.java
  
  Index: AbstractReferenceProxy.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  /**
   * Common Reference Proxy implementation.
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   * @since 4.0
   */
  abstract class AbstractReferenceProxy
      implements ReferenceProxy
  {
      /** AbstractReferenceProxyLatch which owns the proxy. */
      private AbstractReferenceProxyLatch m_latch;
      
      /** Name of the proxy. */
      private String m_name;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Create a new AbstractReferenceProxy around a given object.
       *
       * @param object The object to protect with the proxy.
       * @param latch ReferenceProxyLatch which owns the proxy.
       */
      AbstractReferenceProxy( AbstractReferenceProxyLatch latch, String name )
      {
          m_latch = latch;
          m_name = name;
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Returns the name of the proxy.
       *
       * @return The name of the proxy.
       */
      String getName()
      {
          return m_name;
      }
      
      /**
       * Called when all references to the ReferenceProxy have been removed.
       */
      protected void finalize()
      {
          m_latch.notifyFinalized( this );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/AbstractReferenceProxyLatch.java
  
  Index: AbstractReferenceProxyLatch.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  import org.apache.avalon.excalibur.logger.LoggerManager;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  import org.apache.excalibur.instrument.InstrumentManager;
  
  /**
   * Servlet containers do not have a guaranteed order in which servlets will
   *  be destroyed like there is with initialization.  This means that the
   *  servlet which created and controls an object may be destroyed while other
   *  servlets are still using it. This presents a problem in environments where
   *  common objects are placed into the ServletContext and used by more than
   *  one servlet.
   *
   * To solve this problem an object is placed into the ServletContext wrapped
   *  in a ReferenceProxy.  Whe nthe servlet is ready to be shutdown.  This
   *  proxy latch is used to wait until all other servlets are done with the
   *  components before disposing them.
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   * @since 4.0
   */
  abstract class AbstractReferenceProxyLatch
      extends AbstractLogEnabled
  {
      /** Name of the latch */
      private String m_name;
      
      /** Number of registered proxies which have not yet been finalized. */
      private int m_waitingProxies;
      
      /** Flag that keeps track of when the trigger is requested. */
      private boolean m_triggerRequested;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Create a new ReferenceProxyLatch.
       */
      public AbstractReferenceProxyLatch()
      {
      }
  
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * @param object Object to be protected.
       * @param name Name of the object.
       * @return A new ReferenceProxy instance protecting the object.
       */
      public ReferenceProxy createProxy( Object object, String name )
      {
          m_name = name;
          
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "Creating a proxy named '" + m_name + "' for a "
                  + object.getClass().getName() );
          }
          
          AbstractReferenceProxy proxy;
          if ( object instanceof LoggerManager )
          {
              proxy = new LoggerManagerReferenceProxy( (LoggerManager)object, this, name );
          }
          else if ( object instanceof ComponentManager )
          {
              proxy = new ComponentManagerReferenceProxy( (ComponentManager)object, this, name );
          }
          else if ( object instanceof InstrumentManager )
          {
              proxy = new InstrumentManagerReferenceProxy( (InstrumentManager)object, this, name );
          }
          else
          {
              throw new IllegalArgumentException( "Don't know how to create a proxy for a "
                  + object.getClass().getName() );
          }
          
          m_waitingProxies++;
          
          return proxy;
      }
      
      /**
       * Request that the triggered() method be called by asking all of the proxies
       *  managed by the latch to notify that they are no longer accepting requests
       *  to reference their internal objects.
       */
      public void requestTrigger()
      {
          int waitingProxies;
          synchronized( this )
          {
              waitingProxies = m_waitingProxies;
          }
          
          if ( waitingProxies > 0 )
          {
              // Invoke garbage collection so that any proxies will be GCed if possible.
              System.gc();
              
              // Give the JVM a little time for the proxies to be GCed
              try
              {
                  Thread.sleep( 1500 );
              }
              catch ( InterruptedException e ) 
              {
              }
          }
          
          synchronized( this )
          {
              m_triggerRequested = true;
              waitingProxies = m_waitingProxies;
          }
          
          if ( waitingProxies > 0 )
          {
              if ( getLogger().isDebugEnabled() )
              {
                  getLogger().debug( "Trigger requested.  " + waitingProxies
                      + " proxies have not yet been finalized." );
              }
          }
          else
          {
              if ( getLogger().isDebugEnabled() )
              {
                  getLogger().debug( "Trigger requested.  All proxies have been finalized." );
              }
              
              try
              {
                  triggered();
              }
              catch ( Exception e )
              {
                  getLogger().error( "Encountered an unexpected error in the trigger callback:", e );
              }
          }
      }
      
      /**
       * Called by a proxy when it is finalized.
       *
       * @proxy proxy The AbstractRefernceProxy that is ready.
       */
      void notifyFinalized( AbstractReferenceProxy proxy )
      {
          synchronized( this )
          {
              m_waitingProxies--;
              
              // Was that the last proxy?
              if ( m_waitingProxies > 0 )
              {
                  if ( getLogger().isDebugEnabled() )
                  {
                      getLogger().debug( "The proxy named '" + proxy.getName() + "' was finalized.  "
                          + m_waitingProxies + " proxies remaining." );
                  }
                  return;
              }
          }
          
          // Do this outside the synchronization block.
          if ( getLogger().isDebugEnabled() )
          {
              getLogger().debug( "The proxy named '" + proxy.getName() + "' was finalized.  "
                  + "All proxies have been finalized." );
          }
          
          if ( m_triggerRequested )
          {
              try
              {
                  triggered();
              }
              catch ( Exception e )
              {
                  getLogger().error( "Encountered an unexpected error in the trigger callback:", e );
              }
          }
      }
      
      /**
       * Called when all of the proxies have notified that they are done.
       */
      public abstract void triggered() throws Exception;
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ComponentManagerReferenceProxy.java
  
  Index: ComponentManagerReferenceProxy.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  import org.apache.avalon.framework.component.Component;
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  
  /**
   * Reference Proxy to a ComponentManager
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   */
  final class ComponentManagerReferenceProxy
      extends AbstractReferenceProxy
      implements ComponentManager
  {
      private ComponentManager m_componentManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Create a new proxy.
       *
       * @param componentManager ComponentManager being proxied.
       * @param latch Latch wich will be notified when this proxy is finalized.
       * @param name Name of the proxy.
       */
      ComponentManagerReferenceProxy( ComponentManager componentManager,
                                      AbstractReferenceProxyLatch latch,
                                      String name )
      {
          super( latch, name );
          m_componentManager = componentManager;
      }
      
      /*---------------------------------------------------------------
       * ComponentManager Methods
       *-------------------------------------------------------------*/
      /**
       * Get the <code>Component</code> associated with the given role.  For
       * instance, If the <code>ComponentManager</code> had a
       * <code>LoggerComponent</code> stored and referenced by role, I would use
       * the following call:
       * <pre>
       * try
       * {
       *     MyComponent log;
       *     myComponent = (MyComponent) manager.lookup(MyComponent.ROLE);
       * }
       * catch (...)
       * {
       *     ...
       * }
       * </pre>
       *
       * @param role The role name of the <code>Component</code> to retrieve.
       * @return the desired component
       * @throws ComponentException if an error occurs
       */
      public Component lookup( String role )
          throws ComponentException
      {
          return m_componentManager.lookup( role );
      }
  
      /**
       * Check to see if a <code>Component</code> exists for a role.
       *
       * @param role  a string identifying the role to check.
       * @return True if the component exists, False if it does not.
       */
      public boolean hasComponent( String role )
      {
          return m_componentManager.hasComponent( role );
      }
  
      /**
       * Return the <code>Component</code> when you are finished with it.  This
       * allows the <code>ComponentManager</code> to handle the End-Of-Life Lifecycle
       * events associated with the Component.  Please note, that no Exceptions
       * should be thrown at this point.  This is to allow easy use of the
       * ComponentManager system without having to trap Exceptions on a release.
       *
       * @param component The Component we are releasing.
       */
      public void release( Component component )
      {
          m_componentManager.release( component );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ExcaliburComponentManagerServlet.java
  
  Index: ExcaliburComponentManagerServlet.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  import java.io.InputStream;
  import java.io.IOException;
  
  import javax.servlet.GenericServlet;
  import javax.servlet.ServletConfig;
  import javax.servlet.ServletContext;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.UnavailableException;
  
  import org.apache.avalon.excalibur.component.ExcaliburComponentManagerCreator;
  import org.apache.avalon.excalibur.logger.LoggerManager;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.container.ContainerUtil;
  
  import org.apache.excalibur.instrument.InstrumentManager;
  
  /**
   * Makes it possible for servlets to work with Avalon components
   *  without having to do any coding to setup and manage the
   *  lifecycle of the ComponentManager.
   * <p>
   * To make use of the ExcaliburComponentManagerServet.  You will
   *  need to define the servlet in your web.xml file as follows:
   * <pre>
   *  &lt;!-- ExcaliburComponentManagerServlet (for initializing ComponentManager).   --&gt;
   *  &lt;servlet&gt;
   *      &lt;servlet-name&gt;ExcaliburComponentManagerServlet&lt;/servlet-name&gt;
   *      &lt;display-name&gt;ExcaliburComponentManagerServlet&lt;/display-name&gt;
   *      &lt;description&gt;Creates component manager, does not service requests.&lt;/description&gt;
   *      &lt;servlet-class&gt;
   *          org.apache.avalon.excalibur.component.servlet.ExcaliburComponentManagerServlet
   *      &lt;/servlet-class&gt;
   *
   *      &lt;!-- This parameter points to the logkit configuration file.             --&gt;
   *      &lt;!-- Note that the path is specified in absolute notation but it will be --&gt;
   *      &lt;!-- resolved relative to the servlets webapp context path               --&gt;
   *      &lt;init-param&gt;
   *          &lt;param-name&gt;logkit&lt;/param-name&gt;
   *          &lt;param-value&gt;/WEB-INF/logkit.xml&lt;/param-value&gt;
   *      &lt;/init-param&gt;
   *
   *      &lt;!-- This parameter points to the components configuration file.         --&gt;
   *      &lt;init-param&gt;
   *          &lt;param-name&gt;components&lt;/param-name&gt;
   *          &lt;param-value&gt;/WEB-INF/components.xml&lt;/param-value&gt;
   *      &lt;/init-param&gt;
   *
   *      &lt;!-- Roles file supplements configuration file to make the latter        --&gt;
   *      &lt;!-- more readable. Most likely you don't want to change the roles       --&gt;
   *      &lt;!-- file --&gt;
   *      &lt;init-param&gt;
   *          &lt;param-name&gt;roles&lt;/param-name&gt;
   *          &lt;param-value&gt;/WEB-INF/roles.xml&lt;/param-value&gt;
   *      &lt;/init-param&gt;
   *
   *      &lt;!-- This parameter points to the instrument manager configuration file. --&gt;
   *      &lt;init-param&gt;
   *          &lt;param-name&gt;instrument&lt;/param-name&gt;
   *          &lt;param-value&gt;/WEB-INF/instrument.xml&lt;/param-value&gt;
   *      &lt;/init-param&gt;
   *
   *      &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
   *  &lt;/servlet&gt;
   * </pre>
   * Please pay particular attention to the load-on-startup element.  It is used
   * to control the order in which servlets are started by the servlet engine.
   * It must have a value which is less than any other servlets making use of
   * the ComponentManager.  This is to ensure that the ComponentManager is
   * initialized before any other servlets attempt to start using it.
   * <p>
   * All of the configuration files are located in the WEB-INF directory by
   * default.  The instrument configuration file is optional.  Please see the
   * {@link org.apache.avalon.excalibur.component.ExcaliburComponentManagerCreator}
   * class for details on what goes into these configuration files.  Note that
   * the lifecycle of the ExcaliburComponentManagerCreator is managed automatically
   * by this servlet, so there is no need to access the class directly.
   * <p>
   * Once the servlet has been configured, other servlets may gain access to
   * the ComponentManager, InstrumentManager and LoggerManager via the
   * ServletContext using the following code within a servlet:
   * <pre>
   *  // Get a reference to the ServletContext
   *  ServletContext servletContext = getServletContext();
   *
   *  // Acquire the LoggerManager
   *  LoggerManager loggerManager =
   *      (LoggerManager)m_servletContext.getAttribute( LoggerManager.class.getName() );
   *
   *  // Acquire the InstrumentManager
   *  InstrumentManager instrumentManager =
   *      (InstrumentManager)m_servletContext.getAttribute( InstrumentManager.class.getName() );
   *
   *  // Acquire the ComponentManager
   *  ComponentManager componentManager =
   *      (ComponentManager)m_servletContext.getAttribute( ComponentManager.class.getName() );
   * </pre>
   * The ExcaliburComponentManagerServlet makes use of a proxy system to manage
   * reference to the above managers, so it is not necessary to release them
   * when a servlet is done using them.
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   * @since 4.0
   */
  public class ExcaliburComponentManagerServlet
      extends GenericServlet
  {
      private ExcaliburComponentManagerCreator m_componentManagerCreator;
      
      /** Latch used to shutdown the ExcaliburComponentManagerCreator cleanly. */
      private Latch m_latch;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      
      /*---------------------------------------------------------------
       * GenericServlet Methods
       *-------------------------------------------------------------*/
      /**
       * Builds the component manager and stores references to the
       *  ComponentManager, LoggerManager, and InstrumentManager into
       *  the ServletContext.
       *
       * @param servletConfig Servlet configuration
       *
       * @throws ServletException If there are any problems initializing the
       *                          servlet.
       */
      public void init( ServletConfig servletConfig ) throws ServletException
      {
          super.init( servletConfig );
          
          //System.out.println( "ExcaliburComponentManagerServlet.init() BEGIN" );
          ServletContext servletContext = getServletContext();
          
          InputStream loggerManagerConfigStream = null;
          InputStream roleManagerConfigStream = null;
          InputStream componentManagerConfigStream = null;
          InputStream instrumentManagerConfigStream = null;
          try
          {
              loggerManagerConfigStream =
                  getStreamFromParameter( servletConfig, "logkit", true );
              roleManagerConfigStream =
                  getStreamFromParameter( servletConfig, "roles", true );
              componentManagerConfigStream =
                  getStreamFromParameter( servletConfig, "components", true );
              instrumentManagerConfigStream =
                  getStreamFromParameter( servletConfig, "instrument", false );
              
              // Create the ComponentManagerCreator
              try
              {
                  m_componentManagerCreator = new ExcaliburComponentManagerCreator(
                      null,
                      loggerManagerConfigStream,
                      roleManagerConfigStream,
                      componentManagerConfigStream,
                      instrumentManagerConfigStream );
              }
              catch ( Exception e )
              {
                  String msg = "Unable to create the ComponentManagerCreator.  "
                      + "Most likely a comfiguration problem.";
                  throw new ServletException( msg, e );
              }
          }
          finally
          {
              // Close the resource streams
              try
              {
                  if ( loggerManagerConfigStream != null )
                  {
                      loggerManagerConfigStream.close();
                  }
                  if ( roleManagerConfigStream != null )
                  {
                      roleManagerConfigStream.close();
                  }
                  if ( componentManagerConfigStream != null )
                  {
                      componentManagerConfigStream.close();
                  }
                  if ( instrumentManagerConfigStream != null )
                  {
                      instrumentManagerConfigStream.close();
                  }
              }
              catch ( IOException e )
              {
                  throw new ServletException( "Encountered an error closing resource streams.", e );
              }
          }
          
          LoggerManager loggerManager = m_componentManagerCreator.getLoggerManager();
          
          // A series of ReferenceProxies which will be used to access the ComponentManager
          //  and other managers created by the ComponentManagerCreator must be created.
          //  This is necessary because the order in which servlets are shut down by a
          //  ServletContainer can not be controlled.  If a manager is disposed before all
          //  servlets have released their references to it, then errors can result.
          
          // Create the latch which will manager the ReferenceProxies.
          m_latch = new Latch( m_componentManagerCreator );
          m_latch.enableLogging( loggerManager.getLoggerForCategory( "system.ecmservlet" ) );
          
          // Create the actual ReferenceProxies.
          ReferenceProxy loggerManagerProxy = m_latch.createProxy(
              loggerManager, "LoggerManager" );
          ReferenceProxy componentManagerProxy = m_latch.createProxy(
              m_componentManagerCreator.getComponentManager(), "ComponentManager" );
          ReferenceProxy instrumentManagerProxy = m_latch.createProxy(
              m_componentManagerCreator.getInstrumentManager(), "InstrumentManager" );
          
          // Store references to the proxies in the ServletContext so that other servlets can gain
          //  access to them
          servletContext.setAttribute( LoggerManager.class.getName(),     loggerManagerProxy );
          servletContext.setAttribute( ComponentManager.class.getName(),  componentManagerProxy );
          servletContext.setAttribute( InstrumentManager.class.getName(), instrumentManagerProxy );
          
          //System.out.println( "ExcaliburComponentManagerServlet.init() END" );
      }
  
      /**
       * Called by the servlet container to destroy the servlet.
       */
      public void destroy()
      {
          //System.out.println( "ExcaliburComponentManagerServlet.destroy() BEGIN" );
          
          ServletContext servletContext = getServletContext();
          
          // Remove the references to the managers from the servlet context.
          servletContext.removeAttribute( LoggerManager.class.getName() );
          servletContext.removeAttribute( ComponentManager.class.getName() );
          servletContext.removeAttribute( InstrumentManager.class.getName() );
          
          // Tell the latch that we are ready for it do dispose of the ECMC
          m_latch.requestTrigger();
          
          //System.out.println( "ExcaliburComponentManagerServlet.destroy() END" );
      }
      
      /**
       * This servlet does not accept requests.  It will complain if called.
       *
       * @param req servlet request
       * @param res servlet response
       *
       * @throws UnavailableException always
       */
      public void service( ServletRequest servletRequest, ServletResponse servletResponse )
          throws UnavailableException
      {
          throw new UnavailableException( getClass().getName() + " does not except service requests." );
      }
      
      /*---------------------------------------------------------------
       * Methods
       *-------------------------------------------------------------*/
      /**
       * Looks up a specified resource name and returns it as an InputStream.
       *  It is the responsibility of the caller to close the stream.
       *
       * @param servletConfig ServletConfig.
       * @param resourceName Name of the resource to be loaded.
       * @param required True if an error should be thrown if the property is missing.
       *
       * @return InputStream used to read the contents of the resource.
       *
       * @throws ServletException If the specified resource does not exist,
       *                          or could not be opened.
       */
      private InputStream getStreamFromParameter( ServletConfig servletConfig,
                                                  String resourceName,
                                                  boolean required )
              throws ServletException {
  
          String configFileName = servletConfig.getInitParameter( resourceName );
  
          if ( configFileName == null ) {
              if ( required )
              {
                  throw new ServletException( resourceName
                      + " parameter must be provided in servlet configuration." );
              }
              else
              {
                  return null;
              }
          }
  
          ServletContext servletContext = servletConfig.getServletContext();
  
          log( "Attempting to access resource: " + configFileName );
  
          InputStream is = servletContext.getResourceAsStream( configFileName );
  
          if ( is == null ) {
              throw new ServletException( "Resource '" + configFileName + "' is not available." );
          }
  
          return is;
      }
      
      /*---------------------------------------------------------------
       * Private Classes
       *-------------------------------------------------------------*/
      private static class Latch
          extends AbstractReferenceProxyLatch
      {
          ExcaliburComponentManagerCreator m_componentManagerCreator;
          
          /*---------------------------------------------------------------
           * Constructors
           *-------------------------------------------------------------*/
          /**
           * Create a new Latch.
           *
           * @param ecmc The ExcaliburComponentManagerCreator to be disposed
           *             when all proxies are done.
           */
          Latch( ExcaliburComponentManagerCreator componentManagerCreator )
          {
              m_componentManagerCreator = componentManagerCreator;
          }
          
          /*---------------------------------------------------------------
           * AbstractReferenceProxyLatch Methods
           *-------------------------------------------------------------*/
          /**
           * Called when all of the proxies have notified that they are done.
           */
          public void triggered()
              throws Exception
          {
              //System.out.println( "ExcaliburComponentManagerServlet.Latch.triggered() BEGIN" );
              ContainerUtil.shutdown( m_componentManagerCreator );
              //System.out.println( "ExcaliburComponentManagerServlet.Latch.triggered() END" );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/InstrumentManagerReferenceProxy.java
  
  Index: InstrumentManagerReferenceProxy.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  import org.apache.excalibur.instrument.Instrumentable;
  import org.apache.excalibur.instrument.InstrumentManager;
  
  /**
   * Reference Proxy to an InstrumentManager
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   */
  final class InstrumentManagerReferenceProxy
      extends AbstractReferenceProxy
      implements InstrumentManager
  {
      private InstrumentManager m_instrumentManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Create a new proxy.
       *
       * @param instrumentManager InstrumentManager being proxied.
       * @param latch Latch wich will be notified when this proxy is finalized.
       * @param name Name of the proxy.
       */
      InstrumentManagerReferenceProxy( InstrumentManager instrumentManager,
                                       AbstractReferenceProxyLatch latch,
                                       String name )
      {
          super( latch, name );
          m_instrumentManager = instrumentManager;
      }
      
      /*---------------------------------------------------------------
       * InstrumentManager Methods
       *-------------------------------------------------------------*/
      /**
       * Instrumentable to be registered with the instrument manager.  Should be
       *  called whenever an Instrumentable is created.  The '.' character is
       *  used to denote a child Instrumentable and can be used to register the
       *  instrumentable at a specific point in an instrumentable hierarchy.
       *
       * @param instrumentable Instrumentable to register with the InstrumentManager.
       * @param instrumentableName The name to use when registering the Instrumentable.
       *
       * @throws Exception If there were any problems registering the Instrumentable.
       */
      public void registerInstrumentable( Instrumentable instrumentable, String instrumentableName )
          throws Exception
      {
          m_instrumentManager.registerInstrumentable( instrumentable, instrumentableName );
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/LoggerManagerReferenceProxy.java
  
  Index: LoggerManagerReferenceProxy.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  import org.apache.avalon.excalibur.logger.LoggerManager;
  
  import org.apache.avalon.framework.logger.Logger;
  
  /**
   * Reference Proxy to a LoggerManager
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   */
  final class LoggerManagerReferenceProxy
      extends AbstractReferenceProxy
      implements LoggerManager
  {
      private LoggerManager m_loggerManager;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Create a new proxy.
       *
       * @param componentManager LoggerManager being proxied.
       * @param latch Latch wich will be notified when this proxy is finalized.
       * @param name Name of the proxy.
       */
      LoggerManagerReferenceProxy( LoggerManager loggerManager,
                                   AbstractReferenceProxyLatch latch,
                                   String name )
      {
          super( latch, name );
          m_loggerManager = loggerManager;
      }
      
      /*---------------------------------------------------------------
       * LoggerManager Methods
       *-------------------------------------------------------------*/
      /**
       * Return the Logger for the specified category.
       */
      public Logger getLoggerForCategory( String categoryName )
      {
          return m_loggerManager.getLoggerForCategory( categoryName );
      }
  
      /**
       * Return the default Logger.  This is basically the same
       * as getting the Logger for the "" category.
       */
      public Logger getDefaultLogger()
      {
          return m_loggerManager.getDefaultLogger();
      }
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/ReferenceProxy.java
  
  Index: ReferenceProxy.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.component.servlet;
  
  /**
   * Servlet containers do not have a guaranteed order in which servlets will
   *  be destroyed like there is with initialization.  This means that the
   *  servlet which created and controls an object may be destroyed while other
   *  servlets are still using it. This presents a problem in environments where
   *  common objects are placed into the ServletContext and used by more than
   *  one servlet.
   *
   * To solve this problem an object is placed into the ServletContext wrapped
   *  in a ReferenceProxy.  Whe nthe servlet is ready to be shutdown.  A proxy
   *  latch will monitor these proxies waiting for them to be gced.  When all
   *  proxies have been disposed, it can be known that there are no external
   *  references to the contained components remaining.
   *
   * @author <a href="mailto:leif@apache.org">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/08/21 06:03:16 $
   * @since 4.0
   */
  interface ReferenceProxy
  {
  }
  
  
  
  1.1                  jakarta-avalon-excalibur/component/src/java/org/apache/avalon/excalibur/component/servlet/package.html
  
  Index: package.html
  ===================================================================
  <html>
      <body>
          This package provides the ExcaliburComponentManagerServlet which
          makes it easy to use the ExcaliburComponentManager in a servlet
          environment.
      </body>
  </html>
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>