avalon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcconn...@apache.org
Subject cvs commit: avalon/merlin/web/http/spi/src/java/org/apache/avalon/merlin/http/example ExampleService.java
Date Mon, 10 Nov 2003 22:39:18 GMT
mcconnell    2003/11/10 14:39:18

  Added:       merlin/web/http readme.html
               merlin/web/http/impl .cvsignore maven.xml project.xml
               merlin/web/http/impl/conf avalon-http-1.3.block block.xml
               merlin/web/http/impl/src/java/org/apache/avalon/merlin/http
                        AvalonSessionManager.java JettyWebServer.java
               merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/example
                        ExampleServiceImpl.java ExampleServlet.java
                        ExampleSessionManager.java
               merlin/web/http/spi .cvsignore maven.xml project.xml
               merlin/web/http/spi/src/java/org/apache/avalon/merlin/http
                        SessionManager.java WebServer.java
               merlin/web/http/spi/src/java/org/apache/avalon/merlin/http/example
                        ExampleService.java
  Log:
  Initial commit of the http component and Jetty implementation from Timothy Bennett derived from original content written by and donatated to the ASF by Howard Henson.
  
  Revision  Changes    Path
  1.1                  avalon/merlin/web/http/readme.html
  
  Index: readme.html
  ===================================================================
  <html>
  <head>
  <title>Untitled Document</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  </head>
  
  <body bgcolor="#FFFFFF">
  <div align="center"> 
    <h1>Avalon-Jetty</h1>
    <h3>A Web Server Block for Merlin</h3>
    <h3>&nbsp;</h3>
    <h4 align="left"><u>INTRODUCTION</u></h4>
    <p align="left">With the Avalon-Jetty block, hosting a web server and servlet 
      container inside an Avalon container is easy and straight-forward. Furthermore, 
      with Avalon-Jetty's use of a custom Jetty HTTP Session object, your servlets 
      and web applications have access to Avalon's ServiceManager and Logger interface. 
      With access to the container's ServiceManager, your servlets and web applications 
      can use services provided by other components deployed within the container.</p>
    <p align="left">Familarity with the Jetty web server and servlet container may 
      be of benefit in understanding the configuration and use of the Avalon-Jetty 
      block. Further information about the Jetty web server can be found at <a href="http://www.mortbay.org">http://www.mortbay.org</a>.</p>
    <p align="left">The Avalon-Jetty block is a minor re-factorization of the Jetty-Phoenix 
      block authored by Howard Henson, and is currently available on the MortBay 
      site designated above. Jetty-Phoenix is a block designed specifically for 
      the Avalon-Phoenix container. The goal of this initiative is to (1) generalize 
      the block to work with a variety of Avalon containers, and (2) further enhance 
      the block as a kernel extension to Avalon-Merlin.</p>
    <p align="left">In this document, the services/components that make up the Avalon-Jetty 
      block will first be discussed, then examples of configuration and assembly 
      instructions will be provided, along with examples of possible usage scenarios.</p>
    <h4 align="left"><u>SERVICES</u></h4>
    <p align="left">The Avalon-Jetty block exposes two services:</p>
  </div>
  <ul>
    <li>org.apache.avalon.merlin.http.WebServer</li>
    <li>org.apache.avalon.merlin.http.SessionManager</li>
  </ul>
  <p>Both of these services have default component implementations that are extensible 
    to allow further user customization. The WebServer interface provides methods 
    to deploy and remove web applications, and start/stop specific Jetty listeners.</p>
  <h4><u>org.apache.avalon.merlin.http.WebServer</u></h4>
  <p>The Avalon-Jetty block provides a component implementation of the WebServer 
    service in the form of <b>org.apache.avalon.merlin.http.JettyWebServer</b>. 
    This component provides a wrapper around the Jetty web server and servlet container 
    and manages the following lifecycle actions:</p>
  <ul>
    <li>Initialization of the Jetty web server</li>
    <li>Loading of any user-defined Jetty listeners</li>
    <li>Loading of any user-defined contexts (including servlet contexts)</li>
    <li>Loading of any user-defined web applications (including WAR files)</li>
    <li>Starting/stopping of the listeners and web server</li>
  </ul>
  <p>The JettyWebServer component is designed to allow users to extend the component 
    in order to support certain lifecycle customizations, most notably being hooks 
    to load custom listeners that themselves are extensions of Jetty itself. For 
    example, if you wanted to create a custom SSL listener based on proprietary 
    security toolkit like RSA, then the Avalon-Jetty block provides an extensible 
    means by which that custom listener can be loaded.</p>
  <h4><u>org.apache.avalon.merlin.http.SessionManager</u></h4>
  <p>The Avalon-Jetty block provides a component implementation of the SessionManager 
    service in the form of <b>org.apache.avalon.merlin.http.AvalonSessionManager</b>. 
    This component is responsible for creating a custom Jetty servlet session that 
    contains references to the Avalon ServiceManager and Logger. The JettyWebServer 
    component then provides this custom session to all load servlet contexts and 
    web applications. As such, all servlets and web applications can access the 
    ServiceManager and/or Logger from the Session object exposed by the HttpServletRequest 
    object.</p>
  <p>The AvalonSessionManager <b>MUST</b> be extended by the user in order for the 
    user to add his required service dependency doclet tags to the service lifecycle 
    definition. This will be shown in more clarity in the examples later in this 
    document.</p>
  <h4><u>PACKAGING</u></h4>
  <p>The Avalon-Jetty block is packaged in the following binaries:</p>
  <ul>
    <li>avalon-jetty-api-1.3.jar</li>
    <li>avalon-jetty-impl-1.3.jar</li>
  </ul>
  <p>The avalon-jetty-impl jar contains a block.xml file. If this block.xml is executed 
    by merlin, then the example application is executed. See the Example section 
    below for more details.</p>
  <h4><u>ASSEMBLY/CONFIGURATION</u></h4>
  <p><i>Classloader.</i> The following jars must be defined in the container's classloader 
    in order for the Avalon-Jetty block to function:</p>
  <ul>
    <li>avalon-framework-impl</li>
    <li>avalon-jetty-api</li>
    <li>avalon-jetty-impl</li>
    <li>org.mortbay.jetty</li>
    <li>org.mortbay.jmx</li>
    <li>javax.servlet</li>
    <li>jasper-compiler (if using JSP)</li>
    <li>jasper-runtime (if using JSP)</li>
    <li>ant (if using JSP)</li>
  </ul>
  <p>The mortbay jars are not available via any known remote repositories, so you'll 
    have acquire the binaries at the mortbay site describe in the Introduction section 
    above. The Avalon-Jetty block supports the latest Jetty stable distribution, 
    ver. 4.2.14.</p>
  <p><i>Components.</i> We'll use the block.xml found in the avalon-jetty-impl.jar 
    that describes the Example application as simplistic description of the component 
    definition and configuration for the Avalon-Jetty block.</p>
  <pre>&lt;!-- Test Service --&gt;
  &lt;component name=&quot;ex-service&quot; class=&quot;org.apache.avalon.merlin.http.example.ExampleServiceImpl&quot; activation=&quot;lazy&quot;/&gt;</pre>
  <pre>&lt;!-- Session Manager sub-class --&gt;
  &lt;component name=&quot;session-mgr&quot; class=&quot;org.apache.avalon.merlin.http.example.ExampleSessionManager&quot; activation=&quot;startup&quot;/&gt;</pre>
  <pre>&lt;!-- Web Server --&gt;
  &lt;component name=&quot;avalon-jetty&quot; class=&quot;org.apache.avalon.merlin.http.JettyWebServer&quot; activation=&quot;startup&quot;&gt;
  	&lt;configuration&gt;
  		&lt;Listener port=&quot;8080&quot; type=&quot;socket&quot;/&gt;
  		&lt;Context name=&quot;example&quot; path=&quot;/example/*&quot;&gt;
  			&lt;Servlet name=&quot;Example&quot; path=&quot;/servlets/*&quot; classname=&quot;org.apache.avalon.merlin.http.example.ExampleServlet&quot;/&gt;
  		&lt;/Context&gt;
  	&lt;/configuration&gt;
  &lt;/component&gt;</pre>
  <p>The Test Service represents some service deployed within the container that 
    we would like for our servlet to have access to.</p>
  <p>The Session Manager subclass is our extension of the org.apache.avalon.merlin.http.AvalonSessionManager 
    with an avalon-meta dependency defined for the org.apache.avalon.merlin.http.example.ExampleService 
    as a doclet for the service lifecycle method.</p>
  <p>The Web Server component is the definition/configuration of the org.apache.avalon.merlin.http.JettyWebServer 
    component. It defines a socket (standard HTTP) listener bound to port 8080, 
    and servlet context (in this case, http://localhost:8080/example/servlets/) 
    tied to the ExampleServlet code. This servlet can perform a lookup of the TestService 
    from within the servlet's doGet or doPost methods.</p>
  <pre>import org.apache.avalon.merlin.http.WebServer;
  
  
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
  	Logger logger = (Logger) req.getSession().getAttribute(WebServer.LOGGER);
  	ServiceManager serviceManager = (ServiceManager) req.getSession().getAttribute(WebServer.SERVICE_MANAGER);
  
  	ExampleService service = (ExampleService) serviceManager.lookup(ExampleService.class.getName());
  	...
  	...
  	// do something with reference to ExampleService
  	...
  
  } </pre>
  <h4><u>LISTENERS</u></h4>
  <p>The JettyWebServer component can define one or more listeners configured of 
    any recognized listener type. The complete set of recognized listener attributes 
    are shown below following by a description of each of the listener attributes: 
  </p>
  <pre>&lt;Listener name=&quot;http&quot; port=&quot;8196&quot; host=&quot;192.168.1.102&quot; type=&quot;socket&quot; auto-start=&quot;true&quot; timeout=&quot;60000&quot;/&gt;</pre>
  <ul>
    <li><b>name</b> -- Optional. An alias assigned by the user to a specific listener. 
      If the user wishes to employ the dynamic starting or stopping of listeners 
      post- web server startup, then an alias <b>must</b> be defined.</li>
    <li><b>port</b> -- Optional. The port on the host that the listener will be 
      bound to. For type=socket, default value is 8080; type=ajp, default value 
      is 2345; type=jsse, default value is 8443.</li>
    <li><b>host</b> -- Optional. The host DNS or IP address that the listener will 
      be bound to. Default value is 0.0.0.0, which means all IP addresses defined 
      on the host machine.</li>
    <li><b>type</b> -- Optional. type=<b>socket</b> means a standard non-secure 
      HTTP listener; type=<b>jsse</b> means a secure HTTPS listener that uses Sun's 
      JSSE extension for SSL; type=<b>ajp</b> means a socket listener that uses 
      the AJP 1.3 protocol commonly used to connect web servers like Apache, IIS, 
      and Netscape iPlanet to external servlet containers like Tomcat. Default value 
      is <b>socket</b>.</li>
    <li><b>auto-start</b> -- Optional. Flag to indicate whether or not a listener 
      should be automatically started with the Jetty web server is started. A value 
      of <b>false</b> delays the startup of the listener until the <b>startListener(alias)</b> 
      API method is invoked. If the value of this attribute is <b>false</b>, then 
      it is assumed that the user provided a <b>name</b> attribute value. Default 
      value is <b>true</b>.</li>
    <li><b>timeout</b> -- Optional. Allows the user to specify the socket timeout 
      that a session has to return a response to the client. Value is in units of 
      milliseconds. Default value corresponds to Jetty's default values for these 
      listener types, which I believe corresponds to the underlying defaults the 
      Java socket layer.</li>
  </ul>
  <p>If the type is <b>jsse</b>, then further configuration concerning the keystore 
    for the SSL server certificate is required as shown below:</p>
  <pre>&lt;Listener port=&quot;9443&quot; type=&quot;jsse&quot;&gt;
  	&lt;keystore&gt;
  		&lt;file&gt;conf/my.keystore&lt;/file&gt;
  		&lt;password&gt;my-cert-password&lt;/password&gt;
  		&lt;key-password&gt;my-keystore-password&lt;/key-password&gt;
  	&lt;/keystore&gt;
  &lt;/Listener</pre>
  <p>The <b>file</b> child node corresponds to the location of the certificate keystore, 
    and is assumed to be a JKS type keystore. The path (as shown above) may be relative 
    to the component's directory or a fully qualified filename.</p>
  <p>The <b>password</b> child node corresponds to the password of the SSL server 
    certificate in the keystore. The value of the password may contain the <b>OBF:</b> 
    prefix for Jetty-style obfuscated passwords to indicate that the password has 
    been obfuscated.</p>
  <p>The <b>key-password</b> child node corresponds to the password of the keystore. 
    The value of the password may contain the <b>OBF:</b> prefix for Jetty-style 
    obfuscated passwords to indicate that the password has been obfuscated.</p>
  <p>Note that the appropriate JSSE jars will need to be added to the classloader 
    of the container in order for the JSSE listener to function.</p>
  <h4><u><b>CONTEXTS</b></u></h4>
  <p>The JettyWebServer component can define one or more Contexts to be bound to 
    the listeners defined. There are two types of contexts defined: non-servlet 
    (i.e. html, etc.) and servlet. There can be many contexts defined in a configuration. 
    There can be many servlet definitions within a context. An example of some context 
    configurations follow:</p>
  <pre>
  &lt;configuration&gt;
  	&lt;Listener port=&quot;8196&quot; type=&quot;socket&quot;/&gt;
  	&lt;Context name=&quot;www&quot; path=&quot;/&quot;/&gt;
  	&lt;Context name=&quot;handlers&quot; path=&quot;/handlers&quot;&gt;
  		&lt;Servlet name=&quot;router&quot; path=&quot;/router&quot; classname=&quot;my.company.servlets.MyRouterServlet&quot;/&gt;
  	&lt;/Context&gt;
  &lt;/configuration&gt;
  </pre>
  <p>The first Context definition corresponds to a non-servlet context. The <b>name</b> 
    attribute corresponds to the path where resources will be be served up from 
    and the <b>path</b> attribute corresponds to the URL application path that corresponds 
    to this context. In this example, if a browser hits the URL <b>http://localhost:8196/</b>, 
    then the index.html file located in the <b>www</b> directory located relative 
    to the components home directory, will be served up to the browser.</p>
  <p>The second Context definition corresponds to a servlet context. As before, 
    the <b>path </b>attribute in the <b>Context</b> node corresponds to the URL 
    application for the all the Servlet contexts defined for this Context. The Servlet 
    <b>name</b> attribute is the name of this servlet, the <b>path</b> attribute 
    is the application path to this particular servlet relative to the Context path, 
    and the <b>classname</b> attribute is the FQCN of the servlet to be invoked. 
    In this example, if a browser hits the URL <b>http://localhost:8196/handlers/router</b>, 
    then the MyRouterServlet servlet will be executed.<br>
    <br>
  </p>
  <h4><u>WEB CONTEXTS</u></h4>
  <p>The JettyWebServer component can define one or more WebContexts to be bound 
    to the listeners defined. WebContexts can refer to either WAR file packages, 
    or to a directory where a web application has been deployed. There can be many 
    WebContexts defined in a configuration. An example of some WebContext configurations 
    follow:</p>
  <pre>
  &lt;configuration&gt;
  	&lt;Listener port=&quot;8196&quot; type=&quot;socket&quot;/&gt;
  	&lt;Context name=&quot;www&quot; path=&quot;/&quot;/&gt;
  	&lt;Context name=&quot;handlers&quot; path=&quot;/handlers&quot;&gt;
  		&lt;Servlet name=&quot;router&quot; path=&quot;/router&quot; classname=&quot;my.company.servlets.MyRouterServlet&quot;/&gt;
  	&lt;/Context&gt;
  	&lt;WebContext name=&quot;logon&quot; path=&quot;/logon/logon.war&quot;/&gt;
  	&lt;WebContext name=&quot;logon2&quot; path=&quot;/logon2&quot;/&gt;
  &lt;/configuration&gt;
  </pre>
  <p>In the first WebContext definition, the <b>path</b> attribute contains filename 
    with the .war extension. This indicates to the JettyWebServer that the web application 
    has been package in WAR format, and insures that WAR will be extracted. The 
    path to the WAR file can be a fully qualified filepath, or a path relative to 
    the component's home directory. The <b>name</b> attribute is basically just 
    an alias for the web application defined, as the URL application path is defined 
    by the web applications WEB-INF/web.xml context configuration.</p>
  <p>In the second WebContext definition, the only thing different is that the <b>path</b> 
    attribute defines a directory where a web application has been deployed. The 
    directory may represent a fully qualified path, or a path relative to the component's 
    home directory.</p>
  <h4><u>EXAMPLE</u></h4>
  <p>There's one example tutorial within the codebase for this block. The example 
    code is found in the org.apache.avalon.merlin.http.example package in both the 
    spi and impl codebases. If you execute the block.xml in the avalon-jetty-impl-1.3.jar 
    in merlin, then a web server block will be started using the example code. Point 
    your browser to <b>http://localhost:8080/example/servlets/</b> to see an example 
    servlet executed that performs a ServiceManager lookup to obtain a reference 
    to the ExampleServiceImpl component and invokes its only service <b>getName</b>. 
  </p>
  <p><br>
    <br>
  </p>
  </body>
  </html>
  
  
  
  1.1                  avalon/merlin/web/http/impl/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  .classpath
  .project
  target
  maven.log
  home
  
  
  
  1.1                  avalon/merlin/web/http/impl/maven.xml
  
  Index: maven.xml
  ===================================================================
  <project default="jar:jar" xmlns:maven="jelly:maven" xmlns:j="jelly:core" xmlns:util="jelly:util">
  
      <preGoal name="java:compile">
          <attainGoal name="avalon:meta"/>
      </preGoal>
      
  </project>
  
  
  
  1.1                  avalon/merlin/web/http/impl/project.xml
  
  Index: project.xml
  ===================================================================
  <?xml version="1.0" encoding="ISO-8859-1"?>
  
  <project>
  
      <extend>${basedir}/../../../project.xml</extend>
      
      <groupId>avalon-http</groupId>
      <id>avalon-http-impl</id>
      <name>Avalon HTTP Web Server Component</name>
      <currentVersion>1.3</currentVersion>
      <package>org.apache.avalon.merlin.http</package>
      <inceptionYear>2003</inceptionYear>
      <shortDescription>Avalon-Jetty Web Server</shortDescription>
      
      <dependencies>
          <dependency>
              <groupId>avalon-framework</groupId>
              <artifactId>avalon-framework-api</artifactId>
              <version>4.1.5</version>
          </dependency>
          
          <dependency>
              <groupId>avalon-framework</groupId>
              <artifactId>avalon-framework-impl</artifactId>
              <version>4.1.5</version>
          </dependency>
          
          <dependency>
              <groupId>avalon-http</groupId>
              <artifactId>avalon-http-api</artifactId>
              <version>1.3</version>
          </dependency>
          
          <dependency>
              <groupId>jetty</groupId>
              <artifactId>org.mortbay.jetty</artifactId>
              <version>4.2.14</version>
          </dependency>
          
          <dependency>
            <id>servletapi</id>
            <version>2.3</version>
          </dependency>
  
      </dependencies>
  
  </project>
  
  
  
  1.1                  avalon/merlin/web/http/impl/conf/avalon-http-1.3.block
  
  Index: avalon-http-1.3.block
  ===================================================================
  <container name="avalon-jetty-web-server">
  
      <classloader>
          <classpath>
              <repository>
                  <resource id="avalon-framework:avalon-framework-impl" version="4.1.5"/>
                  <resource id="avalon-http:avalon-http-api" version="1.3"/>
                  <resource id="avalon-http:avalon-http-impl" version="1.3"/>
                  <resource id="jetty:org.mortbay.jetty" version="4.2.14"/>
                  <resource id="servletapi:servletapi" version="2.3"/>
              </repository>
          </classpath>
      </classloader>
      
      <!-- Test Service -->
      <component name="ex-service" class="org.apache.avalon.merlin.http.example.ExampleServiceImpl" activation="lazy"/>
      
      <!-- Session Manager sub-class -->
      <component name="session-mgr" class="org.apache.avalon.merlin.http.example.ExampleSessionManager" activation="startup"/>
      
      <!-- Web Server -->
      <component name="avalon-jetty" class="org.apache.avalon.merlin.http.JettyWebServer" activation="startup">
          <configuration>
              <Listener port="8080"/>
              <Context name="example" path="/example/*">
                  <Servlet name="Example" path="/servlets/*" classname="org.apache.avalon.merlin.http.example.ExampleServlet"/>
              </Context>
          </configuration>
      </component>
      
  </container>
  
  
  
  1.1                  avalon/merlin/web/http/impl/conf/block.xml
  
  Index: block.xml
  ===================================================================
  <container name="avalon-jetty-web-server">
  
      <classloader>
          <classpath>
              <repository>
                  <resource id="avalon-framework:avalon-framework-impl" version="4.1.5"/>
                  <resource id="avalon-http:avalon-http-api" version="1.3"/>
                  <resource id="jetty:org.mortbay.jetty" version="4.2.14"/>
                  <resource id="servletapi:servletapi" version="2.3"/>
              </repository>
          </classpath>
      </classloader>
      
      <!-- Test Service -->
      <component name="ex-service" class="org.apache.avalon.merlin.http.example.ExampleServiceImpl" activation="lazy"/>
      
      <!-- Session Manager sub-class -->
      <component name="session-mgr" class="org.apache.avalon.merlin.http.example.ExampleSessionManager" activation="startup"/>
      
      <!-- Web Server -->
      <component name="avalon-jetty" class="org.apache.avalon.merlin.http.JettyWebServer" activation="startup">
          <configuration>
              <Listener port="8080"/>
              <Context name="example" path="/example/*">
                  <Servlet name="Example" path="/servlets/*" classname="org.apache.avalon.merlin.http.example.ExampleServlet"/>
              </Context>
          </configuration>
      </component>
      
  </container>
  
  
  
  1.1                  avalon/merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/AvalonSessionManager.java
  
  Index: AvalonSessionManager.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http;
  
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Random;
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.avalon.framework.logger.LogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.Serviceable;
  
  import org.mortbay.jetty.servlet.AbstractSessionManager;
  
  import org.apache.avalon.merlin.http.SessionManager;
  import org.apache.avalon.merlin.http.WebServer;
  
  
  /**
   * An Avalon-aware Jetty Session Manager.
   * <b>THIS IS THE CLASS TO OVERRIDE IN ORDER TO SUPPORT THE SERVICES
   * YOU WISH TO USE</b><br>
   *
   * This should be instantiated via the services interface.
   *
   * Then the session manager should be overridden by the user of the system
   * in order to place the service dependancy list correctly in the setServiceManager
   * method. The user implementation should just call super.
   *
   * @author Howard Henson
   * @author  <a href="mailto:exterminatorx@comcast.net">Timothy Bennett</a>
   * @avalon.component name="avalon-jetty-session-mgr" version="1.2" lifestyle="thread"
   * @avalon.service type="org.apache.avalon.merlin.http.SessionManager" version="1.1"
   */
  public class AvalonSessionManager
      extends AbstractSessionManager
      implements SessionManager, Serviceable, LogEnabled
  {
      private Logger m_logger;
      private ServiceManager m_serviceManager;
       
      /**
       * Constructor for PhoenixSessionManagerImpl.
       */
      public AvalonSessionManager() {
          super();
      }
  
      /**
       * Constructor for PhoenixSessionManagerImpl.
       * @param random
       */
      public AvalonSessionManager(Random random) {
          super(random);
      }
  
      /**
       * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
       */
      public void service(ServiceManager manager) throws ServiceException {
          m_serviceManager = manager;
      }
       
      /**
       * @see org.apache.avalon.framework.logger.LogEnabled#enableLogging(org.apache.avalon.framework.logger.Logger)
       */
      public void enableLogging(Logger logger) {
          m_logger = logger;
      }
      
      /**
       * @see org.mortbay.jetty.servlet.AbstractSessionManager#newSession(HttpServletRequest)
       */
      protected AbstractSessionManager.Session newSession(HttpServletRequest request) {
          Session session = new Session(request);
          session.setAttribute(WebServer.SERVICE_MANAGER, m_serviceManager);
          session.setAttribute(WebServer.LOGGER, m_logger);
          return session;
      }
  
      protected class Session extends AbstractSessionManager.Session {
          /* ------------------------------------------------------------- */
          protected Session(HttpServletRequest request) {
              super(request);
          }
  
          /* ------------------------------------------------------------ */
          protected Map newAttributeMap() {
              return new HashMap(10);
          }
      }
  }
  
  
  
  1.1                  avalon/merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/JettyWebServer.java
  
  Index: JettyWebServer.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http;
  
  import java.io.File;
  import java.util.HashMap;
  
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.avalon.framework.logger.Logger;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  import org.apache.avalon.framework.service.Serviceable;
  
  import org.apache.avalon.merlin.http.WebServer;
  
  import org.mortbay.http.HttpContext;
  import org.mortbay.http.HttpHandler;
  import org.mortbay.http.HttpListener;
  import org.mortbay.http.HttpServer;
  import org.mortbay.http.SocketListener;
  import org.mortbay.http.SunJsseListener;
  import org.mortbay.http.ajp.AJP13Listener;
  import org.mortbay.http.handler.ResourceHandler;
  import org.mortbay.jetty.servlet.ServletHandler;
  import org.mortbay.jetty.servlet.SessionManager;
  import org.mortbay.jetty.servlet.WebApplicationContext;
  import org.mortbay.util.MultiException;
  
  /**
   * Implements a web server/servlet container service using the Jetty web server.
   * 
   * The configuration options for this implementation are defined in
   * the {@link JettyWebServer#configure configure} method.
   * 
   * @author Howard Henson
   * @author  <a href="mailto:exterminatorx@comcast.net">Timothy Bennett</a>
   * @avalon.component name="avalon-jetty" version="1.3" lifestyle="singleton"
   * @avalon.service type="org.apache.avalon.merlin.http.WebServer" version="1.2"
   * @see JettyWebServer#configure
   * @see org.apache.avalon.merlin.http.WebServer
   */
  public class JettyWebServer
      extends AbstractLogEnabled
      implements Contextualizable, Configurable, Initializable, Serviceable,
      Startable, Disposable, WebServer
   {
      /************************************************/
      protected Context m_context;
      protected Configuration m_config;
      protected Logger m_logger;
      protected HttpServer m_httpServer;
      protected ServiceManager m_serviceManager;
       
      /************************************************/
      //protected File m_appHome = null;
      protected HashMap m_listeners = new HashMap();
      protected String m_basedir = System.getProperty("merlin.home", System.getProperty("user.dir"));
       
      /************************************************/
      protected static final String CFG_LISTENER = "Listener";
      protected static final String CFG_LISTENER_NAME = "name";
      protected static final String CFG_LISTENER_PORT = "port";
      protected static final String CFG_LISTENER_HOST = "host";
      protected static final String CFG_LISTENER_TYPE = "type";
      protected static final String CFG_LISTENER_AUTO = "auto-start";
      protected static final String CFG_LISTENER_TYPE_SOCKET = "socket";
      protected static final String CFG_LISTENER_TYPE_AJP = "ajp";
      protected static final String CFG_LISTENER_TYPE_JSSE = "jsse";
      protected static final String CFG_LISTENER_TIMEOUT = "timeout";
      protected static final String CFG_CONTEXT = "Context";
      protected static final String CFG_CONTEXT_PATH = "path";
      protected static final String CFG_CONTEXT_NAME = "name";
      protected static final String CFG_SERVLET = "Servlet";
      protected static final String CFG_SERVLET_NAME = "name";
      protected static final String CFG_SERVLET_PATH = "path";
      protected static final String CFG_SERVLET_CLASSNAME = "classname";
      protected static final String CFG_WEB_CONTEXT = "WebContext";
      
      /**
      * Contextualizes the component using an Avalon context. Specifically looks
      * for a home or working directory with the key "app.home" or "urn:avalon:home",
      * and sets this as the component's base directory. Otherwise, the component's
      * base directory will default to either the MERLIN_HOME environment setting
      * or the application's current working directory.
      *
      * @param context an Avalon Context object
      * @throws <code>ContextException</code> if an error occurs while retrieving
      * the avalon home directory from the context
      *
      * @avalon.entry key="urn:avalon:home" type="java.io.File"
      */
      public void contextualize(Context context) throws ContextException {
          m_context = context;
          
          // cache the component's logger
          m_logger = getLogger();
          if (m_logger.isInfoEnabled()) m_logger.info("Contextualizing...");
  
          // attempt to find out the "home" directory of this component
          // if we find it, then set the basedir to this directory
          try {
              File home = null;
  
           // First, we'll try 'app.home'; if that doesn't exist, then 'urn:avalon:home'
           try {
              home = (File) context.get("app.home");
           } catch (ContextException ce) {
              if (m_logger.isWarnEnabled())
                  m_logger.warn("'app.home' key not found in context; trying 'urn:avalon:home'");
              try {
                  home = (File) context.get("urn:avalon:home");
              } catch (ContextException cex) {
                  if (m_logger.isWarnEnabled())
                      m_logger.warn("'urn:avalon:home' key not found in context; using default");
              }
           }
           if (home != null) {
              m_basedir = home.getAbsolutePath();
           }
           if (m_logger.isDebugEnabled())
              m_logger.debug("Setting home directory to: " + m_basedir);
          } catch (Exception e) {
              if (m_logger.isWarnEnabled())
                  m_logger.warn("Error attempting to establish home directory. Using default.", e);
          }
      }
       
      /**
       * Servicing of the component by the container during which service dependencies
       * that are declared can be resolved using the supplied service manager. This
       * component depends upon the following component services:
       * <p>
       * TODO: list dependent services...
       * <br>
       *
       * @param manager the service manager
       * @throws <code>ServiceException</code> if an error occurs while servicing
       * this component
       *
       * @avalon.dependency type="org.mortbay.jetty.servlet.SessionManager"
       * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
      */
      public void service(ServiceManager manager) throws ServiceException {
          if (m_logger.isInfoEnabled()) m_logger.info("Servicing...");
          m_serviceManager = manager;
      }
       
      /**
       * Configuration of the component by the container.
       * <p>
       * A general configuration takes the form of:<br>
       * <br><code>
       * &lt;configuration&gt;<br>
       * &nbsp;&nbsp;&lt;Listener name="my-listener" port="8080" host="localhost" type="socket"/&gt;<br>
       * &nbsp;&nbsp;&lt;Context name="myCtx" path="/mypath/*"&gt;<br>
       * &nbsp;&nbsp;&nbsp;&nbsp;&lt;Servlet name="MyServlet" path="/servlets/MyServlet" classname="package.MyServlet" /&gt;<br>
       * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br>
       * &nbsp;&nbsp;&lt;/Context&gt;<br>
       * &nbsp;&nbsp;&lt;WebContext name="myContext" path="/myContext"/&gt;<br>
       * &nbsp;&nbsp;&lt;WebContext name="myWarContext" path="/myWarFile.war"/&gt;<br>
       * &lt;/configuration&gt;<br>
       * </code><br>
       * One or more listeners can be defined to load and start-up with the server.
       * The port is the port the listener will listen on, and the host
       * is the IP address the web server will be bound to. It is an optional attribute,
       * and defaults to 0.0.0.0, which is all IP addresses defined on the machine.
       * The context name is the directory within the sar
       * file that the resources for this context can be found. The path is the url path to bind the context to.
       * <p>
       * The specific configuration options are:<br>
       * <ul>
       * <li><b>Listener</b> - The listener defines the nature of the connections that the web server will
       * support and provide a service over. The listener supports multiple types connections, via the <code>type</code>
       * attribute, these include:<br>
       * <ul>
       * <li><b>socket</b> - Uses the SocketListener class. This is a standard socket and should work
       * fine for all JDK versions supported by Jetty. This is the default type and provides a stock HTTP protocol
       * listener.</li>
       * <li><b>ajp</b> - Uses the AJP13Listener. This provides a standard implementation of the AJP13 protocol. This is useful
       * for a service that will be accessed from an external web server, for example an external apache web server.</li>
       * <li><b>jsse</b> - Uses the SunJsseListener. This provides a Sun JSSE SSL protocol listener.</li>
       * </ul>
       * The listener can also have the port on which it will listen to defined via the <code>port</code> attribute, by default the
       * HTTP ports are set to 8080, SSL set to 8433, and the AJP port is set to 2345.
       * </li>
       * <br>
       * <li><b>Context</b> - This tag represents the context you wish to bind. The <code>path</code> represents the name
       * of the context (should be the path on the URL) and the <code>name</code> attribute is the relative directory within
       * the application that the files (non-servlet, e.g. html, etc.) can be found. The context also contains servlet definitions,
       * these definitions are as follows:<br>
       * <ul>
       * <li><b>Servlet</b> - The servlet definition describes the servlets that are to be made accessable. The attributes are:
       * <ul>
       * <li>name - The name of the serlvet</li>
       * <li>path - The path to access the servlet, this is what the url will look like</li>
       * <li>classname - The name of the servlet class.</li>
       * </ul>
       * There can be many serlvet definitions within a context.
       * </li>
       * </ul>
       * There can be many context definitions within a configuration.
       * </li>
       * </ul>
       * </p>
       * <p>The new tag is the <code><b>WebContext</b></code> which will treat the contents of the directory within the
       * application (descibed by the <b><i>path</i></b> attribute) as a web application and bind it to the context path 
       * labled with the <b><i>name attribute</i></b>.
       * You don't need to provide any of the old Context tags and can use the WebContext to load the application. This
       * relies on the file WEB-INF/web.xml to configure the context. The file is be within the directory provided for the 
       * application, or if this is a war file the file is extracted and used as the directory.
       * </p>
       * 
       * @param config the configuration object
       * @throws <code>ConfigurationException</code> if an error occurs while configuring
       * this component
       * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
       */
      public void configure(Configuration config) throws ConfigurationException {
          if (m_logger.isInfoEnabled()) m_logger.info("Configuring...");
          m_config = config;
      }
       
      /**
       * Initialization of the component by the container.
       * <p>
       * Initialises the Jetty web server. It is at this time that the configuration information
       * is actually used.  Any defined listeners, contexts, and web applications
       * are loaded at this time.
       *
       * @throws <code>Exception</code> if an error occurs during initialization of
       * this component
       * @see org.apache.avalon.framework.activity.Initializable#initialize()
       */
      public void initialize() throws Exception {
          if (m_logger.isInfoEnabled()) m_logger.info("Initializing...");
  
          m_httpServer = new HttpServer();
          loadListeners();
          loadContexts();
          loadWebApplications();
      }
       
      /**
       * Component is started by the container.
       * <p>
       * Starts the Jetty web server.
       * 
       * @throws <code>Exception</code> if an error occurs during startup of
       * this component
       * @see org.apache.avalon.framework.activity.Startable#start()
       */
      public void start() throws Exception {
          if (m_logger.isInfoEnabled()) m_logger.info("Starting...");
          m_httpServer.start();
      }
  
      /**
      * Component is stopped by the container.
      * <p>
      * Stops the Jetty web server.
      *
      * @throws <code>Exception</code> if an error occurs during shutdown of
      * this component
      * @see org.apache.avalon.framework.activity.Startable#stop()
      */
      public void stop() throws Exception {
          if (m_logger.isInfoEnabled()) m_logger.info("Shutting down...");
          m_httpServer.stop(true);
      }
       
      /**
       * Component disposal by the container.
       * <p>
       * Cleans up resources allocated by the component.
       *
       * @see org.apache.avalon.framework.activity.Disposable#dispose()
       */
      public void dispose() {
          m_context = null;
          m_serviceManager = null;
          m_httpServer = null;
          m_listeners = null;
      }
       
      /**
       * @see org.apache.avalon.merlin.http.WebServer#deployWebApplication(java.lang.String, java.lang.String)
       */
      public void deployWebApplication(String context, String appPath) {
          loadWebApplicationContext(context, appPath);
      }
  
      /**
       * @see org.apache.avalon.merlin.http.WebServer#removeWebApplication(java.lang.String)
       */
      public boolean removeWebApplication(String context) {
          try {
              m_httpServer.stop();
              HttpContext ctx = m_httpServer.getContext(context);
              if (ctx != null) {
                  m_httpServer.removeContext(ctx);
              } else {
                  m_logger.error("Could not find application to remove: " + context);
                  return false;
              }
              m_httpServer.start();
          } catch (InterruptedException e) {
              m_logger.error("Unable to remove web application due to: " + e.getMessage());
              return false;
          } catch (MultiException e) {
              m_logger.error("Unable to re-start web application due to: " + e.getMessage());
              return false;
          }
          return true;
      }
  
      /**
       * Allows dynamic starting of a Jetty listener.
       *
       * @param name the alias of the listener that has been defined in configuration file
       */
      public void startListener(String name) throws Exception {
          boolean found = false;
          boolean started = false;
              
          m_logger.debug("Attempting to start listener " + name);
          if (m_listeners.containsKey(name)) {
              m_logger.debug("Retrieving listener " + name + " from lookup table...");
              HttpListener listener = (HttpListener) m_listeners.get(name);
              m_logger.debug("Listener " + name + " retrieved");
                  
              // listener must be stopped before we can start it
              if (listener == null) {
                  m_logger.debug("Listener " + name + " has not yet been created/started");
                      
                  // get the configuration for this listener...
                  Configuration[] listeners = m_config.getChildren(CFG_LISTENER);
                  m_logger.debug("Searching for listener " + name + "'s configuration...");
                  for (int i = 0; i < listeners.length; i++) {
                      Configuration conf = listeners[i];
                      String alias = conf.getAttribute(CFG_LISTENER_NAME);
                      if (alias.equals(name)) {
                          found = true;
                          m_logger.debug("Found configuration for listener " + name);
                          m_logger.debug("Loading listener " + name + "...");
                          listener = loadListener(conf);
                          if (listener != null) {
                              m_logger.debug("Listener " + name + " loaded");
                              listener.setHttpServer(m_httpServer);
                              m_logger.debug("Registered the listener with Jetty...");
                              if (!listener.isStarted()) {
                                  m_logger.debug("Starting listener " + name);
                                  listener.start();
                                  m_logger.debug("Listener " + name + " started");
                                  started = true;
                                  m_listeners.put(name, listener);
                                  m_logger.debug("Listener " + name + " stored in lookup table");
                              }
                          }
                          break;
                      }
                  }
                      
                  // did we find the listener in our lookup table?
                  if (!found) {
                      String errmsg = "Listener name [" + name + "] cannot be started because configuration not found";
                      m_logger.warn(errmsg);
                      throw new Exception(errmsg);
                  } else if (!started) {
                      String errmsg = "Listener name [" + name + "] cannot be started because of unknown listener name";
                      m_logger.warn(errmsg);
                      throw new Exception(errmsg);
                  }
              } else {
                  String errmsg = "Listener name [" + name + "] cannot be started because it is already running";
                  m_logger.warn(errmsg);
                  throw new Exception(errmsg);
              }
          } else {
              String errmsg = "Listener name [" + name + "] cannot be started because of unknown listener name";
              m_logger.warn(errmsg);
              throw new Exception(errmsg);
          }
      }
  
      /**
       * Allows the dynamic stopping of a Jetty listener.
       *
       * @param name the alias of the listener that has been defined in configuration file
       */
      public void stopListener(String name) throws Exception {
          if (m_listeners.containsKey(name)) {
              HttpListener listener = (HttpListener) m_listeners.get(name);
  
              // listener must be started before we can stop it
              if (listener != null) {
                  if (listener.isStarted()) {
                      listener.stop();
                      //httpServer.removeListener(listener);
                      m_listeners.put(name, null);
                  }
              }
          }
      }
      
      /**
       * Load a individual listener defined in the component configuration. This
       * method may be overloaded in a subclass in order to load a custom Jetty
       * listener. Subclasses should still invoke <code>super()</code> from the 
       * overloaded method so that standard Jetty listeners will continue to be
       * loaded.
       */
      protected HttpListener loadListener(Configuration conf) throws Exception {
          HttpListener listener = null;
  
          String listenerType = conf.getAttribute(CFG_LISTENER_TYPE, CFG_LISTENER_TYPE_SOCKET);
          if (listenerType.equals(CFG_LISTENER_TYPE_AJP)) {
              listener = createAJP13Listener(conf);
              /* Need to set the correct default value here */
              listener.setPort(conf.getAttributeAsInteger(CFG_LISTENER_PORT, 2345));
              listener.setHost(conf.getAttribute(CFG_LISTENER_HOST, "0.0.0.0"));
          } else if (listenerType.equals(CFG_LISTENER_TYPE_JSSE)) {
              listener = createSunJsseListener(conf);
              listener.setPort(conf.getAttributeAsInteger(CFG_LISTENER_PORT, 8443));
              listener.setHost(conf.getAttribute(CFG_LISTENER_HOST, "0.0.0.0"));
          } else {
              listener = createSocketListener(conf);
              listener.setPort(conf.getAttributeAsInteger(CFG_LISTENER_PORT, 8080));
              listener.setHost(conf.getAttribute(CFG_LISTENER_HOST, "0.0.0.0"));
          }
          m_httpServer.addListener(listener);
          m_logger.info("Loaded listener: " + listener.getClass().getName() +
                        " on " + listener.getHost() + ":" + listener.getPort());
          return listener;
      }
      
      /**
       * Loads all the listeners defined in the component configuration.  This method
       * invokes the <code>loadListener</code> method, which may be overloaded in
       * a subclass in order to load custom Jetty listeners.
       */
      private void loadListeners() throws Exception {
          Configuration[] listeners = m_config.getChildren(CFG_LISTENER);
          for (int i = 0; i < listeners.length; i++) {
              Configuration conf = listeners[i];
              
              // Get the listener's alias
              String name = conf.getAttribute(CFG_LISTENER_NAME, null);
  
              // Add a NULL listener to our lookup table.
              if (name != null) m_listeners.put(name, null);
  
              // Do we auto-start this listener? defaults to true
              boolean isAutoStart = conf.getAttributeAsBoolean(CFG_LISTENER_AUTO, true);
              if (isAutoStart) {
                  try {
                      // load/start the listener
                      HttpListener listener = loadListener(conf);
                      
                      // indicate the listener has been started
                      if (name != null) m_listeners.put(name, listener);
                  } catch (Exception e) {
                      m_logger.error("Could not create listner", e);
                  }
              } else {
                  m_logger.error("Listener " + name + " will not be started");
              }
          }
      }
  
      /**
       * Loads all of the contexts defined in the component configuration
       */
      private void loadContexts() {
          Configuration[] contexts = m_config.getChildren(CFG_CONTEXT);
          for (int i = 0; i < contexts.length; i++) {
              try {
                  Configuration conf = contexts[i];
                  HttpContext context = new HttpContext();
                  context.setContextPath(conf.getAttribute(CFG_CONTEXT_PATH, "/*"));
                  m_httpServer.addContext(context);
                  ServletHandler servletHandler = setSessionManager(context);
                  Configuration[] servlets = conf.getChildren(CFG_SERVLET);
                  for (int j = 0; j < servlets.length; j++) {
                      Configuration servletCfg = servlets[j];
                      servletHandler.addServlet(
                          servletCfg.getAttribute(CFG_SERVLET_NAME, servletCfg.getAttribute(CFG_SERVLET_CLASSNAME)),
                          servletCfg.getAttribute(CFG_SERVLET_PATH, "/servlets/*"),
                          servletCfg.getAttribute(CFG_SERVLET_CLASSNAME)
                          );
                  }
                  context.setResourceBase(m_basedir + "/" + conf.getAttribute(CFG_CONTEXT_NAME));
                  context.addHandler(new ResourceHandler());
              } catch (Exception e) {
                  m_logger.error("Could not construct context", e);
              }
          }
      }
  
      /**
       * Loads all the web application defined in the component configuration.
       */
      private void loadWebApplications() {
          Configuration[] confArr = m_config.getChildren(CFG_WEB_CONTEXT);
          for (int c = 0; c < confArr.length; c++) {
              Configuration conf = confArr[c];
              loadWebApplicationContext(
                  conf.getAttribute(CFG_CONTEXT_NAME, ""),
                  new File(m_basedir, conf.getAttribute(CFG_CONTEXT_PATH, "")).toString()
                  );
          }
      }
      
      /**
       * Adds the Avalon SessionManager to the servlet handler. If no servlet handler
       * exists within the context, then a servlet manager is added to the context.
       * 
       * @param the HttpContext
       * @return the created ServletHandler
       * @throws ServiceException
       */
      private ServletHandler setSessionManager(HttpContext context) throws ServiceException 
      {
          HttpHandler[] handlers = context.getHandlers();
          ServletHandler servletHandler = null;
          if (handlers == null || handlers.length == 0) 
          {
              servletHandler = new ServletHandler();
              context.addHandler(servletHandler);
          }
          else 
          {
              for (int c = 0; c < handlers.length; c++) 
              {
                  if (handlers[c] instanceof ServletHandler) 
                  {
                      servletHandler = (ServletHandler) handlers[c];
                      c = handlers.length;
                  }
              }
              if (servletHandler == null) 
              {
                  servletHandler = new ServletHandler();
                  context.addHandler(servletHandler);
              }
          }
  
          // switched from hhtp.SessionManager to jetty variant
          // due to class cast exception - some rethingking needed here
  
          String clazzName = SessionManager.class.getName();
          SessionManager sessionManager = (SessionManager) m_serviceManager.lookup(clazzName) ;
          servletHandler.setSessionManager( sessionManager );
  
          return servletHandler;
      }
  
      /**
       * Loads a web application from the appURL, the application must use
       * the correct directory structure for a web application, i.e WEB-INF/web.xml
       * must exist within the appURL.
       * 
       * @param contextName The name to bind for the context (should not contain a leading / or trailing /*.
       * @param appURL The directory path to load as an application.
       */
      private void loadWebApplicationContext(String contextName, String appURL) {
          WebApplicationContext wac;
          try {
              wac = new WebApplicationContext(appURL);
              
              // Check to see if this is a WAR file, if so extract the WAR.
              File app = new File(appURL);
              if (app.isFile()) {
                  String filename = app.getName();
                  int index = filename.lastIndexOf('.');
                  if (index != -1) {
                      String ext = filename.substring(index + 1);
                      if (ext.equalsIgnoreCase("war")) {
                          wac.setExtractWAR(true);
                      }
                  }
              }
              wac.setContextPath("/" + contextName + "/*");
              String clazzName = org.apache.avalon.merlin.http.SessionManager.class.getName();
              wac.getServletHandler().setSessionManager((SessionManager) m_serviceManager.lookup(clazzName));
          } catch (Exception e) {
              m_logger.error("Failed to load context: " + contextName);
              return;
          }
          m_httpServer.addContext(wac);
      }
  
      /**
       * Creates a new AJP13 Listener
       */
      private HttpListener createAJP13Listener(Configuration config) {
          AJP13Listener listener = new AJP13Listener();
          listener.setMaxIdleTimeMs(config.getAttributeAsInteger(CFG_LISTENER_TIMEOUT, 60000));
          return listener;
      }
          
      /**
       * Creates a new Socket Listener
       */
      private HttpListener createSocketListener(Configuration config) {
          SocketListener listener = new SocketListener();
          listener.setMaxIdleTimeMs(config.getAttributeAsInteger(CFG_LISTENER_TIMEOUT, 60000));
          return listener;
      }
  
      /**
       * Creates a default sun jsse listener.
       * Contributed by Timothy Bennett [exterminatorx@comcast.net].
       * @param configuration
       * @return The newly created sun jsse listener
       * @throws Exception
       */
      private HttpListener createSunJsseListener(Configuration configuration) throws Exception {
          SunJsseListener listener = new SunJsseListener();
          listener.setMaxIdleTimeMs(configuration.getAttributeAsInteger(CFG_LISTENER_TIMEOUT, 60000));
          Configuration ksconfig = configuration.getChild("keystore");
          String fileName = ksconfig.getChild("file").getValue("conf/.keystore");
          File configuredFile = new File(fileName);
          if (!configuredFile.isAbsolute()) {
              listener.setKeystore(new File(m_basedir, fileName).getAbsolutePath());
          } else {
              listener.setKeystore(configuredFile.getAbsolutePath());
          }
          listener.setPassword(ksconfig.getChild("password").getValue(null));
          listener.setKeyPassword(ksconfig.getChild("key-password").getValue(null));
          return listener;
      }
  }
  
  
  
  1.1                  avalon/merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/example/ExampleServiceImpl.java
  
  Index: ExampleServiceImpl.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http.example;
  
  import org.apache.avalon.merlin.http.example.ExampleService;
  
  /**
   * A basic service implementation to test the services addition to the web server.
   *
   * @author Howard Henson
   * @author  <a href="mailto:exterminatorx@comcast.net">Timothy Bennett</a>
   * @avalon.component name="ex-service" version="1.1" lifestyle="transient"
   * @avalon.service type="org.apache.avalon.merlin.http.example.ExampleService" version="1.1"
   */
  public class ExampleServiceImpl implements ExampleService {
      
      /**
       * @see org.mortbay.jettyphoenix.services.web.test.TestService#getName()
       */
      public String getName() {
          return "You have invoked a method from component: " + ExampleServiceImpl.class.getName();
      }
  }
  
  
  
  
  1.1                  avalon/merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/example/ExampleServlet.java
  
  Index: ExampleServlet.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http.example;
  
  import java.io.IOException;
  
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  
  import org.apache.avalon.merlin.http.WebServer;
  import org.apache.avalon.merlin.http.example.ExampleService;
  
  /**
   * Tests whether or not the service manager is being correctly passed to the servlet
   * and whether or not the service can in fact successfully call an Avalon service.
   *
   * @author Howard Henson
   * @author <a href="mailto:timothy.bennett@gxs.com">Timothy Bennett</a>
   * @version 1.1
   */
  public class ExampleServlet extends HttpServlet {
      
      /**
       * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
       */
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
          throws ServletException, IOException {
          
          ServiceManager serviceManager = (ServiceManager) req.getSession().getAttribute(WebServer.SERVICE_MANAGER);
          if (serviceManager != null) {
              resp.getOutputStream().println("<html><head><title>Worked</title></head><body><h1>It worked</h1>");
              try {
                  ExampleService service = (ExampleService) serviceManager.lookup(ExampleService.class.getName());
                  resp.getOutputStream().println("<p>" + service.getName() + "</p>");
              } catch(ServiceException e) {
                  resp.getOutputStream().println("Failed to get service<br>" + e.getMessage());
              }
              resp.getOutputStream().println("</body></html>");
          } else {
              resp.getOutputStream().println("<html><head>Failed</head><body><h1>It failed</h1></body></html>");
          }
      }
      
  }
  
  
  
  1.1                  avalon/merlin/web/http/impl/src/java/org/apache/avalon/merlin/http/example/ExampleSessionManager.java
  
  Index: ExampleSessionManager.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http.example;
  
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  
  import org.apache.avalon.merlin.http.AvalonSessionManager;
  
  /**
   * Subclasses the <code>AvalonSessionManager</code> so that we can declare the
   * service dependencies we want to make available to any servlets.
   * 
   * @author Howard Henson
   * @author  <a href="mailto:exterminatorx@comcast.net">Timothy Bennett</a>
   * @avalon.component name="session-mgr" version="1.1" lifestyle="singleton"
   * @avalon.service type="org.apache.avalon.merlin.http.SessionManager" version="1.1"
   * @avalon.service type="org.mortbay.jetty.servlet.SessionManager"
   */
  public class ExampleSessionManager extends AvalonSessionManager {
      
      /** Creates a new instance of ExampleSessionManager */
      public ExampleSessionManager() {
          super();
      }
      
      /**
       * @avalon.dependency type="org.apache.avalon.merlin.http.example.ExampleService" version="1.1"
       * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
       */
      public void service(ServiceManager manager) throws ServiceException {
          super.service(manager);
      }
  }
  
  
  
  1.1                  avalon/merlin/web/http/spi/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  .classpath
  .project
  target
  maven.log
  home
  
  
  
  1.1                  avalon/merlin/web/http/spi/maven.xml
  
  Index: maven.xml
  ===================================================================
  <project default="jar:jar" xmlns:maven="jelly:maven" xmlns:j="jelly:core" xmlns:util="jelly:util">
  
      <preGoal name="java:compile">
          <attainGoal name="avalon:meta"/>
      </preGoal>
      
  </project>
  
  
  
  1.1                  avalon/merlin/web/http/spi/project.xml
  
  Index: project.xml
  ===================================================================
  <?xml version="1.0" encoding="ISO-8859-1"?>
  
  <project>
  
      <extend>${basedir}/../../../project.xml</extend>
      
      <groupId>avalon-http</groupId>
      <id>avalon-http-api</id>
      <name>Avalon HTTP API</name>
      <currentVersion>1.3</currentVersion>
      <package>org.apache.avalon.merlin.http</package>
      <inceptionYear>2003</inceptionYear>
      <shortDescription>Avalon HTTP Facility API</shortDescription>
  
      <dependencies>
          <dependency>
              <groupId>jetty</groupId>
              <artifactId>org.mortbay.jetty</artifactId>
              <version>4.2.14</version>
          </dependency>
          
          <dependency>
            <id>servletapi</id>
            <version>2.3</version>
          </dependency>
      </dependencies>
  
      
  </project>
  
  
  
  1.1                  avalon/merlin/web/http/spi/src/java/org/apache/avalon/merlin/http/SessionManager.java
  
  Index: SessionManager.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http;
  
  /**
   * The service that provides access to a web server session manager.
   * 
   * @author Howard Henson
   * @author <a href="mailto:timothy.bennett@gxs.com">Timothy Bennett</a>
   * @avalon.service type="org.mortbay.jetty.servlet.SessionManager"
   */
  public interface SessionManager extends org.mortbay.jetty.servlet.SessionManager{    
  }
  
  
  
  1.1                  avalon/merlin/web/http/spi/src/java/org/apache/avalon/merlin/http/WebServer.java
  
  Index: WebServer.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http;
  
  /**
   * A service that provides web server/servlet container facilities.
   *
   * @author Howard Henson
   * @author <a href="mailto:timothy.bennett@gxs.com">Timothy Bennett</a>
   * @avalon.service version="1.2"
   */
  public interface WebServer {
      /**
       * The key to use in order to extract the service manager from the
       * HTTP session.
       */
      public static final String SERVICE_MANAGER = "avalon.service.manager";
      
      /**
       * The key to use in order to extract the logger from the HTTP
       * session.
       */
      public static final String LOGGER = "avalon.logger";
  
      /**
       * Allows for hot deployment of WAR files or extracted web application
       * files during run time. The services that will be available to the new application
       * is limited to the currently defined services offered to the current block.
       *
       * @param context name of the context to associate to this web application
       * @param appPath the relative path to the directory or war file that is
       * associated with this application
       */
      public void deployWebApplication(String context, String appPath);
  
      /**
       * Removes the web application context from the server's list of available contexts.
       * This may require the stopping and starting of the underlying web service provider.
       *
       * @param context name of the context to remove
       * @return <b>true</b> if the context removal was successful
       */
      public boolean removeWebApplication(String context);
  
      /**
       * Allows the dynamic starting of a listener.
       *
       * @param name the alias of the listener that has been defined in the component
       * configuration
       */
      public void startListener(String name) throws Exception;
  
      /**
       * Allows the dynamic stopping of a listener.
       *
       * @param name the alias of the listener that has been defined in the component
       * configuration
       */
      public void stopListener(String name) throws Exception;
  }
  
  
  
  1.1                  avalon/merlin/web/http/spi/src/java/org/apache/avalon/merlin/http/example/ExampleService.java
  
  Index: ExampleService.java
  ===================================================================
  /*
   
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "Jakarta", "Apache Avalon", "Avalon Framework" and
      "Apache Software Foundation"  must not be used to endorse or promote
      products derived  from this  software without  prior written
      permission. For written permission, please contact apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation. For more  information on the
   Apache Software Foundation, please see <http://www.apache.org/>.
   
   */
  
  package org.apache.avalon.merlin.http.example;
  
  /**
   * An example service to demonstrate how servlets gain access to other avalon
   * services.
   *
   * @author Howard Henson
   * @author <a href="mailto:timothy.bennett@gxs.com">Timothy Bennett</a>
   * @avalon.service version="1.1"
   */
  public interface ExampleService {
      public String getName();
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe@avalon.apache.org
For additional commands, e-mail: cvs-help@avalon.apache.org


Mime
View raw message