/*
* $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/core/StandardContext.java,v 1.7 2000/02/13 01:43:45 craigmcc Exp $
* $Revision: 1.7 $
* $Date: 2000/02/13 01:43:45 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 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.tomcat.core;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.tomcat.Container;
import org.apache.tomcat.Context;
import org.apache.tomcat.Request;
import org.apache.tomcat.Response;
import org.apache.tomcat.Wrapper;
import org.apache.tomcat.deploy.ContextEjb;
import org.apache.tomcat.deploy.ContextEnvironment;
import org.apache.tomcat.deploy.ContextResource;
import org.apache.tomcat.deploy.LoginConfig;
import org.apache.tomcat.deploy.SecurityConstraint;
/**
* Standard implementation of the <b>Context</b> interface. Each
* child container must be a Wrapper implementation to process the
* requests directed to a particular servlet.
*
* @author Craig R. McClanahan
* @version $Revision: 1.7 $ $Date: 2000/02/13 01:43:45 $
*/
public final class StandardContext
extends ContainerBase
implements Context {
// ----------------------------------------------------------- Constructors
/**
* Create a new StandardContext component with the default basic Valve.
*/
public StandardContext() {
super();
setBasic(new StandardContextValve());
}
// ----------------------------------------------------- Instance Variables
/**
* The security constraints for this web application.
*/
private Vector constraints = new Vector();
/**
* The ServletContext implementation associated with this Context.
*/
private ApplicationContext context = null;
/**
* The distributable flag for this web application.
*/
private boolean distributable = false;
/**
* The EJB resource references for this web application, keyed by name.
*/
private Hashtable ejbs = new Hashtable();
/**
* The environment entries for this web application, keyed by name.
*/
private Hashtable envs = new Hashtable();
/**
* The exception pages for this web application, keyed by fully qualified
* class name of the Java exception.
*/
private Hashtable exceptionPages = new Hashtable();
/**
* The descriptive information string for this implementation.
*/
private static final String info =
"org.apache.tomcat.core.StandardContext/1.0";
/**
* The login configuration descriptor for this web application.
*/
private LoginConfig loginConfig = null;
/**
* The MIME mappings for this web application, keyed by extension.
*/
private Hashtable mimeMappings = new Hashtable();
/**
* The context initialization parameters for this web application,
* keyed by name.
*/
private Hashtable parameters = new Hashtable();
/**
* The resource references for this web application, keyed by name.
*/
private Hashtable resources = new Hashtable();
/**
* The security roles for this application, keyed by role name.
*/
private Hashtable securityRoles = new Hashtable();
/**
* The servlet mappings for this web application, keyed by
* matching pattern.
*/
private Hashtable servletMappings = new Hashtable();
/**
* The session timeout (in minutes) for this web application.
*/
private int sessionTimeout = 30;
/**
* The status code error pages for this web application, keyed by
* HTTP status code (as an Integer).
*/
private Hashtable statusPages = new Hashtable();
/**
* The JSP tag libraries for this web application, keyed by URI
*/
private Hashtable taglibs = new Hashtable();
/**
* The welcome files for this application, keyed by welcome file name.
*/
private Hashtable welcomeFiles = new Hashtable();
// ------------------------------------------------------------- Properties
/**
* Return the distributable flag for this web application.
*/
public boolean getDistributable() {
return (this.distributable);
}
/**
* Set the distributable flag for this web application.
*
* @param distributable The new distributable flag
*/
public void setDistributable(boolean distributable) {
boolean oldDistributable = this.distributable;
this.distributable = distributable;
support.firePropertyChange("distributable",
new Boolean(oldDistributable),
new Boolean(this.distributable));
}
/**
* Return the login configuration descriptor for this web application.
*/
public LoginConfig getLoginConfig() {
return (this.loginConfig);
}
/**
* Set the login configuration descriptor for this web application.
*
* @param config The new login configuration
*/
public void setLoginConfig(LoginConfig config) {
LoginConfig oldLoginConfig = this.loginConfig;
this.loginConfig = config;
support.firePropertyChange("loginConfig",
oldLoginConfig, this.loginConfig);
}
/**
* Return the context path for this Context.
*/
public String getPath() {
return (getName());
}
/**
* Set the context path for this Context.
* <p>
* <b>IMPLEMENTATION NOTE</b>: The context path is used as the "name" of
* a Context, because it must be unique.
*
* @param path The new context path
*/
public void setPath(String path) {
setName(path);
}
/**
* Return the servlet context for which this Context is a facade.
*/
public ServletContext getServletContext() {
if (context == null)
context = new ApplicationContext(this);
return (context);
}
/**
* Return the default session timeout (in minutes) for this
* web application.
*/
public int getSessionTimeout() {
return (this.sessionTimeout);
}
/**
* Set the default session timeout (in minutes) for this
* web application.
*
* @param timeout The new default session timeout
*/
public void setSessionTimeout(int timeout) {
int oldSessionTimeout = this.sessionTimeout;
this.sessionTimeout = timeout;
support.firePropertyChange("sessionTimeout",
new Integer(oldSessionTimeout),
new Integer(this.sessionTimeout));
}
// --------------------------------------------------------- Public Methods
/**
* Add a child Container, only if the proposed child is an implementation
* of Wrapper.
*
* @param child Child container to be added
*/
public void addChild(Container child) {
if (!(child instanceof Wrapper))
throw new IllegalArgumentException
(sm.getString("standardContext.notWrapper"));
super.addChild(child);
}
/**
* Add a security constraint to the set for this web application.
*/
public void addConstraint(SecurityConstraint constraint) {
if (!constraints.contains(constraint)) {
constraints.addElement(constraint);
fireContainerEvent("addConstraint", constraint);
}
}
/**
* Add an EJB resource reference for this web application.
*
* @param ejb New EJB resource reference
*/
public void addEjb(ContextEjb ejb) {
ejbs.put(ejb.getName(), ejb);
fireContainerEvent("addEjb", ejb.getName());
}
/**
* Add an environment entry for this web application.
*
* @param environment New environment entry
*/
public void addEnvironment(ContextEnvironment environment) {
envs.put(environment.getName(), environment);
fireContainerEvent("addEnvironment", environment.getName());
}
/**
* Add an error page for the specified Java exception.
*
* @param exception Fully qualified exception class
* @param location Context-relative URI of the corresponding page
*/
public void addExceptionPage(String exception, String location) {
exceptionPages.put(exception, location);
fireContainerEvent("addExceptionPage", exception);
}
/**
* Add a new MIME mapping, replacing any existing mapping for
* the specified extension.
*
* @param extension Filename extension being mapped
* @param mimeType Corresponding MIME type
*/
public void addMimeMapping(String extension, String mimeType) {
mimeMappings.put(extension, mimeType);
fireContainerEvent("addMimeMapping", extension);
}
/**
* Add a new context initialization parameter, replacing any existing
* value for the specified name.
*
* @param name Name of the new parameter
* @param value Value of the new parameter
*/
public void addParameter(String name, String value) {
parameters.put(name, value);
fireContainerEvent("addParameter", name);
}
/**
* Add a resource reference for this web application.
*
* @param resource New resource reference
*/
public void addResource(ContextResource resource) {
resources.put(resource.getName(), resource);
fireContainerEvent("addResource", resource.getName());
}
/**
* Add a new security role for this web application.
*
* @param role New security role
*/
public void addSecurityRole(String role) {
securityRoles.put(role, role);
fireContainerEvent("addSecurityRole", role);
}
/**
* Add a new servlet mapping, replacing any existing mapping for
* the specified pattern.
*
* @param pattern URL pattern to be mapped
* @param name Name of the corresponding servlet to execute
*/
public void addServletMapping(String pattern, String name) {
servletMappings.put(pattern, name);
fireContainerEvent("addServletMapping", pattern);
}
/**
* Add an error page for the specified HTTP status code.
*
* @param status HTTP status code to be mapped
* @param location Context-relative URI of the corresponding page
*/
public void addStatusPage(int status, String location) {
statusPages.put(new Integer(status), location);
fireContainerEvent("addStatusPage", new Integer(status));
}
/**
* Add a JSP tag library for the specified URI.
*
* @param uri URI, relative to the web.xml file, of this tag library
* @param location Location of the tag library descriptor
*/
public void addTaglib(String uri, String location) {
taglibs.put(uri, location);
fireContainerEvent("addTaglib", uri);
}
/**
* Add a new welcome file to the set recognized by this Context.
*
* @param name New welcome file name
*/
public void addWelcomeFile(String name) {
welcomeFiles.put(name, name);
fireContainerEvent("addWelcomeFile", name);
}
/**
* Factory method to create and return a new Wrapper instance, of
* the Java implementation class appropriate for this Context
* implementation. The constructor of the instantiated Wrapper
* will have been called, but no properties will have been set.
*/
public Wrapper createWrapper() {
return (new StandardWrapper());
}
/**
* Return the security constraints for this web application.
* If there are none, a zero-length array is returned.
*/
public SecurityConstraint[] findConstraints() {
synchronized (constraints) {
SecurityConstraint results[] =
new SecurityConstraint[constraints.size()];
Enumeration elements = constraints.elements();
for (int i = 0; i < results.length; i++)
results[i] = (SecurityConstraint) elements.nextElement();
return (results);
}
}
/**
* Return the EJB resource reference with the specified name, if any;
* otherwise, return <code>null</code>.
*
* @param name Name of the desired EJB resource reference
*/
public ContextEjb findEjb(String name) {
return ((ContextEjb) ejbs.get(name));
}
/**
* Return the defined EJB resource references for this application.
* If there are none, a zero-length array is returned.
*/
public ContextEjb[] findEjbs() {
synchronized (ejbs) {
ContextEjb results[] = new ContextEjb[ejbs.size()];
Enumeration elements = ejbs.elements();
for (int i = 0; i < results.length; i++)
results[i] = (ContextEjb) elements.nextElement();
return (results);
}
}
/**
* Return the environment entry with the specified name, if any;
* otherwise, return <code>null</code>.
*
* @param name Name of the desired environment entry
*/
public ContextEnvironment findEnvironment(String name) {
return ((ContextEnvironment) envs.get(name));
}
/**
* Return the set of defined environment entries for this web
* application. If none have been defined, a zero-length array
* is returned.
*/
public ContextEnvironment[] findEnvironments() {
synchronized (envs) {
ContextEnvironment results[] = new ContextEnvironment[envs.size()];
Enumeration elements = envs.elements();
for (int i = 0; i < results.length; i++)
results[i] = (ContextEnvironment) elements.nextElement();
return (results);
}
}
/**
* Return the context-relative URI of the exception page for the
* specified Java language exception, if any; otherwise return
* <code>null</code>.
*
* @param exception Exception class to look up
*/
public String findExceptionPage(String exception) {
return ((String) exceptionPages.get(exception));
}
/**
* Return the set of Java language exceptions for which error pages
* have been specified. If none are specified, a zero-length array
* is returned.
*/
public String[] findExceptionPages() {
synchronized (exceptionPages) {
String results[] = new String[exceptionPages.size()];
Enumeration elements = exceptionPages.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return the MIME type to which the specified extension is mapped,
* if any; otherwise return <code>null</code>.
*
* @param extension Extension to map to a MIME type
*/
public String findMimeMapping(String extension) {
return ((String) mimeMappings.get(extension));
}
/**
* Return the extensions for which MIME mappings are defined. If there
* are none, a zero-length array is returned.
*/
public String[] findMimeMappings() {
synchronized (mimeMappings) {
String results[] = new String[mimeMappings.size()];
Enumeration elements = mimeMappings.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return the value for the specified context initialization
* parameter name, if any; otherwise return <code>null</code>.
*
* @param name Name of the parameter to return
*/
public String findParameter(String name) {
return ((String) parameters.get(name));
}
/**
* Return the names of all defined context initialization parameters
* for this Context. If no parameters are defined, a zero-length
* array is returned.
*/
public String[] findParameters() {
synchronized (parameters) {
String results[] = new String[parameters.size()];
Enumeration elements = parameters.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return the resource reference with the specified name, if any;
* otherwise return <code>null</code>.
*
* @param name Name of the desired resource reference
*/
public ContextResource findResource(String name) {
return ((ContextResource) resources.get(name));
}
/**
* Return the defined resource references for this application. If
* none have been defined, a zero-length array is returned.
*/
public ContextResource[] findResources() {
synchronized (resources) {
ContextResource results[] = new ContextResource[resources.size()];
Enumeration elements = resources.elements();
for (int i = 0; i < results.length; i++)
results[i] = (ContextResource) elements.nextElement();
return (results);
}
}
/**
* Return <code>true</code> if the specified security role is defined
* for this application; otherwise return <code>false</code>.
*
* @param role Security role to verify
*/
public boolean findSecurityRole(String role) {
return (securityRoles.get(role) != null);
}
/**
* Return the security roles defined for this application. If none
* have been defined, a zero-length array is returned.
*/
public String[] findSecurityRoles() {
synchronized (securityRoles) {
String results[] = new String[securityRoles.size()];
Enumeration elements = resources.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return the servlet name mapped by the specified pattern (if any);
* otherwise return <code>null</code>.
*
* @param pattern Pattern for which a mapping is requested
*/
public String findServletMapping(String pattern) {
return ((String) servletMappings.get(pattern));
}
/**
* Return the patterns of all defined servlet mappings for this
* Context. If no mappings are defined, a zero-length array is returned.
*/
public String[] findServletMappings() {
synchronized (servletMappings) {
String results[] = new String[servletMappings.size()];
Enumeration elements = servletMappings.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return the context-relative URI of the error page for the specified
* HTTP status code, if any; otherwise return <code>null</code>.
*
* @param status HTTP status code to look up
*/
public String findStatusPage(int status) {
return ((String) statusPages.get(new Integer(status)));
}
/**
* Return the set of HTTP status codes for which error pages have
* been specified. If none are specified, a zero-length array
* is returned.
*/
public int[] findStatusPages() {
synchronized (statusPages) {
int results[] = new int[statusPages.size()];
Enumeration elements = statusPages.keys();
for (int i = 0; i < results.length; i++)
results[i] = ((Integer) elements.nextElement()).intValue();
return (results);
}
}
/**
* Return the tag library descriptor location for the specified taglib
* URI, if any; otherwise, return <code>null</code>.
*
* @param uri URI, relative to the web.xml file
*/
public String findTaglib(String uri) {
return ((String) taglibs.get(uri));
}
/**
* Return the URIs of all tag libraries for which a tag library
* descriptor location has been specified. If none are specified,
* a zero-length array is returned.
*/
public String[] findTaglibs() {
synchronized (taglibs) {
String results[] = new String[taglibs.size()];
Enumeration elements = taglibs.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return <code>true</code> if the specified welcome file is defined
* for this Context; otherwise return <code>false</code>.
*
* @param name Welcome file to verify
*/
public boolean findWelcomeFile(String name) {
return (welcomeFiles.get(name) != null);
}
/**
* Return the set of welcome files defined for this Context. If none are
* defined, a zero-length array is returned.
*/
public String[] findWelcomeFiles() {
synchronized (welcomeFiles) {
String results[] = new String[welcomeFiles.size()];
Enumeration elements = welcomeFiles.keys();
for (int i = 0; i < results.length; i++)
results[i] = (String) elements.nextElement();
return (results);
}
}
/**
* Return descriptive information about this Container implementation and
* the corresponding version number, in the format
* <code><description>/<version></code>.
*/
public String getInfo() {
return (info);
}
/**
* Return the Wrapper associated with the servlet that matches the
* specified context-relative URI, if any; otherwise return
* <code>null</code>.
*
* @param uri Context-relative URI, which must start with a "/"
*/
public Wrapper map(String uri) {
return (null); // FIXME - map() via servlet mappings
}
/**
* Remove the specified security constraint from this web application.
*
* @param constraint Constraint to be removed
*/
public void removeConstraint(SecurityConstraint constraint) {
if (constraints.contains(constraint)) {
constraints.removeElement(constraint);
fireContainerEvent("removeConstraint", constraint);
}
}
/**
* Remove any EJB resource reference with the specified name.
*
* @param name Name of the EJB resource reference to remove
*/
public void removeEjb(String name) {
ejbs.remove(name);
fireContainerEvent("removeEjb", name);
}
/**
* Remove any environment entry with the specified name.
*
* @param name Name of the environment entry to remove
*/
public void removeEnvironment(String name) {
envs.remove(name);
fireContainerEvent("removeEnvironment", name);
}
/**
* Remove the error page for the specified Java language exception,
* if it exists; otherwise, no action is taken.
*
* @param exception Java language exception to remove
*/
public void removeExceptionPage(String exception) {
exceptionPages.remove(exception);
fireContainerEvent("removeExceptionPage", exception);
}
/**
* Remove the MIME mapping for the specified extension, if it exists;
* otherwise, no action is taken.
*
* @param extension Extension to remove the mapping for
*/
public void removeMimeMapping(String extension) {
mimeMappings.remove(extension);
fireContainerEvent("removeMimeMapping", extension);
}
/**
* Remove the context initialization parameter with the specified
* name, if it exists; otherwise, no action is taken.
*
* @param name Name of the parameter to remove
*/
public void removeParameter(String name) {
parameters.remove(name);
fireContainerEvent("removeParameter", name);
}
/**
* Remove any resource reference with the specified name.
*
* @param name Name of the resource reference to remove
*/
public void removeResource(String name) {
resources.remove(name);
fireContainerEvent("removeResource", name);
}
/**
* Remove any security role with the specified name.
*
* @param role Security role to remove
*/
public void removeSecurityRole(String role) {
securityRoles.remove(role);
fireContainerEvent("removeSecurityRole", role);
}
/**
* Remove any servlet mapping for the specified pattern, if it exists;
* otherwise, no action is taken.
*
* @param pattern URL pattern of the mapping to remove
*/
public void removeServletMapping(String pattern) {
servletMappings.remove(pattern);
fireContainerEvent("removeServletMapping", pattern);
}
/**
* Remove the error page for the specified HTTP status code, if it
* exists; otherwise, no action is taken.
*
* @param status HTTP status code to remove
*/
public void removeStatusPage(int status) {
statusPages.remove(new Integer(status));
fireContainerEvent("removeStatusPage", new Integer(status));
}
/**
* Remove the tag library location forthe specified tag library URI.
*
* @param uri URI, relative to the web.xml file
*/
public void removeTaglib(String uri) {
taglibs.remove(uri);
fireContainerEvent("removeTaglib", uri);
}
/**
* Remove the specified welcome file name from the list recognized
* by this Context.
*
* @param name Name of the welcome file to be removed
*/
public void removeWelcomeFile(String name) {
welcomeFiles.remove(name);
fireContainerEvent("removeWelcomeFile", name);
}
}