You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by hu...@apache.org on 2003/10/01 19:04:02 UTC
cvs commit: jakarta-commons-sandbox/chain/src/java/org/apache/commons/chain/web ChainListener2.java
husted 2003/10/01 10:04:02
Added: chain/src/java/org/apache/commons/chain/web
ChainListener2.java
Log:
ContextListener that loads resoruces from classpath on demand.
Revision Changes Path
1.1 jakarta-commons-sandbox/chain/src/java/org/apache/commons/chain/web/ChainListener2.java
Index: ChainListener2.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons-sandbox/chain/src/java/org/apache/commons/chain/web/ChainListener2.java,v 1.1 2003/10/01 17:04:02 husted Exp $
* $Revision: 1.1 $
* $Date: 2003/10/01 17:04:02 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", 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 names without prior written
* permission of the Apache Group.
*
* 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 (INCLUDING, 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.commons.chain.web;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.config.ConfigParser;
import org.apache.commons.chain.impl.CatalogBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.net.URL;
/**
* EXPERIMENTAL CLASS :: MAY BE REMOVED AT ANY TIME.
*
* <p>Optional <code>ServletContextListener</code> that automatically
* scans chain configuration files in the current web application at
* startup time, and exposes the result in a {@link Catalog} under a
* specified servlet context attribute. The following
* <code>context-param</code> attributes are utilized:</p>
* <ul>
* <li><strong>org.apache.commons.chain.CONFIG_WEB_RESOURCE</strong> -
* comma-delimited list of chain configuration webapp resources
* to be loaded. (For example,
* <code>/WEB-INF/chain-config.xml</code>.)</li>
* <li><strong>org.apache.commons.chain.CONFIG_RESOURCE</strong> -
* comma-delimited list of chain configuration classpath resources
* to be loaded. (For example,
* <code>com/myCompany/command/ChainConfig.xml</code>.)</li>
* <li><strong>org.apache.commons.chain.CONFIG_CATALOG</strong> -
* Name of the servlet context attribute under which the
* resulting {@link Catalog} will be exposed. If not specified,
* defaults to <code>Chain.CATALOG_KEY</code>.</li>
* </ul>
*
* <p>When a web application that has configured this listener is
* started, it will create a new {@link Catalog} (if needed) and populate it by
* scanning configuration resources from the init parameter described
* above. If a {@link Catalog} instance already exists at the specified
* attribute, any new parsed definitions will be merged into the existing
* catalog (the last definition for a particular name wins). </p>
*
* <p>At least one configuration file must be specified, using either
* the <code>org.apache.commons.chain.CONFIG_WEB_RESOURCE</code> or
* <code>org.apache.commons.chain.CONFIG_RESOURCE<code> context attributes,
* or a runtime error occurs. You may also specify more than one file, using
* either or both attributes.</p>
*
* <p>This class requires Servlet 2.3 or later. If you are running on
* a Servlet 2.2 system, consider using {@link ChainServlet} instead.</p>
*
* <p>To configure the listener, add an elements like this to the web deployment descriptor (web.xml),
* before any servlet elements: </p>
*
* <pre><code>
* <context-param>
* <param-name>org.apache.commons.chain.CONFIG_RESOURCE</param-name>
* <param-value>us_ok_deq_wqdata/command/ChainConfig.xml</param-value>
* </context-param>
*
* <context-param>
* <param-name>org.apache.commons.chain.CONFIG_WEB_RESOURCE</param-name>
* <param-value>/WEB-INF/chain-config.xml</param-value>
* </context-param>
*
* <listener>
* <listener-class>org.apache.commons.chain.web.ChainListener2</listener-class>
* </listener>
* </code></pre>
*
* @author Craig R. McClanahan
* @author Ted Husted
* @version $Revision: 1.1 $ $Date: 2003/10/01 17:04:02 $
*/
public class ChainListener2 implements ServletContextListener {
// ------------------------------------------------------ Manifest Constants
/**
* <p>The default servlet context attribute key.</p>
*/
private static final String CONFIG_ATTR_DEFAULT = Catalog.CATALOG_KEY;
/**
* <p>The name of the context init parameter containing the name of the
* servlet context attribute under which our resulting {@link Catalog}
* will be stored.</p>
*/
public static final String CONFIG_ATTR =
"org.apache.commons.chain.CONFIG_ATTR";
/**
* <p>The name of the context init parameter containing a comma-delimited
* list of web applicaton resources to be scanned.</p>
*/
public static final String CONFIG_WEB_RESOURCE =
"org.apache.commons.chain.CONFIG_WEB_RESOURCE";
/**
* <p>The name of the context init parameter containing a comma-delimited
* list of resources on the application classpath to be scanned.</p>
*/
public static final String CONFIG_RESOURCE =
"org.apache.commons.chain.CONFIG_RESOURCE";
// -------------------------------------------------------- Static Variables
/**
* <p>The <code>Log</code> instance for this class.</p>
*/
private static final Log log = LogFactory.getLog(ChainListener2.class);
// ------------------------------------------ ServletContextListener Methods
/**
* <p>Remove the configured {@link Catalog} from the servlet context
* attributes for this web application.</p>
*
* @param event <code>ServletContextEvent</code> to be processed
*/
public void contextDestroyed(ServletContextEvent event) {
ServletContext context = event.getServletContext();
String attr = context.getInitParameter(CONFIG_ATTR);
if (attr == null) {
attr = CONFIG_ATTR_DEFAULT;
}
context.removeAttribute(attr);
}
/**
* Add Chains and/or Commands from one or more web resource
* configuration files to the runtime Catalog.
*
* @param resource A comma-delimited list of web resources
* @param context ServletContext instance to locate web resources
* @param parser ConfigParser instance to parse the configuration file
* @param catalog Catalog instance to which Commands and Chains are added
*/
private void parseWebResource(String resource, ServletContext context, ConfigParser parser, Catalog catalog) {
String path = null;
try {
while (true) {
int comma = resource.indexOf(",");
if (comma < 0) {
path = resource.trim();
resource = "";
} else {
path = resource.substring(0, comma);
resource = resource.substring(comma + 1);
}
if (path.length() < 1) {
break;
}
URL url = context.getResource(path);
if (url == null) {
throw new IllegalStateException
("Missing chain config resource '" + path + "'");
}
if (log.isDebugEnabled()) {
log.debug("Loading chain config resource '" + path + "'");
}
parser.parse(catalog, url);
}
} catch (Exception e) {
throw new RuntimeException
("Exception parsing chain config resource '" + path + "': " +
e.getMessage());
}
}
/**
* Add Chains and/or Commands from one or more classpath resource
* configuration files to the runtime Catalog.
*
* @param resource A comma-delimited list of web resources
* @param parser ConfigParser instance to parse the configuration file
* @param catalog Catalog instance to which Commands and Chains are added
*/
private void parseResource(String resource, ConfigParser parser, Catalog catalog) {
String path = null;
URL configResource = null;
try {
while (true) {
int comma = resource.indexOf(",");
if (comma < 0) {
path = resource.trim();
resource = "";
} else {
path = resource.substring(0, comma);
resource = resource.substring(comma + 1);
}
if (path.length() < 1) {
break;
}
log.info("Loading classloader resources from '" +
resource + "'");
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = this.getClass().getClassLoader();
}
configResource = loader.getResource(path);
parser.parse(catalog, configResource);
}
} catch (Exception e) {
throw new RuntimeException
("Exception parsing chain config resource '" + path + "': " +
e.getMessage());
}
}
/**
* <p>Scan the required chain configuration resources, assemble the
* configured chains into a {@link Catalog}, and expose it as a
* servlet context attribute under the specified key.</p>
*
* @param event <code>ServletContextEvent</code> to be processed
*/
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
String attr = context.getInitParameter(CONFIG_ATTR);
if (attr == null) {
attr = CONFIG_ATTR_DEFAULT;
}
// Retrieve or create the Catalog instance we will be updating
Catalog catalog = (Catalog) context.getAttribute(attr);
if (catalog == null) {
catalog = new CatalogBase();
}
// Construct the configuration resource parser we will use
// FIXME - Do we need to make this more configurable?
ConfigParser parser = new ConfigParser();
// Parse the web resources specified in our init parameter (if any)
String webResource = context.getInitParameter(CONFIG_WEB_RESOURCE);
if (webResource != null) parseWebResource(webResource, context, parser, catalog);
// Parse the class resources specified in our init parameter (if any)
String resource = context.getInitParameter(CONFIG_RESOURCE);
if (resource != null) parseResource(resource, parser, catalog);
if ((webResource == null) && (resource == null)) {
throw new RuntimeException
("ChainListener2: At least one resource must be specified '");
}
// Expose the completed catalog
context.setAttribute(attr, catalog);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org