/*
* $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/startup/ContextConfig.java,v 1.52.2.1 2002/02/20 03:18:32 remm Exp $
* $Revision: 1.52.2.1 $
* $Date: 2002/02/20 03:18:32 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999-2001 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", "Tomcat", 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/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.catalina.startup;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Stack;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.servlet.ServletContext;
import javax.naming.NamingException;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import org.apache.catalina.Authenticator;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Logger;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.core.ContainerBase;
import org.apache.catalina.core.DefaultContext;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.deploy.ApplicationParameter;
import org.apache.catalina.deploy.ContextEjb;
import org.apache.catalina.deploy.ContextEnvironment;
import org.apache.catalina.deploy.ErrorPage;
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.deploy.ContextLocalEjb;
import org.apache.catalina.deploy.ContextResource;
import org.apache.catalina.loader.Extension;
import org.apache.catalina.util.StringManager;
import org.apache.catalina.util.xml.SaxContext;
import org.apache.catalina.util.xml.XmlAction;
import org.apache.catalina.util.xml.XmlMapper;
import org.apache.catalina.valves.ValveBase;
import org.xml.sax.SAXParseException;
/**
* Startup event listener for a <b>Context</b> that configures the properties
* of that Context, and the associated defined servlets.
*
* @author Craig R. McClanahan
* @version $Revision: 1.52.2.1 $ $Date: 2002/02/20 03:18:32 $
*/
public final class ContextConfig
implements LifecycleListener {
// ----------------------------------------------------- Instance Variables
/**
* The set of Authenticators that we know how to configure. The key is
* the name of the implemented authentication method, and the value is
* the fully qualified Java class name of the corresponding Valve.
*/
private static ResourceBundle authenticators = null;
/**
* The Context we are associated with.
*/
private Context context = null;
/**
* The debugging detail level for this component.
*/
private int debug = 0;
/**
* Track any fatal errors during startup configuration processing.
*/
private boolean ok = false;
/**
* The string resources for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
// ------------------------------------------------------------- Properties
/**
* Return the debugging detail level for this component.
*/
public int getDebug() {
return (this.debug);
}
/**
* Set the debugging detail level for this component.
*
* @param debug The new debugging detail level
*/
public void setDebug(int debug) {
this.debug = debug;
}
// --------------------------------------------------------- Public Methods
/**
* Process the START event for an associated Context.
*
* @param event The lifecycle event that has occurred
*/
public void lifecycleEvent(LifecycleEvent event) {
// Identify the context we are associated with
try {
context = (Context) event.getLifecycle();
if (context instanceof StandardContext) {
int contextDebug = ((StandardContext) context).getDebug();
if (contextDebug > this.debug)
this.debug = contextDebug;
}
} catch (ClassCastException e) {
log(sm.getString("contextConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.START_EVENT))
start();
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
// -------------------------------------------------------- Private Methods
/**
* Process the application configuration file, if it exists.
*
* @param mapper The XmlMapper to be used
*/
private void applicationConfig(XmlMapper mapper) {
// Open the application web.xml file, if it exists
InputStream stream = null;
ServletContext servletContext = context.getServletContext();
if (servletContext != null)
stream = servletContext.getResourceAsStream
(Constants.ApplicationWebXml);
if (stream == null) {
log(sm.getString("contextConfig.applicationMissing"));
return;
}
// Process the application web.xml file
try {
if (context instanceof StandardContext)
((StandardContext) context).setReplaceWelcomeFiles(true);
mapper.readXml(stream, context);
} catch (InvocationTargetException e) {
log(sm.getString("contextConfig.applicationConfig"),
e.getTargetException());
ok = false;
} catch (SAXParseException e) {
log(sm.getString("contextConfig.applicationParse"), e);
log(sm.getString("contextConfig.applicationPosition",
"" + e.getLineNumber(),
"" + e.getColumnNumber()));
ok = false;
} catch (Exception e) {
log(sm.getString("contextConfig.applicationParse"), e);
ok = false;
} finally {
try {
stream.close();
} catch (IOException e) {
log(sm.getString("contextConfig.applicationClose"), e);
}
}
}
/**
* Set up an Authenticator automatically if required, and one has not
* already been configured.
*/
private synchronized void authenticatorConfig() {
// Does this Context require an Authenticator?
SecurityConstraint constraints[] = context.findConstraints();
if ((constraints == null) || (constraints.length == 0))
return;
LoginConfig loginConfig = context.getLoginConfig();
if (loginConfig == null) {
loginConfig = new LoginConfig("NONE", null, null, null);
context.setLoginConfig(loginConfig);
}
// Has an authenticator been configured already?
if (context instanceof Authenticator)
return;
if (context instanceof ContainerBase) {
Pipeline pipeline = ((ContainerBase) context).getPipeline();
if (pipeline != null) {
Valve basic = pipeline.getBasic();
if ((basic != null) && (basic instanceof Authenticator))
return;
Valve valves[] = pipeline.getValves();
for (int i = 0; i < valves.length; i++) {
if (valves[i] instanceof Authenticator)
return;
}
}
} else {
return; // Cannot install a Valve even if it would be needed
}
// Has a Realm been configured for us to authenticate against?
if (context.getRealm() == null) {
log(sm.getString("contextConfig.missingRealm"));
ok = false;
return;
}
// Load our mapping properties if necessary
if (authenticators == null) {
try {
authenticators = ResourceBundle.getBundle
("org.apache.catalina.startup.Authenticators");
} catch (MissingResourceException e) {
log(sm.getString("contextConfig.authenticatorResources"), e);
ok = false;
return;
}
}
// Identify the class name of the Valve we should configure
String authenticatorName = null;
try {
authenticatorName =
authenticators.getString(loginConfig.getAuthMethod());
} catch (MissingResourceException e) {
authenticatorName = null;
}
if (authenticatorName == null) {
log(sm.getString("contextConfig.authenticatorMissing",
loginConfig.getAuthMethod()));
ok = false;
return;
}
// Instantiate and install an Authenticator of the requested class
Valve authenticator = null;
try {
Class authenticatorClass = Class.forName(authenticatorName);
authenticator = (Valve) authenticatorClass.newInstance();
if (context instanceof ContainerBase) {
Pipeline pipeline = ((ContainerBase) context).getPipeline();
if (pipeline != null) {
pipeline.addValve(authenticator);
log(sm.getString("contextConfig.authenticatorConfigured",
loginConfig.getAuthMethod()));
}
}
} catch (Throwable t) {
log(sm.getString("contextConfig.authenticatorInstantiate",
authenticatorName), t);
ok = false;
}
}
/**
* Create and deploy a Valve to expose the SSL certificates presented
* by this client, if any. If we cannot instantiate such a Valve
* (because the JSSE classes are not available), silently continue.
*/
private void certificatesConfig() {
// Validate that the JSSE classes are present
try {
Class clazz = this.getClass().getClassLoader().loadClass
("javax.net.ssl.SSLSocket");
if (clazz == null)
return;
} catch (Throwable t) {
return;
}
// Instantiate a new CertificatesValve if possible
Valve certificates = null;
try {
Class clazz =
Class.forName("org.apache.catalina.valves.CertificatesValve");
certificates = (Valve) clazz.newInstance();
} catch (Throwable t) {
return; // Probably JSSE classes not present
}
// Add this Valve to our Pipeline
try {
if (context instanceof ContainerBase) {
Pipeline pipeline = ((ContainerBase) context).getPipeline();
if (pipeline != null) {
pipeline.addValve(certificates);
log(sm.getString
("contextConfig.certificatesConfig.added"));
}
}
} catch (Throwable t) {
log(sm.getString("contextConfig.certificatesConfig.error"), t);
ok = false;
}
}
/**
* Create and return an XmlMapper configured to process a tag library
* descriptor, looking for additional listener classes to be registered.
*/
private XmlMapper createTldMapper() {
XmlMapper mapper = new XmlMapper();
if (debug > 0)
mapper.setDebug(3);
mapper.setValidating(true);
mapper.registerDTDRes(Constants.TldDtdPublicId_11,
Constants.TldDtdResourcePath_11);
mapper.registerDTDRes(Constants.TldDtdPublicId_12,
Constants.TldDtdResourcePath_12);
mapper.addRule("taglib/listener/listener-class",
mapper.methodSetter("addApplicationListener", 0));
return (mapper);
}
/**
* Create and return an XmlMapper configured to process the web application
* deployment descriptor (web.xml).
*/
private XmlMapper createWebMapper() {
XmlMapper mapper = new XmlMapper();
if (debug > 0)
mapper.setDebug(3);
mapper.setValidating(true);
mapper.registerDTDRes(Constants.WebDtdPublicId_22,
Constants.WebDtdResourcePath_22);
mapper.registerDTDRes(Constants.WebDtdPublicId_23,
Constants.WebDtdResourcePath_23);
mapper.addRule("web-app",
new SetPublicIdAction("setPublicId"));
mapper.addRule("web-app/context-param",
mapper.methodSetter("addParameter", 2));
mapper.addRule("web-app/context-param/param-name",
mapper.methodParam(0));
mapper.addRule("web-app/context-param/param-value",
mapper.methodParam(1));
mapper.addRule("web-app/display-name",
mapper.methodSetter("setDisplayName", 0));
mapper.addRule("web-app/distributable",
new SetDistributableAction());
mapper.addRule("web-app/ejb-local-ref",
mapper.objectCreate("org.apache.catalina.deploy.ContextLocalEjb"));
mapper.addRule("web-app/ejb-local-ref",
mapper.addChild("addLocalEjb",
"org.apache.catalina.deploy.ContextLocalEjb"));
mapper.addRule("web-app/ejb-local-ref/description",
mapper.methodSetter("setDescription", 0));
mapper.addRule("web-app/ejb-local-ref/ejb-ref-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/ejb-local-ref/ejb-ref-type",
mapper.methodSetter("setType", 0));
mapper.addRule("web-app/ejb-local-ref/local-home",
mapper.methodSetter("setHome", 0));
mapper.addRule("web-app/ejb-local-ref/local",
mapper.methodSetter("setLocal", 0));
mapper.addRule("web-app/ejb-local-ref/ejb-link",
mapper.methodSetter("setLink", 0));
mapper.addRule("web-app/ejb-ref",
mapper.objectCreate("org.apache.catalina.deploy.ContextEjb"));
mapper.addRule("web-app/ejb-ref",
mapper.addChild("addEjb",
"org.apache.catalina.deploy.ContextEjb"));
mapper.addRule("web-app/ejb-ref/description",
mapper.methodSetter("setDescription", 0));
mapper.addRule("web-app/ejb-ref/ejb-ref-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/ejb-ref/ejb-ref-type",
mapper.methodSetter("setType", 0));
mapper.addRule("web-app/ejb-ref/home",
mapper.methodSetter("setHome", 0));
mapper.addRule("web-app/ejb-ref/remote",
mapper.methodSetter("setRemote", 0));
mapper.addRule("web-app/ejb-ref/ejb-link",
mapper.methodSetter("setLink", 0));
mapper.addRule("web-app/env-entry",
mapper.objectCreate("org.apache.catalina.deploy.ContextEnvironment"));
mapper.addRule("web-app/env-entry",
mapper.addChild("addEnvironment",
"org.apache.catalina.deploy.ContextEnvironment"));
mapper.addRule("web-app/env-entry/env-entry-description",
mapper.methodSetter("setDescription", 0));
mapper.addRule("web-app/env-entry/env-entry-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/env-entry/env-entry-type",
mapper.methodSetter("setType", 0));
mapper.addRule("web-app/env-entry/env-entry-value",
mapper.methodSetter("setValue", 0));
mapper.addRule("web-app/error-page",
mapper.objectCreate("org.apache.catalina.deploy.ErrorPage"));
mapper.addRule("web-app/error-page",
mapper.addChild("addErrorPage",
"org.apache.catalina.deploy.ErrorPage"));
mapper.addRule("web-app/error-page/error-code",
mapper.methodSetter("setErrorCode", 0));
mapper.addRule("web-app/error-page/exception-type",
mapper.methodSetter("setExceptionType", 0));
mapper.addRule("web-app/error-page/location",
mapper.methodSetter("setLocation", 0));
mapper.addRule("web-app/filter",
mapper.objectCreate("org.apache.catalina.deploy.FilterDef"));
mapper.addRule("web-app/filter",
mapper.addChild("addFilterDef",
"org.apache.catalina.deploy.FilterDef"));
mapper.addRule("web-app/filter/description",
mapper.methodSetter("setDescription", 0));
mapper.addRule("web-app/filter/display-name",
mapper.methodSetter("setDisplayName", 0));
mapper.addRule("web-app/filter/filter-class",
mapper.methodSetter("setFilterClass", 0));
mapper.addRule("web-app/filter/filter-name",
mapper.methodSetter("setFilterName", 0));
mapper.addRule("web-app/filter/icon/large-icon",
mapper.methodSetter("setLargeIcon", 0));
mapper.addRule("web-app/filter/icon/small-icon",
mapper.methodSetter("setSmallIcon", 0));
mapper.addRule("web-app/filter/init-param",
mapper.methodSetter("addInitParameter", 2));
mapper.addRule("web-app/filter/init-param/param-name",
mapper.methodParam(0));
mapper.addRule("web-app/filter/init-param/param-value",
mapper.methodParam(1));
mapper.addRule("web-app/filter-mapping",
mapper.objectCreate("org.apache.catalina.deploy.FilterMap"));
mapper.addRule("web-app/filter-mapping",
mapper.addChild("addFilterMap",
"org.apache.catalina.deploy.FilterMap"));
mapper.addRule("web-app/filter-mapping/filter-name",
mapper.methodSetter("setFilterName", 0));
mapper.addRule("web-app/filter-mapping/servlet-name",
mapper.methodSetter("setServletName", 0));
mapper.addRule("web-app/filter-mapping/url-pattern",
mapper.methodSetter("setURLPattern", 0));
mapper.addRule("web-app/listener/listener-class",
mapper.methodSetter("addApplicationListener", 0));
mapper.addRule("web-app/login-config",
mapper.objectCreate("org.apache.catalina.deploy.LoginConfig"));
mapper.addRule("web-app/login-config",
mapper.addChild("setLoginConfig",
"org.apache.catalina.deploy.LoginConfig"));
mapper.addRule("web-app/login-config/auth-method",
mapper.methodSetter("setAuthMethod", 0));
mapper.addRule("web-app/login-config/realm-name",
mapper.methodSetter("setRealmName", 0));
mapper.addRule("web-app/login-config/form-login-config/form-login-page",
mapper.methodSetter("setLoginPage", 0));
mapper.addRule("web-app/login-config/form-login-config/form-error-page",
mapper.methodSetter("setErrorPage", 0));
mapper.addRule("web-app/mime-mapping",
mapper.methodSetter("addMimeMapping", 2));
mapper.addRule("web-app/mime-mapping/extension",
mapper.methodParam(0));
mapper.addRule("web-app/mime-mapping/mime-type",
mapper.methodParam(1));
mapper.addRule("web-app/resource-env-ref",
mapper.methodSetter("addResourceEnvRef", 2));
mapper.addRule("web-app/resource-env-ref/resource-env-ref-name",
mapper.methodParam(0));
mapper.addRule("web-app/resource-env-ref/resource-env-ref-type",
mapper.methodParam(1));
mapper.addRule("web-app/resource-ref",
mapper.objectCreate("org.apache.catalina.deploy.ContextResource"));
mapper.addRule("web-app/resource-ref",
mapper.addChild("addResource",
"org.apache.catalina.deploy.ContextResource"));
mapper.addRule("web-app/resource-ref/description",
mapper.methodSetter("setDescription", 0));
mapper.addRule("web-app/resource-ref/res-auth",
mapper.methodSetter("setAuth", 0));
mapper.addRule("web-app/resource-ref/res-ref-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/resource-ref/res-sharing-scope",
mapper.methodSetter("setScope", 0));
mapper.addRule("web-app/resource-ref/res-type",
mapper.methodSetter("setType", 0));
mapper.addRule("web-app/security-constraint",
mapper.objectCreate("org.apache.catalina.deploy.SecurityConstraint"));
mapper.addRule("web-app/security-constraint",
mapper.addChild("addConstraint",
"org.apache.catalina.deploy.SecurityConstraint"));
mapper.addRule("web-app/security-constraint/auth-constraint",
new SetAuthConstraint());
mapper.addRule("web-app/security-constraint/auth-constraint/role-name",
mapper.methodSetter("addAuthRole", 0));
mapper.addRule("web-app/security-constraint/display-name",
mapper.methodSetter("setDisplayName", 0));
mapper.addRule("web-app/security-constraint/user-data-constraint/transport-guarantee",
mapper.methodSetter("setUserConstraint", 0));
mapper.addRule("web-app/security-constraint/web-resource-collection",
mapper.objectCreate("org.apache.catalina.deploy.SecurityCollection"));
mapper.addRule("web-app/security-constraint/web-resource-collection",
mapper.addChild("addCollection",
"org.apache.catalina.deploy.SecurityCollection"));
mapper.addRule("web-app/security-constraint/web-resource-collection/http-method",
mapper.methodSetter("addMethod", 0));
mapper.addRule("web-app/security-constraint/web-resource-collection/url-pattern",
mapper.methodSetter("addPattern", 0));
mapper.addRule("web-app/security-constraint/web-resource-collection/web-resource-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/security-role",
mapper.methodSetter("addSecurityRole", 1));
mapper.addRule("web-app/security-role/role-name",
mapper.methodParam(0));
mapper.addRule("web-app/servlet",
new WrapperCreate(context));
mapper.addRule("web-app/servlet",
mapper.addChild("addChild",
"org.apache.catalina.Container"));
mapper.addRule("web-app/servlet/init-param",
mapper.methodSetter("addInitParameter", 2));
mapper.addRule("web-app/servlet/init-param/param-name",
mapper.methodParam(0));
mapper.addRule("web-app/servlet/init-param/param-value",
mapper.methodParam(1));
mapper.addRule("web-app/servlet/jsp-file",
mapper.methodSetter("setJspFile", 0));
mapper.addRule("web-app/servlet/load-on-startup",
mapper.methodSetter("setLoadOnStartupString", 0));
mapper.addRule("web-app/servlet/run-as/role-name",
mapper.methodSetter("setRunAs", 0));
mapper.addRule("web-app/servlet/security-role-ref",
mapper.methodSetter("addSecurityReference", 2));
mapper.addRule("web-app/servlet/security-role-ref/role-link",
mapper.methodParam(1));
mapper.addRule("web-app/servlet/security-role-ref/role-name",
mapper.methodParam(0));
mapper.addRule("web-app/servlet/servlet-class",
mapper.methodSetter("setServletClass", 0));
mapper.addRule("web-app/servlet/servlet-name",
mapper.methodSetter("setName", 0));
mapper.addRule("web-app/servlet-mapping",
mapper.methodSetter("addServletMapping", 2));
mapper.addRule("web-app/servlet-mapping/servlet-name",
mapper.methodParam(1));
mapper.addRule("web-app/servlet-mapping/url-pattern",
mapper.methodParam(0));
mapper.addRule("web-app/session-config",
mapper.methodSetter("setSessionTimeout", 1,
new String[]{"int"}));
mapper.addRule("web-app/session-config/session-timeout",
mapper.methodParam(0));
mapper.addRule("web-app/taglib",
mapper.methodSetter("addTaglib", 2));
mapper.addRule("web-app/taglib/taglib-location",
mapper.methodParam(1));
mapper.addRule("web-app/taglib/taglib-uri",
mapper.methodParam(0));
mapper.addRule("web-app/welcome-file-list/welcome-file",
mapper.methodSetter("addWelcomeFile", 0));
return (mapper);
}
/**
* Process the default configuration file, if it exists.
*
* @param mapper The XmlMapper to be used
*/
private void defaultConfig(XmlMapper mapper) {
// Open the default web.xml file, if it exists
File file = new File(Constants.DefaultWebXml);
if (!file.isAbsolute())
file = new File(System.getProperty("catalina.base"),
Constants.DefaultWebXml);
FileInputStream stream = null;
try {
stream = new FileInputStream(file.getCanonicalPath());
} catch (FileNotFoundException e) {
log(sm.getString("contextConfig.defaultMissing"));
return;
} catch (IOException e) {
log(sm.getString("contextConfig.defaultMissing"), e);
return;
}
// Process the default web.xml file
try {
if (context instanceof StandardContext)
((StandardContext) context).setReplaceWelcomeFiles(true);
mapper.readXml(stream, context);
} catch (InvocationTargetException e) {
log(sm.getString("contextConfig.defaultConfig"),
e.getTargetException());
ok = false;
} catch (SAXParseException e) {
log(sm.getString("contextConfig.defaultParse"), e);
log(sm.getString("contextConfig.defaultPosition",
"" + e.getLineNumber(),
"" + e.getColumnNumber()));
ok = false;
} catch (Exception e) {
log(sm.getString("contextConfig.defaultParse"), e);
ok = false;
} finally {
try {
stream.close();
} catch (IOException e) {
log(sm.getString("contextConfig.defaultClose"), e);
}
}
}
/**
* Log a message on the Logger associated with our Context (if any)
*
* @param message Message to be logged
*/
private void log(String message) {
Logger logger = null;
if (context != null)
logger = context.getLogger();
if (logger != null)
logger.log("ContextConfig[" + context.getName() + "]: " + message);
else
System.out.println("ContextConfig[" + context.getName() + "]: "
+ message);
}
/**
* Log a message on the Logger associated with our Context (if any)
*
* @param message Message to be logged
* @param throwable Associated exception
*/
private void log(String message, Throwable throwable) {
Logger logger = null;
if (context != null)
logger = context.getLogger();
if (logger != null)
logger.log("ContextConfig[" + context.getName() + "] "
+ message, throwable);
else {
System.out.println("ContextConfig[" + context.getName() + "]: "
+ message);
System.out.println("" + throwable);
throwable.printStackTrace(System.out);
}
}
/**
* Process a "start" event for this Context.
*/
private synchronized void start() {
if (debug > 0)
log(sm.getString("contextConfig.start"));
context.setConfigured(false);
ok = true;
// Set properties based on DefaultContext
Container container = context.getParent();
if( !context.getOverride() ) {
if( container instanceof Host ) {
((Host)container).importDefaultContext(context);
container = container.getParent();
}
if( container instanceof Engine ) {
((Engine)container).importDefaultContext(context);
}
}
// Process the default and application web.xml files
XmlMapper mapper = createWebMapper();
defaultConfig(mapper);
applicationConfig(mapper);
// Scan tag library descriptor files for additional listener classes
if (ok)
tldConfig();
// Configure a certificates exposer valve, if required
if (ok)
certificatesConfig();
// Configure an authenticator if we need one
if (ok)
authenticatorConfig();
// Dump the contents of this pipeline if requested
if ((debug >= 1) && (context instanceof ContainerBase)) {
log("Pipline Configuration:");
Pipeline pipeline = ((ContainerBase) context).getPipeline();
Valve valves[] = null;
if (pipeline != null)
valves = pipeline.getValves();
if (valves != null) {
for (int i = 0; i < valves.length; i++) {
log(" " + valves[i].getInfo());
}
}
log("======================");
}
// Make our application available if no problems were encountered
if (ok)
context.setConfigured(true);
else {
log(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}
/**
* Process a "stop" event for this Context.
*/
private synchronized void stop() {
if (debug > 0)
log(sm.getString("contextConfig.stop"));
int i;
// Removing children
Container[] children = context.findChildren();
for (i = 0; i < children.length; i++) {
context.removeChild(children[i]);
}
// FIXME : remove mappers ?
// Removing application listeners
String[] applicationListeners = context.findApplicationListeners();
for (i = 0; i < applicationListeners.length; i++) {
context.removeApplicationListener(applicationListeners[i]);
}
// Removing application parameters
ApplicationParameter[] applicationParameters =
context.findApplicationParameters();
for (i = 0; i < applicationParameters.length; i++) {
context.removeApplicationParameter
(applicationParameters[i].getName());
}
// Removing security constraints
SecurityConstraint[] securityConstraints = context.findConstraints();
for (i = 0; i < securityConstraints.length; i++) {
context.removeConstraint(securityConstraints[i]);
}
// Removing Ejbs
ContextEjb[] contextEjbs = context.findEjbs();
for (i = 0; i < contextEjbs.length; i++) {
context.removeEjb(contextEjbs[i].getName());
}
// Removing environments
ContextEnvironment[] contextEnvironments = context.findEnvironments();
for (i = 0; i < contextEnvironments.length; i++) {
context.removeEnvironment(contextEnvironments[i].getName());
}
// Removing errors pages
ErrorPage[] errorPages = context.findErrorPages();
for (i = 0; i < errorPages.length; i++) {
context.removeErrorPage(errorPages[i]);
}
// Removing filter defs
FilterDef[] filterDefs = context.findFilterDefs();
for (i = 0; i < filterDefs.length; i++) {
context.removeFilterDef(filterDefs[i]);
}
// Removing filter maps
FilterMap[] filterMaps = context.findFilterMaps();
for (i = 0; i < filterMaps.length; i++) {
context.removeFilterMap(filterMaps[i]);
}
// Removing instance listeners
String[] instanceListeners = context.findInstanceListeners();
for (i = 0; i < instanceListeners.length; i++) {
context.removeInstanceListener(instanceListeners[i]);
}
// Removing local ejbs
ContextLocalEjb[] contextLocalEjbs = context.findLocalEjbs();
for (i = 0; i < contextLocalEjbs.length; i++) {
context.removeLocalEjb(contextLocalEjbs[i].getName());
}
// Removing Mime mappings
String[] mimeMappings = context.findMimeMappings();
for (i = 0; i < mimeMappings.length; i++) {
context.removeMimeMapping(mimeMappings[i]);
}
// Removing parameters
String[] parameters = context.findParameters();
for (i = 0; i < parameters.length; i++) {
context.removeParameter(parameters[i]);
}
// Removing resource env refs
String[] resourceEnvRefs = context.findResourceEnvRefs();
for (i = 0; i < resourceEnvRefs.length; i++) {
context.removeResourceEnvRef(resourceEnvRefs[i]);
}
// Removing resources
ContextResource[] contextResources = context.findResources();
for (i = 0; i < contextResources.length; i++) {
context.removeResource(contextResources[i].getName());
}
// Removing sercurity role
String[] securityRoles = context.findSecurityRoles();
for (i = 0; i < securityRoles.length; i++) {
context.removeSecurityRole(securityRoles[i]);
}
// Removing servlet mappings
String[] servletMappings = context.findServletMappings();
for (i = 0; i < servletMappings.length; i++) {
context.removeServletMapping(servletMappings[i]);
}
// FIXME : Removing status pages
// Removing taglibs
String[] taglibs = context.findTaglibs();
for (i = 0; i < taglibs.length; i++) {
context.removeTaglib(taglibs[i]);
}
// Removing welcome files
String[] welcomeFiles = context.findWelcomeFiles();
for (i = 0; i < welcomeFiles.length; i++) {
context.removeWelcomeFile(welcomeFiles[i]);
}
// Removing wrapper lifecycles
String[] wrapperLifecycles = context.findWrapperLifecycles();
for (i = 0; i < wrapperLifecycles.length; i++) {
context.removeWrapperLifecycle(wrapperLifecycles[i]);
}
// Removing wrapper listeners
String[] wrapperListeners = context.findWrapperListeners();
for (i = 0; i < wrapperListeners.length; i++) {
context.removeWrapperListener(wrapperListeners[i]);
}
ok = true;
}
/**
* Scan the tag library descriptors of all tag libraries we can find, and
* register any application descriptor classes that are found there.
*/
private void tldConfig() {
// Acquire an XmlMapper to use for parsing
XmlMapper mapper = createTldMapper();
// First, scan tag libraries declared in our deployment descriptor
if (debug >= 1)
log("Scanning web.xml tag libraries");
ArrayList resourcePaths = new ArrayList(); // Already processed TLDs
String taglibs[] = context.findTaglibs();
for (int i = 0; i < taglibs.length; i++) {
// Calculate the resource path of the next tag library to check
String resourcePath = context.findTaglib(taglibs[i]);
if (!resourcePath.startsWith("/"))
resourcePath = "/WEB-INF/web.xml/../" + resourcePath;
if (debug >= 2)
log(" URI='" + taglibs[i] + "', ResourcePath='" +
resourcePath + "'");
if (resourcePaths.contains(resourcePath)) {
if (debug >= 2)
log(" Already processed");
continue;
}
resourcePaths.add(resourcePath);
// Process either a JAR file or a TLD at this location
if (!tldConfigJar(resourcePath, mapper))
tldConfigTld(resourcePath, mapper);
}
DirContext resources = context.getResources();
// Second, scan tag libraries defined in tld files in /WEB-INF
if (debug >= 1)
log("Scanning TLD files in /WEB-INF");
String webinfName = "/WEB-INF";
// Looking up directory /WEB-INF in the context
try {
NamingEnumeration enum = resources.list(webinfName);
while (enum.hasMoreElements()) {
NameClassPair ncPair = (NameClassPair) enum.nextElement();
String filename = webinfName + "/" + ncPair.getName();
if (!filename.endsWith(".tld"))
continue;
tldConfigTld(filename, mapper);
}
} catch (NamingException e) {
// Silent catch: it's valid that no /WEB-INF directory exists
}
// Third, scan tag libraries defined in JAR files
if (debug >= 1)
log("Scanning library JAR files");
String libName = "/WEB-INF/lib";
// Looking up directory /WEB-INF/lib in the context
try {
NamingEnumeration enum = resources.list(libName);
while (enum.hasMoreElements()) {
NameClassPair ncPair = (NameClassPair) enum.nextElement();
String filename = libName + "/" + ncPair.getName();
if (!filename.endsWith(".jar"))
continue;
tldConfigJar(filename, mapper);
}
} catch (NamingException e) {
// Silent catch: it's valid that no /WEB-INF/lib directory exists
}
}
/**
* Process a TLD (if there is one) in the JAR file (if there is one) at
* the specified resource path. Return <code>true</code> if we actually
* found and processed such a TLD, or <code>false</code> otherwise.
*
* @param resourcePath Context-relative resource path
* @param mapper XmlMapper to use for parsing
*/
private boolean tldConfigJar(String resourcePath, XmlMapper mapper) {
JarFile jarFile = null;
InputStream stream = null;
try {
URL url = context.getServletContext().getResource(resourcePath);
if (url == null)
return (false);
url = new URL("jar:" + url.toString() + "!/");
JarURLConnection conn =
(JarURLConnection) url.openConnection();
jarFile = conn.getJarFile();
boolean found = false;
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
String name = entry.getName();
if (!name.startsWith("META-INF/"))
continue;
if (!name.endsWith(".tld"))
continue;
if (debug >= 2)
log(" tldConfigJar(" + resourcePath +
"): Processing entry '" + name + "'");
stream = jarFile.getInputStream(entry);
mapper.readXml(stream, context);
stream.close();
found = true;
}
// FIXME jarFile.close();
return (found);
} catch (Exception e) {
if (debug >= 2)
log(" tldConfigJar(" + resourcePath + "): " + e);
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
;
}
}
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable t) {
;
}
}
return (false);
}
}
/**
* Process a TLD (if there is one) at the specified resource path.
* Return <code>true</code> if we actually found and processed such
* a TLD, or <code>false</code> otherwise.
*
* @param resourcePath Context-relative resource path
* @param mapper XmlMapper to use for parsing
*/
private boolean tldConfigTld(String resourcePath, XmlMapper mapper) {
InputStream stream = null;
try {
stream =
context.getServletContext().getResourceAsStream(resourcePath);
if (stream == null)
return (false);
mapper.readXml(stream, context);
stream.close();
return (true);
} catch (Exception e) {
if (debug >= 2)
log(" tldConfigTld(" + resourcePath + "): " + e);
if (stream != null) {
try {
stream.close();
} catch (Throwable t) {
;
}
}
return (false);
}
}
}
// ----------------------------------------------------------- Private Classes
/**
* An XmlAction that calls the <code>setAuthConstraint(true)</code> method of
* the top item on the stack, which must be of type
* <code>org.apache.catalina.deploy.SecurityConstraint</code>.
*/
final class SetAuthConstraint extends XmlAction {
public SetAuthConstraint() {
super();
}
public void start(SaxContext ctx) {
Stack stack = ctx.getObjectStack();
SecurityConstraint securityConstraint =
(SecurityConstraint) stack.peek();
securityConstraint.setAuthConstraint(true);
if (ctx.getDebug() > 0)
ctx.log("Calling SecurityConstraint.setAuthConstraint(true)");
}
}
/**
* Class that calls <code>setDistributable(true)</code> for the top object
* on the stack, which must be a <code>org.apache.catalina.Context</code>.
*/
final class SetDistributableAction extends XmlAction {
public SetDistributableAction() {
super();
}
public void start(SaxContext ctx) throws Exception {
Stack stack = ctx.getObjectStack();
Context context = (Context) stack.peek();
context.setDistributable(true);
if (ctx.getDebug() > 0)
ctx.log(context.getClass().getName() +
".setDistributable( true)");
}
}
/**
* Class that calls a property setter for the top object on the stack,
* passing the public ID of the entity we are currently processing.
*/
final class SetPublicIdAction extends XmlAction {
public SetPublicIdAction(String method) {
super();
this.method = method;
}
private String method = null;
public void start(SaxContext context) throws Exception {
Stack stack = context.getObjectStack();
Object top = stack.peek();
Class paramClasses[] = new Class[1];
paramClasses[0] = "String".getClass();
String paramValues[] = new String[1];
paramValues[0] = context.getPublicId();
Method m = null;
try {
m = top.getClass().getMethod(method, paramClasses);
} catch (NoSuchMethodException e) {
context.log("Can't find method " + method + " in " + top +
" CLASS " + top.getClass());
return;
}
m.invoke(top, paramValues);
if (context.getDebug() >= 1)
context.log("" + top.getClass().getName() + "." + method +
"(" + paramValues[0] + ")");
}
}
/**
* An XmlAction that calls the factory method on the specified context to
* create the object that is to be added to the stack.
*/
final class WrapperCreate extends XmlAction {
private Context context = null;
public WrapperCreate(Context context) {
this.context = context;
}
public void start(SaxContext ctx) {
Stack stack = ctx.getObjectStack();
Wrapper wrapper = context.createWrapper();
stack.push(wrapper);
if (ctx.getDebug() > 0)
ctx.log("new " + wrapper.getClass().getName());
}
public void cleanup(SaxContext ctx) {
Stack stack = ctx.getObjectStack();
Wrapper wrapper = (Wrapper) stack.pop();
if (ctx.getDebug() > 0)
ctx.log("pop " + wrapper.getClass().getName());
}
}