0001: /*
0002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/core/StandardContext.java,v 1.109 2002/06/28 16:09:57 remm Exp $
0003: * $Revision: 1.109 $
0004: * $Date: 2002/06/28 16:09:57 $
0005: *
0006: * ====================================================================
0007: *
0008: * The Apache Software License, Version 1.1
0009: *
0010: * Copyright (c) 1999 The Apache Software Foundation. All rights
0011: * reserved.
0012: *
0013: * Redistribution and use in source and binary forms, with or without
0014: * modification, are permitted provided that the following conditions
0015: * are met:
0016: *
0017: * 1. Redistributions of source code must retain the above copyright
0018: * notice, this list of conditions and the following disclaimer.
0019: *
0020: * 2. Redistributions in binary form must reproduce the above copyright
0021: * notice, this list of conditions and the following disclaimer in
0022: * the documentation and/or other materials provided with the
0023: * distribution.
0024: *
0025: * 3. The end-user documentation included with the redistribution, if
0026: * any, must include the following acknowlegement:
0027: * "This product includes software developed by the
0028: * Apache Software Foundation (http://www.apache.org/)."
0029: * Alternately, this acknowlegement may appear in the software itself,
0030: * if and wherever such third-party acknowlegements normally appear.
0031: *
0032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0033: * Foundation" must not be used to endorse or promote products derived
0034: * from this software without prior written permission. For written
0035: * permission, please contact apache@apache.org.
0036: *
0037: * 5. Products derived from this software may not be called "Apache"
0038: * nor may "Apache" appear in their names without prior written
0039: * permission of the Apache Group.
0040: *
0041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0052: * SUCH DAMAGE.
0053: * ====================================================================
0054: *
0055: * This software consists of voluntary contributions made by many
0056: * individuals on behalf of the Apache Software Foundation. For more
0057: * information on the Apache Software Foundation, please see
0058: * <http://www.apache.org/>.
0059: *
0060: * [Additional notices, if required by prior licensing conditions]
0061: *
0062: */
0063:
0064: package org.apache.catalina.core;
0065:
0066: import java.io.File;
0067: import java.io.IOException;
0068: import java.util.ArrayList;
0069: import java.util.HashMap;
0070: import java.net.URL;
0071: import java.util.Iterator;
0072: import java.util.TreeMap;
0073: import java.util.Hashtable;
0074: import java.util.Stack;
0075: import java.util.Enumeration;
0076: import java.util.StringTokenizer;
0077: import javax.servlet.FilterConfig;
0078: import javax.servlet.ServletContext;
0079: import javax.servlet.ServletContextEvent;
0080: import javax.servlet.ServletContextListener;
0081: import javax.servlet.ServletException;
0082: import javax.servlet.http.HttpServletRequest;
0083: import javax.servlet.http.HttpServletResponse;
0084: import javax.naming.NamingException;
0085: import javax.naming.InitialContext;
0086: import javax.naming.Reference;
0087: import javax.naming.StringRefAddr;
0088: import javax.naming.NamingEnumeration;
0089: import javax.naming.Binding;
0090: import javax.naming.StringRefAddr;
0091: import javax.naming.directory.DirContext;
0092: import org.apache.naming.NamingContext;
0093: import org.apache.naming.ContextBindings;
0094: import org.apache.naming.ContextAccessController;
0095: import org.apache.naming.EjbRef;
0096: import org.apache.naming.ResourceRef;
0097: import org.apache.naming.ResourceEnvRef;
0098: import org.apache.naming.TransactionRef;
0099: import org.apache.naming.resources.BaseDirContext;
0100: import org.apache.naming.resources.FileDirContext;
0101: import org.apache.naming.resources.ProxyDirContext;
0102: import org.apache.naming.resources.WARDirContext;
0103: import org.apache.naming.resources.DirContextURLStreamHandler;
0104: import org.apache.catalina.Container;
0105: import org.apache.catalina.ContainerListener;
0106: import org.apache.catalina.Context;
0107: import org.apache.catalina.Host;
0108: import org.apache.catalina.Globals;
0109: import org.apache.catalina.HttpRequest;
0110: import org.apache.catalina.InstanceListener;
0111: import org.apache.catalina.Lifecycle;
0112: import org.apache.catalina.LifecycleEvent;
0113: import org.apache.catalina.LifecycleException;
0114: import org.apache.catalina.LifecycleListener;
0115: import org.apache.catalina.Loader;
0116: import org.apache.catalina.Mapper;
0117: import org.apache.catalina.Request;
0118: import org.apache.catalina.Response;
0119: import org.apache.catalina.Wrapper;
0120: import org.apache.catalina.deploy.ApplicationParameter;
0121: import org.apache.catalina.deploy.ContextEjb;
0122: import org.apache.catalina.deploy.ContextEnvironment;
0123: import org.apache.catalina.deploy.ContextLocalEjb;
0124: import org.apache.catalina.deploy.ContextResource;
0125: import org.apache.catalina.deploy.ContextResourceLink;
0126: import org.apache.catalina.deploy.ErrorPage;
0127: import org.apache.catalina.deploy.FilterDef;
0128: import org.apache.catalina.deploy.FilterMap;
0129: import org.apache.catalina.deploy.LoginConfig;
0130: import org.apache.catalina.deploy.NamingResources;
0131: import org.apache.catalina.deploy.ResourceParams;
0132: import org.apache.catalina.deploy.SecurityCollection;
0133: import org.apache.catalina.deploy.SecurityConstraint;
0134: import org.apache.catalina.loader.StandardClassLoader;
0135: import org.apache.catalina.loader.WebappLoader;
0136: import org.apache.catalina.session.StandardManager;
0137: import org.apache.catalina.util.CharsetMapper;
0138: import org.apache.catalina.util.RequestUtil;
0139:
0140: /**
0141: * Standard implementation of the <b>Context</b> interface. Each
0142: * child container must be a Wrapper implementation to process the
0143: * requests directed to a particular servlet.
0144: *
0145: * @author Craig R. McClanahan
0146: * @author Remy Maucherat
0147: * @version $Revision: 1.109 $ $Date: 2002/06/28 16:09:57 $
0148: */
0149:
0150: public class StandardContext extends ContainerBase implements Context {
0151:
0152: // ----------------------------------------------------------- Constructors
0153:
0154: /**
0155: * Create a new StandardContext component with the default basic Valve.
0156: */
0157: public StandardContext() {
0158:
0159: super ();
0160: pipeline.setBasic(new StandardContextValve());
0161: namingResources.setContainer(this );
0162:
0163: }
0164:
0165: // ----------------------------------------------------- Instance Variables
0166:
0167: /**
0168: * The set of application listener class names configured for this
0169: * application, in the order they were encountered in the web.xml file.
0170: */
0171: private String applicationListeners[] = new String[0];
0172:
0173: /**
0174: * The set of instantiated application listener objects, in a one-to-one
0175: * correspondence to the class names in <code>applicationListeners</code>.
0176: */
0177: private Object applicationListenersObjects[] = new Object[0];
0178:
0179: /**
0180: * The set of application parameters defined for this application.
0181: */
0182: private ApplicationParameter applicationParameters[] = new ApplicationParameter[0];
0183:
0184: /**
0185: * The application available flag for this Context.
0186: */
0187: private boolean available = false;
0188:
0189: /**
0190: * The Locale to character set mapper for this application.
0191: */
0192: private CharsetMapper charsetMapper = null;
0193:
0194: /**
0195: * The Java class name of the CharsetMapper class to be created.
0196: */
0197: private String charsetMapperClass = "org.apache.catalina.util.CharsetMapper";
0198:
0199: /**
0200: * The "correctly configured" flag for this Context.
0201: */
0202: private boolean configured = false;
0203:
0204: /**
0205: * The security constraints for this web application.
0206: */
0207: private SecurityConstraint constraints[] = new SecurityConstraint[0];
0208:
0209: /**
0210: * The ServletContext implementation associated with this Context.
0211: */
0212: private ApplicationContext context = null;
0213:
0214: /**
0215: * Should we attempt to use cookies for session id communication?
0216: */
0217: private boolean cookies = true;
0218:
0219: /**
0220: * Should we allow the <code>ServletContext.getContext()</code> method
0221: * to access the context of other web applications in this server?
0222: */
0223: private boolean crossContext = false;
0224:
0225: /**
0226: * The display name of this web application.
0227: */
0228: private String displayName = null;
0229:
0230: /**
0231: * The distributable flag for this web application.
0232: */
0233: private boolean distributable = false;
0234:
0235: /**
0236: * The document root for this web application.
0237: */
0238: private String docBase = null;
0239:
0240: /**
0241: * The exception pages for this web application, keyed by fully qualified
0242: * class name of the Java exception.
0243: */
0244: private HashMap exceptionPages = new HashMap();
0245:
0246: /**
0247: * The set of filter configurations (and associated filter instances) we
0248: * have initialized, keyed by filter name.
0249: */
0250: private HashMap filterConfigs = new HashMap();
0251:
0252: /**
0253: * The set of filter definitions for this application, keyed by
0254: * filter name.
0255: */
0256: private HashMap filterDefs = new HashMap();
0257:
0258: /**
0259: * The set of filter mappings for this application, in the order
0260: * they were defined in the deployment descriptor.
0261: */
0262: private FilterMap filterMaps[] = new FilterMap[0];
0263:
0264: /**
0265: * The descriptive information string for this implementation.
0266: */
0267: private static final String info = "org.apache.catalina.core.StandardContext/1.0";
0268:
0269: /**
0270: * The set of classnames of InstanceListeners that will be added
0271: * to each newly created Wrapper by <code>createWrapper()</code>.
0272: */
0273: private String instanceListeners[] = new String[0];
0274:
0275: /**
0276: * The login configuration descriptor for this web application.
0277: */
0278: private LoginConfig loginConfig = null;
0279:
0280: /**
0281: * The naming context listener for this web application.
0282: */
0283: private NamingContextListener namingContextListener = null;
0284:
0285: /**
0286: * The naming resources for this web application.
0287: */
0288: private NamingResources namingResources = new NamingResources();
0289:
0290: /**
0291: * The Java class name of the default Mapper class for this Container.
0292: */
0293: private String mapperClass = "org.apache.catalina.core.StandardContextMapper";
0294:
0295: /**
0296: * The MIME mappings for this web application, keyed by extension.
0297: */
0298: private HashMap mimeMappings = new HashMap();
0299:
0300: /**
0301: * The context initialization parameters for this web application,
0302: * keyed by name.
0303: */
0304: private HashMap parameters = new HashMap();
0305:
0306: /**
0307: * The request processing pause flag (while reloading occurs)
0308: */
0309: private boolean paused = false;
0310:
0311: /**
0312: * The public identifier of the DTD for the web application deployment
0313: * descriptor version we are currently parsing. This is used to support
0314: * relaxed validation rules when processing version 2.2 web.xml files.
0315: */
0316: private String publicId = null;
0317:
0318: /**
0319: * The reloadable flag for this web application.
0320: */
0321: private boolean reloadable = false;
0322:
0323: /**
0324: * The DefaultContext override flag for this web application.
0325: */
0326: private boolean override = false;
0327:
0328: /**
0329: * The privileged flag for this web application.
0330: */
0331: private boolean privileged = false;
0332:
0333: /**
0334: * Should the next call to <code>addWelcomeFile()</code> cause replacement
0335: * of any existing welcome files? This will be set before processing the
0336: * web application's deployment descriptor, so that application specified
0337: * choices <strong>replace</strong>, rather than append to, those defined
0338: * in the global descriptor.
0339: */
0340: private boolean replaceWelcomeFiles = false;
0341:
0342: /**
0343: * The security role mappings for this application, keyed by role
0344: * name (as used within the application).
0345: */
0346: private HashMap roleMappings = new HashMap();
0347:
0348: /**
0349: * The security roles for this application, keyed by role name.
0350: */
0351: private String securityRoles[] = new String[0];
0352:
0353: /**
0354: * The servlet mappings for this web application, keyed by
0355: * matching pattern.
0356: */
0357: private HashMap servletMappings = new HashMap();
0358:
0359: /**
0360: * The session timeout (in minutes) for this web application.
0361: */
0362: private int sessionTimeout = 30;
0363:
0364: /**
0365: * The status code error pages for this web application, keyed by
0366: * HTTP status code (as an Integer).
0367: */
0368: private HashMap statusPages = new HashMap();
0369:
0370: /**
0371: * The JSP tag libraries for this web application, keyed by URI
0372: */
0373: private HashMap taglibs = new HashMap();
0374:
0375: /**
0376: * The welcome files for this application.
0377: */
0378: private String welcomeFiles[] = new String[0];
0379:
0380: /**
0381: * The set of classnames of LifecycleListeners that will be added
0382: * to each newly created Wrapper by <code>createWrapper()</code>.
0383: */
0384: private String wrapperLifecycles[] = new String[0];
0385:
0386: /**
0387: * The set of classnames of ContainerListeners that will be added
0388: * to each newly created Wrapper by <code>createWrapper()</code>.
0389: */
0390: private String wrapperListeners[] = new String[0];
0391:
0392: /**
0393: * The pathname to the work directory for this context (relative to
0394: * the server's home if not absolute).
0395: */
0396: private String workDir = null;
0397:
0398: /**
0399: * Java class name of the Wrapper class implementation we use.
0400: */
0401: private String wrapperClass = "org.apache.catalina.core.StandardWrapper";
0402:
0403: /**
0404: * JNDI use flag.
0405: */
0406: private boolean useNaming = true;
0407:
0408: /**
0409: * Filesystem based flag.
0410: */
0411: private boolean filesystemBased = false;
0412:
0413: /**
0414: * Name of the associated naming context.
0415: */
0416: private String namingContextName = null;
0417:
0418: /**
0419: * Caching allowed flag.
0420: */
0421: protected boolean cachingAllowed = true;
0422:
0423: // ----------------------------------------------------- Context Properties
0424:
0425: /**
0426: * Is caching allowed ?
0427: */
0428: public boolean isCachingAllowed() {
0429: return cachingAllowed;
0430: }
0431:
0432: /**
0433: * Set caching allowed flag.
0434: */
0435: public void setCachingAllowed(boolean cachingAllowed) {
0436: this .cachingAllowed = cachingAllowed;
0437: }
0438:
0439: /**
0440: * Returns true if the internal naming support is used.
0441: */
0442: public boolean isUseNaming() {
0443:
0444: return (useNaming);
0445:
0446: }
0447:
0448: /**
0449: * Enables or disables naming.
0450: */
0451: public void setUseNaming(boolean useNaming) {
0452: this .useNaming = useNaming;
0453: }
0454:
0455: /**
0456: * Returns true if the resources associated with this context are
0457: * filesystem based.
0458: */
0459: public boolean isFilesystemBased() {
0460:
0461: return (filesystemBased);
0462:
0463: }
0464:
0465: /**
0466: * Return the set of initialized application listener objects,
0467: * in the order they were specified in the web application deployment
0468: * descriptor, for this application.
0469: *
0470: * @exception IllegalStateException if this method is called before
0471: * this application has started, or after it has been stopped
0472: */
0473: public Object[] getApplicationListeners() {
0474:
0475: return (applicationListenersObjects);
0476:
0477: }
0478:
0479: /**
0480: * Store the set of initialized application listener objects,
0481: * in the order they were specified in the web application deployment
0482: * descriptor, for this application.
0483: *
0484: * @param listeners The set of instantiated listener objects.
0485: */
0486: public void setApplicationListeners(Object listeners[]) {
0487:
0488: applicationListenersObjects = listeners;
0489:
0490: }
0491:
0492: /**
0493: * Return the application available flag for this Context.
0494: */
0495: public boolean getAvailable() {
0496:
0497: return (this .available);
0498:
0499: }
0500:
0501: /**
0502: * Set the application available flag for this Context.
0503: *
0504: * @param available The new application available flag
0505: */
0506: public void setAvailable(boolean available) {
0507:
0508: boolean oldAvailable = this .available;
0509: this .available = available;
0510: support.firePropertyChange("available", new Boolean(
0511: oldAvailable), new Boolean(this .available));
0512:
0513: }
0514:
0515: /**
0516: * Return the Locale to character set mapper for this Context.
0517: */
0518: public CharsetMapper getCharsetMapper() {
0519:
0520: // Create a mapper the first time it is requested
0521: if (this .charsetMapper == null) {
0522: try {
0523: Class clazz = Class.forName(charsetMapperClass);
0524: this .charsetMapper = (CharsetMapper) clazz
0525: .newInstance();
0526: } catch (Throwable t) {
0527: this .charsetMapper = new CharsetMapper();
0528: }
0529: }
0530:
0531: return (this .charsetMapper);
0532:
0533: }
0534:
0535: /**
0536: * Set the Locale to character set mapper for this Context.
0537: *
0538: * @param mapper The new mapper
0539: */
0540: public void setCharsetMapper(CharsetMapper mapper) {
0541:
0542: CharsetMapper oldCharsetMapper = this .charsetMapper;
0543: this .charsetMapper = mapper;
0544: support.firePropertyChange("charsetMapper", oldCharsetMapper,
0545: this .charsetMapper);
0546:
0547: }
0548:
0549: /**
0550: * Return the "correctly configured" flag for this Context.
0551: */
0552: public boolean getConfigured() {
0553:
0554: return (this .configured);
0555:
0556: }
0557:
0558: /**
0559: * Set the "correctly configured" flag for this Context. This can be
0560: * set to false by startup listeners that detect a fatal configuration
0561: * error to avoid the application from being made available.
0562: *
0563: * @param configured The new correctly configured flag
0564: */
0565: public void setConfigured(boolean configured) {
0566:
0567: boolean oldConfigured = this .configured;
0568: this .configured = configured;
0569: support.firePropertyChange("configured", new Boolean(
0570: oldConfigured), new Boolean(this .configured));
0571:
0572: }
0573:
0574: /**
0575: * Return the "use cookies for session ids" flag.
0576: */
0577: public boolean getCookies() {
0578:
0579: return (this .cookies);
0580:
0581: }
0582:
0583: /**
0584: * Set the "use cookies for session ids" flag.
0585: *
0586: * @param cookies The new flag
0587: */
0588: public void setCookies(boolean cookies) {
0589:
0590: boolean oldCookies = this .cookies;
0591: this .cookies = cookies;
0592: support.firePropertyChange("cookies", new Boolean(oldCookies),
0593: new Boolean(this .cookies));
0594:
0595: }
0596:
0597: /**
0598: * Return the "allow crossing servlet contexts" flag.
0599: */
0600: public boolean getCrossContext() {
0601:
0602: return (this .crossContext);
0603:
0604: }
0605:
0606: /**
0607: * Set the "allow crossing servlet contexts" flag.
0608: *
0609: * @param crossContext The new cross contexts flag
0610: */
0611: public void setCrossContext(boolean crossContext) {
0612:
0613: boolean oldCrossContext = this .crossContext;
0614: this .crossContext = crossContext;
0615: support.firePropertyChange("crossContext", new Boolean(
0616: oldCrossContext), new Boolean(this .crossContext));
0617:
0618: }
0619:
0620: /**
0621: * Return the display name of this web application.
0622: */
0623: public String getDisplayName() {
0624:
0625: return (this .displayName);
0626:
0627: }
0628:
0629: /**
0630: * Set the display name of this web application.
0631: *
0632: * @param displayName The new display name
0633: */
0634: public void setDisplayName(String displayName) {
0635:
0636: String oldDisplayName = this .displayName;
0637: this .displayName = displayName;
0638: support.firePropertyChange("displayName", oldDisplayName,
0639: this .displayName);
0640: }
0641:
0642: /**
0643: * Return the distributable flag for this web application.
0644: */
0645: public boolean getDistributable() {
0646:
0647: return (this .distributable);
0648:
0649: }
0650:
0651: /**
0652: * Set the distributable flag for this web application.
0653: *
0654: * @param distributable The new distributable flag
0655: */
0656: public void setDistributable(boolean distributable) {
0657:
0658: boolean oldDistributable = this .distributable;
0659: this .distributable = distributable;
0660: support.firePropertyChange("distributable", new Boolean(
0661: oldDistributable), new Boolean(this .distributable));
0662:
0663: }
0664:
0665: /**
0666: * Return the document root for this Context. This can be an absolute
0667: * pathname, a relative pathname, or a URL.
0668: */
0669: public String getDocBase() {
0670:
0671: return (this .docBase);
0672:
0673: }
0674:
0675: /**
0676: * Set the document root for this Context. This can be an absolute
0677: * pathname, a relative pathname, or a URL.
0678: *
0679: * @param docBase The new document root
0680: */
0681: public void setDocBase(String docBase) {
0682:
0683: this .docBase = docBase;
0684:
0685: }
0686:
0687: /**
0688: * Return descriptive information about this Container implementation and
0689: * the corresponding version number, in the format
0690: * <code><description>/<version></code>.
0691: */
0692: public String getInfo() {
0693:
0694: return (info);
0695:
0696: }
0697:
0698: /**
0699: * Set the Loader with which this Context is associated.
0700: *
0701: * @param loader The newly associated loader
0702: */
0703: public synchronized void setLoader(Loader loader) {
0704:
0705: super .setLoader(loader);
0706:
0707: }
0708:
0709: /**
0710: * Return the login configuration descriptor for this web application.
0711: */
0712: public LoginConfig getLoginConfig() {
0713:
0714: return (this .loginConfig);
0715:
0716: }
0717:
0718: /**
0719: * Set the login configuration descriptor for this web application.
0720: *
0721: * @param config The new login configuration
0722: */
0723: public void setLoginConfig(LoginConfig config) {
0724:
0725: // Validate the incoming property value
0726: if (config == null)
0727: throw new IllegalArgumentException(sm
0728: .getString("standardContext.loginConfig.required"));
0729: String loginPage = config.getLoginPage();
0730: if ((loginPage != null) && !loginPage.startsWith("/")) {
0731: if (isServlet22()) {
0732: log(sm.getString(
0733: "standardContext.loginConfig.loginWarning",
0734: loginPage));
0735: config.setLoginPage("/" + loginPage);
0736: } else {
0737: throw new IllegalArgumentException(sm.getString(
0738: "standardContext.loginConfig.loginPage",
0739: loginPage));
0740: }
0741: }
0742: String errorPage = config.getErrorPage();
0743: if ((errorPage != null) && !errorPage.startsWith("/")) {
0744: if (isServlet22()) {
0745: log(sm.getString(
0746: "standardContext.loginConfig.errorWarning",
0747: errorPage));
0748: config.setErrorPage("/" + errorPage);
0749: } else {
0750: throw new IllegalArgumentException(sm.getString(
0751: "standardContext.loginConfig.errorPage",
0752: errorPage));
0753: }
0754: }
0755:
0756: // Process the property setting change
0757: LoginConfig oldLoginConfig = this .loginConfig;
0758: this .loginConfig = config;
0759: support.firePropertyChange("loginConfig", oldLoginConfig,
0760: this .loginConfig);
0761:
0762: }
0763:
0764: /**
0765: * Return the naming resources associated with this web application.
0766: */
0767: public NamingResources getNamingResources() {
0768:
0769: return (this .namingResources);
0770:
0771: }
0772:
0773: /**
0774: * Set the naming resources for this web application.
0775: *
0776: * @param namingResources The new naming resources
0777: */
0778: public void setNamingResources(NamingResources namingResources) {
0779:
0780: // Process the property setting change
0781: NamingResources oldNamingResources = this .namingResources;
0782: this .namingResources = namingResources;
0783: support.firePropertyChange("namingResources",
0784: oldNamingResources, this .namingResources);
0785:
0786: }
0787:
0788: /**
0789: * Return the context path for this Context.
0790: */
0791: public String getPath() {
0792:
0793: return (getName());
0794:
0795: }
0796:
0797: /**
0798: * Set the context path for this Context.
0799: * <p>
0800: * <b>IMPLEMENTATION NOTE</b>: The context path is used as the "name" of
0801: * a Context, because it must be unique.
0802: *
0803: * @param path The new context path
0804: */
0805: public void setPath(String path) {
0806:
0807: setName(RequestUtil.URLDecode(path));
0808:
0809: }
0810:
0811: /**
0812: * Return the public identifier of the deployment descriptor DTD that is
0813: * currently being parsed.
0814: */
0815: public String getPublicId() {
0816:
0817: return (this .publicId);
0818:
0819: }
0820:
0821: /**
0822: * Set the public identifier of the deployment descriptor DTD that is
0823: * currently being parsed.
0824: *
0825: * @param publicId The public identifier
0826: */
0827: public void setPublicId(String publicId) {
0828:
0829: if (debug >= 1)
0830: log("Setting deployment descriptor public ID to '"
0831: + publicId + "'");
0832:
0833: String oldPublicId = this .publicId;
0834: this .publicId = publicId;
0835: support.firePropertyChange("publicId", oldPublicId, publicId);
0836:
0837: }
0838:
0839: /**
0840: * Return the reloadable flag for this web application.
0841: */
0842: public boolean getReloadable() {
0843:
0844: return (this .reloadable);
0845:
0846: }
0847:
0848: /**
0849: * Return the DefaultContext override flag for this web application.
0850: */
0851: public boolean getOverride() {
0852:
0853: return (this .override);
0854:
0855: }
0856:
0857: /**
0858: * Return the privileged flag for this web application.
0859: */
0860: public boolean getPrivileged() {
0861:
0862: return (this .privileged);
0863:
0864: }
0865:
0866: /**
0867: * Set the privileged flag for this web application.
0868: *
0869: * @param privileged The new privileged flag
0870: */
0871: public void setPrivileged(boolean privileged) {
0872:
0873: boolean oldPrivileged = this .privileged;
0874: this .privileged = privileged;
0875: support.firePropertyChange("privileged", new Boolean(
0876: oldPrivileged), new Boolean(this .privileged));
0877:
0878: }
0879:
0880: /**
0881: * Set the reloadable flag for this web application.
0882: *
0883: * @param reloadable The new reloadable flag
0884: */
0885: public void setReloadable(boolean reloadable) {
0886:
0887: boolean oldReloadable = this .reloadable;
0888: this .reloadable = reloadable;
0889: support.firePropertyChange("reloadable", new Boolean(
0890: oldReloadable), new Boolean(this .reloadable));
0891:
0892: }
0893:
0894: /**
0895: * Set the DefaultContext override flag for this web application.
0896: *
0897: * @param override The new override flag
0898: */
0899: public void setOverride(boolean override) {
0900:
0901: boolean oldOverride = this .override;
0902: this .override = override;
0903: support.firePropertyChange("override",
0904: new Boolean(oldOverride), new Boolean(this .override));
0905:
0906: }
0907:
0908: /**
0909: * Return the "replace welcome files" property.
0910: */
0911: public boolean isReplaceWelcomeFiles() {
0912:
0913: return (this .replaceWelcomeFiles);
0914:
0915: }
0916:
0917: /**
0918: * Set the "replace welcome files" property.
0919: *
0920: * @param replaceWelcomeFiles The new property value
0921: */
0922: public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
0923:
0924: boolean oldReplaceWelcomeFiles = this .replaceWelcomeFiles;
0925: this .replaceWelcomeFiles = replaceWelcomeFiles;
0926: support.firePropertyChange("replaceWelcomeFiles", new Boolean(
0927: oldReplaceWelcomeFiles), new Boolean(
0928: this .replaceWelcomeFiles));
0929:
0930: }
0931:
0932: /**
0933: * Return the servlet context for which this Context is a facade.
0934: */
0935: public ServletContext getServletContext() {
0936:
0937: if (context == null)
0938: context = new ApplicationContext(getBasePath(), this );
0939: return (context);
0940:
0941: }
0942:
0943: /**
0944: * Return the default session timeout (in minutes) for this
0945: * web application.
0946: */
0947: public int getSessionTimeout() {
0948:
0949: return (this .sessionTimeout);
0950:
0951: }
0952:
0953: /**
0954: * Set the default session timeout (in minutes) for this
0955: * web application.
0956: *
0957: * @param timeout The new default session timeout
0958: */
0959: public void setSessionTimeout(int timeout) {
0960:
0961: int oldSessionTimeout = this .sessionTimeout;
0962: this .sessionTimeout = timeout;
0963: support.firePropertyChange("sessionTimeout", new Integer(
0964: oldSessionTimeout), new Integer(this .sessionTimeout));
0965:
0966: }
0967:
0968: /**
0969: * Return the Java class name of the Wrapper implementation used
0970: * for servlets registered in this Context.
0971: */
0972: public String getWrapperClass() {
0973:
0974: return (this .wrapperClass);
0975:
0976: }
0977:
0978: /**
0979: * Set the Java class name of the Wrapper implementation used
0980: * for servlets registered in this Context.
0981: *
0982: * @param wrapperClass The new wrapper class
0983: */
0984: public void setWrapperClass(String wrapperClass) {
0985:
0986: this .wrapperClass = wrapperClass;
0987:
0988: }
0989:
0990: /**
0991: * Set the resources DirContext object with which this Container is
0992: * associated.
0993: *
0994: * @param resources The newly associated DirContext
0995: */
0996: public synchronized void setResources(DirContext resources) {
0997:
0998: if (resources instanceof BaseDirContext) {
0999: ((BaseDirContext) resources).setDocBase(getBasePath());
1000: ((BaseDirContext) resources).setCached(isCachingAllowed());
1001: }
1002: if (resources instanceof FileDirContext) {
1003: filesystemBased = true;
1004: }
1005: super .setResources(resources);
1006: if (started)
1007: postResources(); // As a servlet context attribute
1008:
1009: }
1010:
1011: // ------------------------------------------------------ Public Properties
1012:
1013: /**
1014: * Return the Locale to character set mapper class for this Context.
1015: */
1016: public String getCharsetMapperClass() {
1017:
1018: return (this .charsetMapperClass);
1019:
1020: }
1021:
1022: /**
1023: * Set the Locale to character set mapper class for this Context.
1024: *
1025: * @param mapper The new mapper class
1026: */
1027: public void setCharsetMapperClass(String mapper) {
1028:
1029: String oldCharsetMapperClass = this .charsetMapperClass;
1030: this .charsetMapperClass = mapper;
1031: support.firePropertyChange("charsetMapperClass",
1032: oldCharsetMapperClass, this .charsetMapperClass);
1033:
1034: }
1035:
1036: /**
1037: * Return the default Mapper class name.
1038: */
1039: public String getMapperClass() {
1040:
1041: return (this .mapperClass);
1042:
1043: }
1044:
1045: /**
1046: * Set the default Mapper class name.
1047: *
1048: * @param mapperClass The new default Mapper class name
1049: */
1050: public void setMapperClass(String mapperClass) {
1051:
1052: String oldMapperClass = this .mapperClass;
1053: this .mapperClass = mapperClass;
1054: support.firePropertyChange("mapperClass", oldMapperClass,
1055: this .mapperClass);
1056:
1057: }
1058:
1059: /**
1060: * Return the work directory for this Context.
1061: */
1062: public String getWorkDir() {
1063:
1064: return (this .workDir);
1065:
1066: }
1067:
1068: /**
1069: * Set the work directory for this Context.
1070: *
1071: * @param workDir The new work directory
1072: */
1073: public void setWorkDir(String workDir) {
1074:
1075: this .workDir = workDir;
1076:
1077: if (started)
1078: postWorkDirectory();
1079:
1080: }
1081:
1082: // -------------------------------------------------------- Context Methods
1083:
1084: /**
1085: * Add a new Listener class name to the set of Listeners
1086: * configured for this application.
1087: *
1088: * @param listener Java class name of a listener class
1089: */
1090: public void addApplicationListener(String listener) {
1091:
1092: synchronized (applicationListeners) {
1093: String results[] = new String[applicationListeners.length + 1];
1094: for (int i = 0; i < applicationListeners.length; i++) {
1095: if (listener.equals(applicationListeners[i]))
1096: return;
1097: results[i] = applicationListeners[i];
1098: }
1099: results[applicationListeners.length] = listener;
1100: applicationListeners = results;
1101: }
1102: fireContainerEvent("addApplicationListener", listener);
1103:
1104: // FIXME - add instance if already started?
1105:
1106: }
1107:
1108: /**
1109: * Add a new application parameter for this application.
1110: *
1111: * @param parameter The new application parameter
1112: */
1113: public void addApplicationParameter(ApplicationParameter parameter) {
1114:
1115: synchronized (applicationParameters) {
1116: String newName = parameter.getName();
1117: for (int i = 0; i < applicationParameters.length; i++) {
1118: if (name.equals(applicationParameters[i].getName())
1119: && !applicationParameters[i].getOverride())
1120: return;
1121: }
1122: ApplicationParameter results[] = new ApplicationParameter[applicationParameters.length + 1];
1123: System.arraycopy(applicationParameters, 0, results, 0,
1124: applicationParameters.length);
1125: results[applicationParameters.length] = parameter;
1126: applicationParameters = results;
1127: }
1128: fireContainerEvent("addApplicationParameter", parameter);
1129:
1130: }
1131:
1132: /**
1133: * Add a child Container, only if the proposed child is an implementation
1134: * of Wrapper.
1135: *
1136: * @param child Child container to be added
1137: *
1138: * @exception IllegalArgumentException if the proposed container is
1139: * not an implementation of Wrapper
1140: */
1141: public void addChild(Container child) {
1142:
1143: if (!(child instanceof Wrapper))
1144: throw new IllegalArgumentException(sm
1145: .getString("standardContext.notWrapper"));
1146: Wrapper wrapper = (Wrapper) child;
1147: String jspFile = wrapper.getJspFile();
1148: if ((jspFile != null) && !jspFile.startsWith("/")) {
1149: if (isServlet22()) {
1150: log(sm.getString("standardContext.wrapper.warning",
1151: jspFile));
1152: wrapper.setJspFile("/" + jspFile);
1153: } else {
1154: throw new IllegalArgumentException(sm.getString(
1155: "standardContext.wrapper.error", jspFile));
1156: }
1157: }
1158:
1159: super .addChild(child);
1160:
1161: }
1162:
1163: /**
1164: * Add a security constraint to the set for this web application.
1165: */
1166: public void addConstraint(SecurityConstraint constraint) {
1167:
1168: // Validate the proposed constraint
1169: SecurityCollection collections[] = constraint.findCollections();
1170: for (int i = 0; i < collections.length; i++) {
1171: String patterns[] = collections[i].findPatterns();
1172: for (int j = 0; j < patterns.length; j++) {
1173: patterns[j] = adjustURLPattern(patterns[j]);
1174: if (!validateURLPattern(patterns[j]))
1175: throw new IllegalArgumentException(
1176: sm
1177: .getString(
1178: "standardContext.securityConstraint.pattern",
1179: patterns[j]));
1180: }
1181: }
1182:
1183: // Add this constraint to the set for our web application
1184: synchronized (constraints) {
1185: SecurityConstraint results[] = new SecurityConstraint[constraints.length + 1];
1186: for (int i = 0; i < constraints.length; i++)
1187: results[i] = constraints[i];
1188: results[constraints.length] = constraint;
1189: constraints = results;
1190: }
1191:
1192: }
1193:
1194: /**
1195: * Add an EJB resource reference for this web application.
1196: *
1197: * @param ejb New EJB resource reference
1198: */
1199: public void addEjb(ContextEjb ejb) {
1200:
1201: namingResources.addEjb(ejb);
1202: fireContainerEvent("addEjb", ejb.getName());
1203:
1204: }
1205:
1206: /**
1207: * Add an environment entry for this web application.
1208: *
1209: * @param environment New environment entry
1210: */
1211: public void addEnvironment(ContextEnvironment environment) {
1212:
1213: ContextEnvironment env = findEnvironment(environment.getName());
1214: if ((env != null) && !env.getOverride())
1215: return;
1216: namingResources.addEnvironment(environment);
1217: fireContainerEvent("addEnvironment", environment.getName());
1218:
1219: }
1220:
1221: /**
1222: * Add resource parameters for this web application.
1223: *
1224: * @param resourceParameters New resource parameters
1225: */
1226: public void addResourceParams(ResourceParams resourceParameters) {
1227:
1228: namingResources.addResourceParams(resourceParameters);
1229: fireContainerEvent("addResourceParams", resourceParameters
1230: .getName());
1231:
1232: }
1233:
1234: /**
1235: * Add an error page for the specified error or Java exception.
1236: *
1237: * @param errorPage The error page definition to be added
1238: */
1239: public void addErrorPage(ErrorPage errorPage) {
1240:
1241: // Validate the input parameters
1242: if (errorPage == null)
1243: throw new IllegalArgumentException(sm
1244: .getString("standardContext.errorPage.required"));
1245: String location = errorPage.getLocation();
1246: if ((location != null) && !location.startsWith("/")) {
1247: if (isServlet22()) {
1248: log(sm.getString("standardContext.errorPage.warning",
1249: location));
1250: errorPage.setLocation("/" + location);
1251: } else {
1252: throw new IllegalArgumentException(sm.getString(
1253: "standardContext.errorPage.error", location));
1254: }
1255: }
1256:
1257: // Add the specified error page to our internal collections
1258: String exceptionType = errorPage.getExceptionType();
1259: if (exceptionType != null) {
1260: synchronized (exceptionPages) {
1261: exceptionPages.put(exceptionType, errorPage);
1262: }
1263: } else {
1264: synchronized (statusPages) {
1265: statusPages.put(new Integer(errorPage.getErrorCode()),
1266: errorPage);
1267: }
1268: }
1269: fireContainerEvent("addErrorPage", errorPage);
1270:
1271: }
1272:
1273: /**
1274: * Add a filter definition to this Context.
1275: *
1276: * @param filterDef The filter definition to be added
1277: */
1278: public void addFilterDef(FilterDef filterDef) {
1279:
1280: synchronized (filterDefs) {
1281: filterDefs.put(filterDef.getFilterName(), filterDef);
1282: }
1283: fireContainerEvent("addFilterDef", filterDef);
1284:
1285: }
1286:
1287: /**
1288: * Add a filter mapping to this Context.
1289: *
1290: * @param filterMap The filter mapping to be added
1291: *
1292: * @exception IllegalArgumentException if the specified filter name
1293: * does not match an existing filter definition, or the filter mapping
1294: * is malformed
1295: */
1296: public void addFilterMap(FilterMap filterMap) {
1297:
1298: // Validate the proposed filter mapping
1299: String filterName = filterMap.getFilterName();
1300: String servletName = filterMap.getServletName();
1301: String urlPattern = filterMap.getURLPattern();
1302: if (findFilterDef(filterName) == null)
1303: throw new IllegalArgumentException(sm.getString(
1304: "standardContext.filterMap.name", filterName));
1305: if ((servletName == null) && (urlPattern == null))
1306: throw new IllegalArgumentException(sm
1307: .getString("standardContext.filterMap.either"));
1308: if ((servletName != null) && (urlPattern != null))
1309: throw new IllegalArgumentException(sm
1310: .getString("standardContext.filterMap.either"));
1311: // Because filter-pattern is new in 2.3, no need to adjust
1312: // for 2.2 backwards compatibility
1313: if ((urlPattern != null) && !validateURLPattern(urlPattern))
1314: throw new IllegalArgumentException(sm.getString(
1315: "standardContext.filterMap.pattern", urlPattern));
1316:
1317: // Add this filter mapping to our registered set
1318: synchronized (filterMaps) {
1319: FilterMap results[] = new FilterMap[filterMaps.length + 1];
1320: System.arraycopy(filterMaps, 0, results, 0,
1321: filterMaps.length);
1322: results[filterMaps.length] = filterMap;
1323: filterMaps = results;
1324: }
1325: fireContainerEvent("addFilterMap", filterMap);
1326:
1327: }
1328:
1329: /**
1330: * Add the classname of an InstanceListener to be added to each
1331: * Wrapper appended to this Context.
1332: *
1333: * @param listener Java class name of an InstanceListener class
1334: */
1335: public void addInstanceListener(String listener) {
1336:
1337: synchronized (instanceListeners) {
1338: String results[] = new String[instanceListeners.length + 1];
1339: for (int i = 0; i < instanceListeners.length; i++)
1340: results[i] = instanceListeners[i];
1341: results[instanceListeners.length] = listener;
1342: instanceListeners = results;
1343: }
1344: fireContainerEvent("addInstanceListener", listener);
1345:
1346: }
1347:
1348: /**
1349: * Add a local EJB resource reference for this web application.
1350: *
1351: * @param ejb New EJB resource reference
1352: */
1353: public void addLocalEjb(ContextLocalEjb ejb) {
1354:
1355: namingResources.addLocalEjb(ejb);
1356: fireContainerEvent("addLocalEjb", ejb.getName());
1357:
1358: }
1359:
1360: /**
1361: * Add a new MIME mapping, replacing any existing mapping for
1362: * the specified extension.
1363: *
1364: * @param extension Filename extension being mapped
1365: * @param mimeType Corresponding MIME type
1366: */
1367: public void addMimeMapping(String extension, String mimeType) {
1368:
1369: synchronized (mimeMappings) {
1370: mimeMappings.put(extension, mimeType);
1371: }
1372: fireContainerEvent("addMimeMapping", extension);
1373:
1374: }
1375:
1376: /**
1377: * Add a new context initialization parameter.
1378: *
1379: * @param name Name of the new parameter
1380: * @param value Value of the new parameter
1381: *
1382: * @exception IllegalArgumentException if the name or value is missing,
1383: * or if this context initialization parameter has already been
1384: * registered
1385: */
1386: public void addParameter(String name, String value) {
1387:
1388: // Validate the proposed context initialization parameter
1389: if ((name == null) || (value == null))
1390: throw new IllegalArgumentException(sm
1391: .getString("standardContext.parameter.required"));
1392: if (parameters.get(name) != null)
1393: throw new IllegalArgumentException(sm.getString(
1394: "standardContext.parameter.duplicate", name));
1395:
1396: // Add this parameter to our defined set
1397: synchronized (parameters) {
1398: parameters.put(name, value);
1399: }
1400: fireContainerEvent("addParameter", name);
1401:
1402: }
1403:
1404: /**
1405: * Add a resource reference for this web application.
1406: *
1407: * @param resource New resource reference
1408: */
1409: public void addResource(ContextResource resource) {
1410:
1411: namingResources.addResource(resource);
1412: fireContainerEvent("addResource", resource.getName());
1413:
1414: }
1415:
1416: /**
1417: * Add a resource environment reference for this web application.
1418: *
1419: * @param name The resource environment reference name
1420: * @param type The resource environment reference type
1421: */
1422: public void addResourceEnvRef(String name, String type) {
1423:
1424: namingResources.addResourceEnvRef(name, type);
1425: fireContainerEvent("addResourceEnvRef", name);
1426:
1427: }
1428:
1429: /**
1430: * Add a resource link for this web application.
1431: *
1432: * @param resourceLink New resource link
1433: */
1434: public void addResourceLink(ContextResourceLink resourceLink) {
1435:
1436: namingResources.addResourceLink(resourceLink);
1437: fireContainerEvent("addResourceLink", resourceLink.getName());
1438:
1439: }
1440:
1441: /**
1442: * Add a security role reference for this web application.
1443: *
1444: * @param role Security role used in the application
1445: * @param link Actual security role to check for
1446: */
1447: public void addRoleMapping(String role, String link) {
1448:
1449: synchronized (roleMappings) {
1450: roleMappings.put(role, link);
1451: }
1452: fireContainerEvent("addRoleMapping", role);
1453:
1454: }
1455:
1456: /**
1457: * Add a new security role for this web application.
1458: *
1459: * @param role New security role
1460: */
1461: public void addSecurityRole(String role) {
1462:
1463: synchronized (securityRoles) {
1464: String results[] = new String[securityRoles.length + 1];
1465: for (int i = 0; i < securityRoles.length; i++)
1466: results[i] = securityRoles[i];
1467: results[securityRoles.length] = role;
1468: securityRoles = results;
1469: }
1470: fireContainerEvent("addSecurityRole", role);
1471:
1472: }
1473:
1474: /**
1475: * Add a new servlet mapping, replacing any existing mapping for
1476: * the specified pattern.
1477: *
1478: * @param pattern URL pattern to be mapped
1479: * @param name Name of the corresponding servlet to execute
1480: *
1481: * @exception IllegalArgumentException if the specified servlet name
1482: * is not known to this Context
1483: */
1484: public void addServletMapping(String pattern, String name) {
1485:
1486: // Validate the proposed mapping
1487: if (findChild(name) == null)
1488: throw new IllegalArgumentException(sm.getString(
1489: "standardContext.servletMap.name", name));
1490: pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
1491: if (!validateURLPattern(pattern))
1492: throw new IllegalArgumentException(sm.getString(
1493: "standardContext.servletMap.pattern", pattern));
1494:
1495: // Add this mapping to our registered set
1496: synchronized (servletMappings) {
1497: servletMappings.put(pattern, name);
1498: }
1499: fireContainerEvent("addServletMapping", pattern);
1500:
1501: }
1502:
1503: /**
1504: * Add a JSP tag library for the specified URI.
1505: *
1506: * @param uri URI, relative to the web.xml file, of this tag library
1507: * @param location Location of the tag library descriptor
1508: */
1509: public void addTaglib(String uri, String location) {
1510:
1511: synchronized (taglibs) {
1512: taglibs.put(uri, location);
1513: }
1514: fireContainerEvent("addTaglib", uri);
1515:
1516: }
1517:
1518: /**
1519: * Add a new welcome file to the set recognized by this Context.
1520: *
1521: * @param name New welcome file name
1522: */
1523: public void addWelcomeFile(String name) {
1524:
1525: synchronized (welcomeFiles) {
1526: // Welcome files from the application deployment descriptor
1527: // completely replace those from the default conf/web.xml file
1528: if (replaceWelcomeFiles) {
1529: welcomeFiles = new String[0];
1530: setReplaceWelcomeFiles(false);
1531: }
1532: String results[] = new String[welcomeFiles.length + 1];
1533: for (int i = 0; i < welcomeFiles.length; i++)
1534: results[i] = welcomeFiles[i];
1535: results[welcomeFiles.length] = name;
1536: welcomeFiles = results;
1537: }
1538: postWelcomeFiles();
1539: fireContainerEvent("addWelcomeFile", name);
1540:
1541: }
1542:
1543: /**
1544: * Add the classname of a LifecycleListener to be added to each
1545: * Wrapper appended to this Context.
1546: *
1547: * @param listener Java class name of a LifecycleListener class
1548: */
1549: public void addWrapperLifecycle(String listener) {
1550:
1551: synchronized (wrapperLifecycles) {
1552: String results[] = new String[wrapperLifecycles.length + 1];
1553: for (int i = 0; i < wrapperLifecycles.length; i++)
1554: results[i] = wrapperLifecycles[i];
1555: results[wrapperLifecycles.length] = listener;
1556: wrapperLifecycles = results;
1557: }
1558: fireContainerEvent("addWrapperLifecycle", listener);
1559:
1560: }
1561:
1562: /**
1563: * Add the classname of a ContainerListener to be added to each
1564: * Wrapper appended to this Context.
1565: *
1566: * @param listener Java class name of a ContainerListener class
1567: */
1568: public void addWrapperListener(String listener) {
1569:
1570: synchronized (wrapperListeners) {
1571: String results[] = new String[wrapperListeners.length + 1];
1572: for (int i = 0; i < wrapperListeners.length; i++)
1573: results[i] = wrapperListeners[i];
1574: results[wrapperListeners.length] = listener;
1575: wrapperListeners = results;
1576: }
1577: fireContainerEvent("addWrapperListener", listener);
1578:
1579: }
1580:
1581: /**
1582: * Factory method to create and return a new Wrapper instance, of
1583: * the Java implementation class appropriate for this Context
1584: * implementation. The constructor of the instantiated Wrapper
1585: * will have been called, but no properties will have been set.
1586: */
1587: public Wrapper createWrapper() {
1588:
1589: Wrapper wrapper = new StandardWrapper();
1590:
1591: synchronized (instanceListeners) {
1592: for (int i = 0; i < instanceListeners.length; i++) {
1593: try {
1594: Class clazz = Class.forName(instanceListeners[i]);
1595: InstanceListener listener = (InstanceListener) clazz
1596: .newInstance();
1597: wrapper.addInstanceListener(listener);
1598: } catch (Throwable t) {
1599: log("createWrapper", t);
1600: return (null);
1601: }
1602: }
1603: }
1604:
1605: synchronized (wrapperLifecycles) {
1606: for (int i = 0; i < wrapperLifecycles.length; i++) {
1607: try {
1608: Class clazz = Class.forName(wrapperLifecycles[i]);
1609: LifecycleListener listener = (LifecycleListener) clazz
1610: .newInstance();
1611: if (wrapper instanceof Lifecycle)
1612: ((Lifecycle) wrapper)
1613: .addLifecycleListener(listener);
1614: } catch (Throwable t) {
1615: log("createWrapper", t);
1616: return (null);
1617: }
1618: }
1619: }
1620:
1621: synchronized (wrapperListeners) {
1622: for (int i = 0; i < wrapperListeners.length; i++) {
1623: try {
1624: Class clazz = Class.forName(wrapperListeners[i]);
1625: ContainerListener listener = (ContainerListener) clazz
1626: .newInstance();
1627: wrapper.addContainerListener(listener);
1628: } catch (Throwable t) {
1629: log("createWrapper", t);
1630: return (null);
1631: }
1632: }
1633: }
1634:
1635: return (wrapper);
1636:
1637: }
1638:
1639: /**
1640: * Return the set of application listener class names configured
1641: * for this application.
1642: */
1643: public String[] findApplicationListeners() {
1644:
1645: return (applicationListeners);
1646:
1647: }
1648:
1649: /**
1650: * Return the set of application parameters for this application.
1651: */
1652: public ApplicationParameter[] findApplicationParameters() {
1653:
1654: return (applicationParameters);
1655:
1656: }
1657:
1658: /**
1659: * Return the security constraints for this web application.
1660: * If there are none, a zero-length array is returned.
1661: */
1662: public SecurityConstraint[] findConstraints() {
1663:
1664: return (constraints);
1665:
1666: }
1667:
1668: /**
1669: * Return the EJB resource reference with the specified name, if any;
1670: * otherwise, return <code>null</code>.
1671: *
1672: * @param name Name of the desired EJB resource reference
1673: */
1674: public ContextEjb findEjb(String name) {
1675:
1676: return namingResources.findEjb(name);
1677:
1678: }
1679:
1680: /**
1681: * Return the defined EJB resource references for this application.
1682: * If there are none, a zero-length array is returned.
1683: */
1684: public ContextEjb[] findEjbs() {
1685:
1686: return namingResources.findEjbs();
1687:
1688: }
1689:
1690: /**
1691: * Return the environment entry with the specified name, if any;
1692: * otherwise, return <code>null</code>.
1693: *
1694: * @param name Name of the desired environment entry
1695: */
1696: public ContextEnvironment findEnvironment(String name) {
1697:
1698: return namingResources.findEnvironment(name);
1699:
1700: }
1701:
1702: /**
1703: * Return the set of defined environment entries for this web
1704: * application. If none have been defined, a zero-length array
1705: * is returned.
1706: */
1707: public ContextEnvironment[] findEnvironments() {
1708:
1709: return namingResources.findEnvironments();
1710:
1711: }
1712:
1713: /**
1714: * Return the error page entry for the specified HTTP error code,
1715: * if any; otherwise return <code>null</code>.
1716: *
1717: * @param errorCode Error code to look up
1718: */
1719: public ErrorPage findErrorPage(int errorCode) {
1720:
1721: return ((ErrorPage) statusPages.get(new Integer(errorCode)));
1722:
1723: }
1724:
1725: /**
1726: * Return the error page entry for the specified Java exception type,
1727: * if any; otherwise return <code>null</code>.
1728: *
1729: * @param exceptionType Exception type to look up
1730: */
1731: public ErrorPage findErrorPage(String exceptionType) {
1732:
1733: synchronized (exceptionPages) {
1734: return ((ErrorPage) exceptionPages.get(exceptionType));
1735: }
1736:
1737: }
1738:
1739: /**
1740: * Return the set of defined error pages for all specified error codes
1741: * and exception types.
1742: */
1743: public ErrorPage[] findErrorPages() {
1744:
1745: synchronized (exceptionPages) {
1746: synchronized (statusPages) {
1747: ErrorPage results1[] = new ErrorPage[exceptionPages
1748: .size()];
1749: results1 = (ErrorPage[]) exceptionPages.values()
1750: .toArray(results1);
1751: ErrorPage results2[] = new ErrorPage[statusPages.size()];
1752: results2 = (ErrorPage[]) statusPages.values().toArray(
1753: results2);
1754: ErrorPage results[] = new ErrorPage[results1.length
1755: + results2.length];
1756: for (int i = 0; i < results1.length; i++)
1757: results[i] = results1[i];
1758: for (int i = results1.length; i < results.length; i++)
1759: results[i] = results2[i - results1.length];
1760: return (results);
1761: }
1762: }
1763:
1764: }
1765:
1766: /**
1767: * Return the filter definition for the specified filter name, if any;
1768: * otherwise return <code>null</code>.
1769: *
1770: * @param filterName Filter name to look up
1771: */
1772: public FilterDef findFilterDef(String filterName) {
1773:
1774: synchronized (filterDefs) {
1775: return ((FilterDef) filterDefs.get(filterName));
1776: }
1777:
1778: }
1779:
1780: /**
1781: * Return the set of defined filters for this Context.
1782: */
1783: public FilterDef[] findFilterDefs() {
1784:
1785: synchronized (filterDefs) {
1786: FilterDef results[] = new FilterDef[filterDefs.size()];
1787: return ((FilterDef[]) filterDefs.values().toArray(results));
1788: }
1789:
1790: }
1791:
1792: /**
1793: * Return the set of filter mappings for this Context.
1794: */
1795: public FilterMap[] findFilterMaps() {
1796:
1797: return (filterMaps);
1798:
1799: }
1800:
1801: /**
1802: * Return the set of InstanceListener classes that will be added to
1803: * newly created Wrappers automatically.
1804: */
1805: public String[] findInstanceListeners() {
1806:
1807: return (instanceListeners);
1808:
1809: }
1810:
1811: /**
1812: * Return the local EJB resource reference with the specified name, if any;
1813: * otherwise, return <code>null</code>.
1814: *
1815: * @param name Name of the desired EJB resource reference
1816: */
1817: public ContextLocalEjb findLocalEjb(String name) {
1818:
1819: return namingResources.findLocalEjb(name);
1820:
1821: }
1822:
1823: /**
1824: * Return the defined local EJB resource references for this application.
1825: * If there are none, a zero-length array is returned.
1826: */
1827: public ContextLocalEjb[] findLocalEjbs() {
1828:
1829: return namingResources.findLocalEjbs();
1830:
1831: }
1832:
1833: /**
1834: * Return the MIME type to which the specified extension is mapped,
1835: * if any; otherwise return <code>null</code>.
1836: *
1837: * @param extension Extension to map to a MIME type
1838: */
1839: public String findMimeMapping(String extension) {
1840:
1841: synchronized (mimeMappings) {
1842: return ((String) mimeMappings.get(extension));
1843: }
1844:
1845: }
1846:
1847: /**
1848: * Return the extensions for which MIME mappings are defined. If there
1849: * are none, a zero-length array is returned.
1850: */
1851: public String[] findMimeMappings() {
1852:
1853: synchronized (mimeMappings) {
1854: String results[] = new String[mimeMappings.size()];
1855: return ((String[]) mimeMappings.keySet().toArray(results));
1856: }
1857:
1858: }
1859:
1860: /**
1861: * Return the value for the specified context initialization
1862: * parameter name, if any; otherwise return <code>null</code>.
1863: *
1864: * @param name Name of the parameter to return
1865: */
1866: public String findParameter(String name) {
1867:
1868: synchronized (parameters) {
1869: return ((String) parameters.get(name));
1870: }
1871:
1872: }
1873:
1874: /**
1875: * Return the names of all defined context initialization parameters
1876: * for this Context. If no parameters are defined, a zero-length
1877: * array is returned.
1878: */
1879: public String[] findParameters() {
1880:
1881: synchronized (parameters) {
1882: String results[] = new String[parameters.size()];
1883: return ((String[]) parameters.keySet().toArray(results));
1884: }
1885:
1886: }
1887:
1888: /**
1889: * Return the resource reference with the specified name, if any;
1890: * otherwise return <code>null</code>.
1891: *
1892: * @param name Name of the desired resource reference
1893: */
1894: public ContextResource findResource(String name) {
1895:
1896: return namingResources.findResource(name);
1897:
1898: }
1899:
1900: /**
1901: * Return the resource environment reference type for the specified
1902: * name, if any; otherwise return <code>null</code>.
1903: *
1904: * @param name Name of the desired resource environment reference
1905: */
1906: public String findResourceEnvRef(String name) {
1907:
1908: return namingResources.findResourceEnvRef(name);
1909:
1910: }
1911:
1912: /**
1913: * Return the set of resource environment reference names for this
1914: * web application. If none have been specified, a zero-length
1915: * array is returned.
1916: */
1917: public String[] findResourceEnvRefs() {
1918:
1919: return namingResources.findResourceEnvRefs();
1920:
1921: }
1922:
1923: /**
1924: * Return the resource link with the specified name, if any;
1925: * otherwise return <code>null</code>.
1926: *
1927: * @param name Name of the desired resource link
1928: */
1929: public ContextResourceLink findResourceLink(String name) {
1930:
1931: return namingResources.findResourceLink(name);
1932:
1933: }
1934:
1935: /**
1936: * Return the defined resource links for this application. If
1937: * none have been defined, a zero-length array is returned.
1938: */
1939: public ContextResourceLink[] findResourceLinks() {
1940:
1941: return namingResources.findResourceLinks();
1942:
1943: }
1944:
1945: /**
1946: * Return the defined resource references for this application. If
1947: * none have been defined, a zero-length array is returned.
1948: */
1949: public ContextResource[] findResources() {
1950:
1951: return namingResources.findResources();
1952:
1953: }
1954:
1955: /**
1956: * For the given security role (as used by an application), return the
1957: * corresponding role name (as defined by the underlying Realm) if there
1958: * is one. Otherwise, return the specified role unchanged.
1959: *
1960: * @param role Security role to map
1961: */
1962: public String findRoleMapping(String role) {
1963:
1964: String realRole = null;
1965: synchronized (roleMappings) {
1966: realRole = (String) roleMappings.get(role);
1967: }
1968: if (realRole != null)
1969: return (realRole);
1970: else
1971: return (role);
1972:
1973: }
1974:
1975: /**
1976: * Return <code>true</code> if the specified security role is defined
1977: * for this application; otherwise return <code>false</code>.
1978: *
1979: * @param role Security role to verify
1980: */
1981: public boolean findSecurityRole(String role) {
1982:
1983: synchronized (securityRoles) {
1984: for (int i = 0; i < securityRoles.length; i++) {
1985: if (role.equals(securityRoles[i]))
1986: return (true);
1987: }
1988: }
1989: return (false);
1990:
1991: }
1992:
1993: /**
1994: * Return the security roles defined for this application. If none
1995: * have been defined, a zero-length array is returned.
1996: */
1997: public String[] findSecurityRoles() {
1998:
1999: return (securityRoles);
2000:
2001: }
2002:
2003: /**
2004: * Return the servlet name mapped by the specified pattern (if any);
2005: * otherwise return <code>null</code>.
2006: *
2007: * @param pattern Pattern for which a mapping is requested
2008: */
2009: public String findServletMapping(String pattern) {
2010:
2011: synchronized (servletMappings) {
2012: return ((String) servletMappings.get(pattern));
2013: }
2014:
2015: }
2016:
2017: /**
2018: * Return the patterns of all defined servlet mappings for this
2019: * Context. If no mappings are defined, a zero-length array is returned.
2020: */
2021: public String[] findServletMappings() {
2022:
2023: synchronized (servletMappings) {
2024: String results[] = new String[servletMappings.size()];
2025: return ((String[]) servletMappings.keySet()
2026: .toArray(results));
2027: }
2028:
2029: }
2030:
2031: /**
2032: * Return the context-relative URI of the error page for the specified
2033: * HTTP status code, if any; otherwise return <code>null</code>.
2034: *
2035: * @param status HTTP status code to look up
2036: */
2037: public String findStatusPage(int status) {
2038:
2039: return ((String) statusPages.get(new Integer(status)));
2040:
2041: }
2042:
2043: /**
2044: * Return the set of HTTP status codes for which error pages have
2045: * been specified. If none are specified, a zero-length array
2046: * is returned.
2047: */
2048: public int[] findStatusPages() {
2049:
2050: synchronized (statusPages) {
2051: int results[] = new int[statusPages.size()];
2052: Iterator elements = statusPages.keySet().iterator();
2053: int i = 0;
2054: while (elements.hasNext())
2055: results[i++] = ((Integer) elements.next()).intValue();
2056: return (results);
2057: }
2058:
2059: }
2060:
2061: /**
2062: * Return the tag library descriptor location for the specified taglib
2063: * URI, if any; otherwise, return <code>null</code>.
2064: *
2065: * @param uri URI, relative to the web.xml file
2066: */
2067: public String findTaglib(String uri) {
2068:
2069: synchronized (taglibs) {
2070: return ((String) taglibs.get(uri));
2071: }
2072:
2073: }
2074:
2075: /**
2076: * Return the URIs of all tag libraries for which a tag library
2077: * descriptor location has been specified. If none are specified,
2078: * a zero-length array is returned.
2079: */
2080: public String[] findTaglibs() {
2081:
2082: synchronized (taglibs) {
2083: String results[] = new String[taglibs.size()];
2084: return ((String[]) taglibs.keySet().toArray(results));
2085: }
2086:
2087: }
2088:
2089: /**
2090: * Return <code>true</code> if the specified welcome file is defined
2091: * for this Context; otherwise return <code>false</code>.
2092: *
2093: * @param name Welcome file to verify
2094: */
2095: public boolean findWelcomeFile(String name) {
2096:
2097: synchronized (welcomeFiles) {
2098: for (int i = 0; i < welcomeFiles.length; i++) {
2099: if (name.equals(welcomeFiles[i]))
2100: return (true);
2101: }
2102: }
2103: return (false);
2104:
2105: }
2106:
2107: /**
2108: * Return the set of welcome files defined for this Context. If none are
2109: * defined, a zero-length array is returned.
2110: */
2111: public String[] findWelcomeFiles() {
2112:
2113: return (welcomeFiles);
2114:
2115: }
2116:
2117: /**
2118: * Return the set of LifecycleListener classes that will be added to
2119: * newly created Wrappers automatically.
2120: */
2121: public String[] findWrapperLifecycles() {
2122:
2123: return (wrapperLifecycles);
2124:
2125: }
2126:
2127: /**
2128: * Return the set of ContainerListener classes that will be added to
2129: * newly created Wrappers automatically.
2130: */
2131: public String[] findWrapperListeners() {
2132:
2133: return (wrapperListeners);
2134:
2135: }
2136:
2137: /**
2138: * Process the specified Request, and generate the corresponding Response,
2139: * according to the design of this particular Container.
2140: *
2141: * @param request Request to be processed
2142: * @param response Response to be produced
2143: *
2144: * @exception IOException if an input/output error occurred while
2145: * processing
2146: * @exception ServletException if a ServletException was thrown
2147: * while processing this request
2148: */
2149: public void invoke(Request request, Response response)
2150: throws IOException, ServletException {
2151:
2152: // Wait if we are reloading
2153: while (getPaused()) {
2154: try {
2155: Thread.sleep(1000);
2156: } catch (InterruptedException e) {
2157: ;
2158: }
2159: }
2160:
2161: // Normal request processing
2162: super .invoke(request, response);
2163:
2164: }
2165:
2166: /**
2167: * Reload this web application, if reloading is supported.
2168: * <p>
2169: * <b>IMPLEMENTATION NOTE</b>: This method is designed to deal with
2170: * reloads required by changes to classes in the underlying repositories
2171: * of our class loader. It does not handle changes to the web application
2172: * deployment descriptor. If that has occurred, you should stop this
2173: * Context and create (and start) a new Context instance instead.
2174: *
2175: * @exception IllegalStateException if the <code>reloadable</code>
2176: * property is set to <code>false</code>.
2177: */
2178: public synchronized void reload() {
2179:
2180: // Validate our current component state
2181: if (!started)
2182: throw new IllegalStateException(sm.getString(
2183: "containerBase.notStarted", logName()));
2184:
2185: // Make sure reloading is enabled
2186: // if (!reloadable)
2187: // throw new IllegalStateException
2188: // (sm.getString("standardContext.notReloadable"));
2189: log(sm.getString("standardContext.reloadingStarted"));
2190:
2191: // Stop accepting requests temporarily
2192: setPaused(true);
2193:
2194: // Binding thread
2195: ClassLoader oldCCL = bindThread();
2196:
2197: // Shut down our session manager
2198: if ((manager != null) && (manager instanceof Lifecycle)) {
2199: try {
2200: ((Lifecycle) manager).stop();
2201: } catch (LifecycleException e) {
2202: log(sm.getString("standardContext.stoppingManager"), e);
2203: }
2204: }
2205:
2206: // Shut down the current version of all active servlets
2207: Container children[] = findChildren();
2208: for (int i = 0; i < children.length; i++) {
2209: Wrapper wrapper = (Wrapper) children[i];
2210: if (wrapper instanceof Lifecycle) {
2211: try {
2212: ((Lifecycle) wrapper).stop();
2213: } catch (LifecycleException e) {
2214: log(sm.getString("standardContext.stoppingWrapper",
2215: wrapper.getName()), e);
2216: }
2217: }
2218: }
2219:
2220: // Shut down application event listeners
2221: listenerStop();
2222:
2223: // Clear all application-originated servlet context attributes
2224: if (context != null)
2225: context.clearAttributes();
2226:
2227: // Shut down filters
2228: filterStop();
2229:
2230: if (isUseNaming()) {
2231: // Start
2232: namingContextListener.lifecycleEvent(new LifecycleEvent(
2233: this , Lifecycle.STOP_EVENT));
2234: }
2235:
2236: // Binding thread
2237: unbindThread(oldCCL);
2238:
2239: // Shut down our application class loader
2240: if ((loader != null) && (loader instanceof Lifecycle)) {
2241: try {
2242: ((Lifecycle) loader).stop();
2243: } catch (LifecycleException e) {
2244: log(sm.getString("standardContext.stoppingLoader"), e);
2245: }
2246: }
2247:
2248: // Binding thread
2249: oldCCL = bindThread();
2250:
2251: // Restart our application class loader
2252: if ((loader != null) && (loader instanceof Lifecycle)) {
2253: try {
2254: ((Lifecycle) loader).start();
2255: } catch (LifecycleException e) {
2256: log(sm.getString("standardContext.startingLoader"), e);
2257: }
2258: }
2259:
2260: // Binding thread
2261: unbindThread(oldCCL);
2262:
2263: // Create and register the associated naming context, if internal
2264: // naming is used
2265: boolean ok = true;
2266: if (isUseNaming()) {
2267: // Start
2268: namingContextListener.lifecycleEvent(new LifecycleEvent(
2269: this , Lifecycle.START_EVENT));
2270: }
2271:
2272: // Binding thread
2273: oldCCL = bindThread();
2274:
2275: // Restart our application event listeners and filters
2276: if (ok) {
2277: if (!listenerStart()) {
2278: log(sm.getString("standardContext.listenerStartFailed"));
2279: ok = false;
2280: }
2281: }
2282: if (ok) {
2283: if (!filterStart()) {
2284: log(sm.getString("standardContext.filterStartFailed"));
2285: ok = false;
2286: }
2287: }
2288:
2289: // Restore the "Welcome Files" and "Resources" context attributes
2290: postResources();
2291: postWelcomeFiles();
2292:
2293: // Restart our currently defined servlets
2294: for (int i = 0; i < children.length; i++) {
2295: if (!ok)
2296: break;
2297: Wrapper wrapper = (Wrapper) children[i];
2298: if (wrapper instanceof Lifecycle) {
2299: try {
2300: ((Lifecycle) wrapper).start();
2301: } catch (LifecycleException e) {
2302: log(sm.getString("standardContext.startingWrapper",
2303: wrapper.getName()), e);
2304: ok = false;
2305: }
2306: }
2307: }
2308:
2309: // Reinitialize all load on startup servlets
2310: loadOnStartup(children);
2311:
2312: // Restart our session manager (AFTER naming context recreated/bound)
2313: if ((manager != null) && (manager instanceof Lifecycle)) {
2314: try {
2315: ((Lifecycle) manager).start();
2316: } catch (LifecycleException e) {
2317: log(sm.getString("standardContext.startingManager"), e);
2318: }
2319: }
2320:
2321: // Unbinding thread
2322: unbindThread(oldCCL);
2323:
2324: // Start accepting requests again
2325: if (ok) {
2326: log(sm.getString("standardContext.reloadingCompleted"));
2327: } else {
2328: setAvailable(false);
2329: log(sm.getString("standardContext.reloadingFailed"));
2330: }
2331: setPaused(false);
2332:
2333: // Notify our interested LifecycleListeners
2334: lifecycle.fireLifecycleEvent(Context.RELOAD_EVENT, null);
2335:
2336: }
2337:
2338: /**
2339: * Remove the specified application listener class from the set of
2340: * listeners for this application.
2341: *
2342: * @param listener Java class name of the listener to be removed
2343: */
2344: public void removeApplicationListener(String listener) {
2345:
2346: synchronized (applicationListeners) {
2347:
2348: // Make sure this welcome file is currently present
2349: int n = -1;
2350: for (int i = 0; i < applicationListeners.length; i++) {
2351: if (applicationListeners[i].equals(listener)) {
2352: n = i;
2353: break;
2354: }
2355: }
2356: if (n < 0)
2357: return;
2358:
2359: // Remove the specified constraint
2360: int j = 0;
2361: String results[] = new String[applicationListeners.length - 1];
2362: for (int i = 0; i < applicationListeners.length; i++) {
2363: if (i != n)
2364: results[j++] = applicationListeners[i];
2365: }
2366: applicationListeners = results;
2367:
2368: }
2369:
2370: // Inform interested listeners
2371: fireContainerEvent("removeApplicationListener", listener);
2372:
2373: // FIXME - behavior if already started?
2374:
2375: }
2376:
2377: /**
2378: * Remove the application parameter with the specified name from
2379: * the set for this application.
2380: *
2381: * @param name Name of the application parameter to remove
2382: */
2383: public void removeApplicationParameter(String name) {
2384:
2385: synchronized (applicationParameters) {
2386:
2387: // Make sure this parameter is currently present
2388: int n = -1;
2389: for (int i = 0; i < applicationParameters.length; i++) {
2390: if (name.equals(applicationParameters[i].getName())) {
2391: n = i;
2392: break;
2393: }
2394: }
2395: if (n < 0)
2396: return;
2397:
2398: // Remove the specified parameter
2399: int j = 0;
2400: ApplicationParameter results[] = new ApplicationParameter[applicationParameters.length - 1];
2401: for (int i = 0; i < applicationParameters.length; i++) {
2402: if (i != n)
2403: results[j++] = applicationParameters[i];
2404: }
2405: applicationParameters = results;
2406:
2407: }
2408:
2409: // Inform interested listeners
2410: fireContainerEvent("removeApplicationParameter", name);
2411:
2412: }
2413:
2414: /**
2415: * Remove the specified security constraint from this web application.
2416: *
2417: * @param constraint Constraint to be removed
2418: */
2419: public void removeConstraint(SecurityConstraint constraint) {
2420:
2421: synchronized (constraints) {
2422:
2423: // Make sure this constraint is currently present
2424: int n = -1;
2425: for (int i = 0; i < constraints.length; i++) {
2426: if (constraints[i].equals(constraint)) {
2427: n = i;
2428: break;
2429: }
2430: }
2431: if (n < 0)
2432: return;
2433:
2434: // Remove the specified constraint
2435: int j = 0;
2436: SecurityConstraint results[] = new SecurityConstraint[constraints.length - 1];
2437: for (int i = 0; i < constraints.length; i++) {
2438: if (i != n)
2439: results[j++] = constraints[i];
2440: }
2441: constraints = results;
2442:
2443: }
2444:
2445: // Inform interested listeners
2446: fireContainerEvent("removeConstraint", constraint);
2447:
2448: }
2449:
2450: /**
2451: * Remove any EJB resource reference with the specified name.
2452: *
2453: * @param name Name of the EJB resource reference to remove
2454: */
2455: public void removeEjb(String name) {
2456:
2457: namingResources.removeEjb(name);
2458: fireContainerEvent("removeEjb", name);
2459:
2460: }
2461:
2462: /**
2463: * Remove any environment entry with the specified name.
2464: *
2465: * @param name Name of the environment entry to remove
2466: */
2467: public void removeEnvironment(String name) {
2468:
2469: namingResources.removeEnvironment(name);
2470: fireContainerEvent("removeEnvironment", name);
2471:
2472: }
2473:
2474: /**
2475: * Remove the error page for the specified error code or
2476: * Java language exception, if it exists; otherwise, no action is taken.
2477: *
2478: * @param errorPage The error page definition to be removed
2479: */
2480: public void removeErrorPage(ErrorPage errorPage) {
2481:
2482: String exceptionType = errorPage.getExceptionType();
2483: if (exceptionType != null) {
2484: synchronized (exceptionPages) {
2485: exceptionPages.remove(exceptionType);
2486: }
2487: } else {
2488: synchronized (statusPages) {
2489: statusPages
2490: .remove(new Integer(errorPage.getErrorCode()));
2491: }
2492: }
2493: fireContainerEvent("removeErrorPage", errorPage);
2494:
2495: }
2496:
2497: /**
2498: * Remove the specified filter definition from this Context, if it exists;
2499: * otherwise, no action is taken.
2500: *
2501: * @param filterDef Filter definition to be removed
2502: */
2503: public void removeFilterDef(FilterDef filterDef) {
2504:
2505: synchronized (filterDefs) {
2506: filterDefs.remove(filterDef.getFilterName());
2507: }
2508: fireContainerEvent("removeFilterDef", filterDef);
2509:
2510: }
2511:
2512: /**
2513: * Remove a filter mapping from this Context.
2514: *
2515: * @param filterMap The filter mapping to be removed
2516: */
2517: public void removeFilterMap(FilterMap filterMap) {
2518:
2519: synchronized (filterMaps) {
2520:
2521: // Make sure this filter mapping is currently present
2522: int n = -1;
2523: for (int i = 0; i < filterMaps.length; i++) {
2524: if (filterMaps[i] == filterMap) {
2525: n = i;
2526: break;
2527: }
2528: }
2529: if (n < 0)
2530: return;
2531:
2532: // Remove the specified filter mapping
2533: FilterMap results[] = new FilterMap[filterMaps.length - 1];
2534: System.arraycopy(filterMaps, 0, results, 0, n);
2535: System.arraycopy(filterMaps, n + 1, results, n,
2536: (filterMaps.length - 1) - n);
2537: filterMaps = results;
2538:
2539: }
2540:
2541: // Inform interested listeners
2542: fireContainerEvent("removeFilterMap", filterMap);
2543:
2544: }
2545:
2546: /**
2547: * Remove a class name from the set of InstanceListener classes that
2548: * will be added to newly created Wrappers.
2549: *
2550: * @param listener Class name of an InstanceListener class to be removed
2551: */
2552: public void removeInstanceListener(String listener) {
2553:
2554: synchronized (instanceListeners) {
2555:
2556: // Make sure this welcome file is currently present
2557: int n = -1;
2558: for (int i = 0; i < instanceListeners.length; i++) {
2559: if (instanceListeners[i].equals(listener)) {
2560: n = i;
2561: break;
2562: }
2563: }
2564: if (n < 0)
2565: return;
2566:
2567: // Remove the specified constraint
2568: int j = 0;
2569: String results[] = new String[instanceListeners.length - 1];
2570: for (int i = 0; i < instanceListeners.length; i++) {
2571: if (i != n)
2572: results[j++] = instanceListeners[i];
2573: }
2574: instanceListeners = results;
2575:
2576: }
2577:
2578: // Inform interested listeners
2579: fireContainerEvent("removeInstanceListener", listener);
2580:
2581: }
2582:
2583: /**
2584: * Remove any local EJB resource reference with the specified name.
2585: *
2586: * @param name Name of the EJB resource reference to remove
2587: */
2588: public void removeLocalEjb(String name) {
2589:
2590: namingResources.removeLocalEjb(name);
2591: fireContainerEvent("removeLocalEjb", name);
2592:
2593: }
2594:
2595: /**
2596: * Remove the MIME mapping for the specified extension, if it exists;
2597: * otherwise, no action is taken.
2598: *
2599: * @param extension Extension to remove the mapping for
2600: */
2601: public void removeMimeMapping(String extension) {
2602:
2603: synchronized (mimeMappings) {
2604: mimeMappings.remove(extension);
2605: }
2606: fireContainerEvent("removeMimeMapping", extension);
2607:
2608: }
2609:
2610: /**
2611: * Remove the context initialization parameter with the specified
2612: * name, if it exists; otherwise, no action is taken.
2613: *
2614: * @param name Name of the parameter to remove
2615: */
2616: public void removeParameter(String name) {
2617:
2618: synchronized (parameters) {
2619: parameters.remove(name);
2620: }
2621: fireContainerEvent("removeParameter", name);
2622:
2623: }
2624:
2625: /**
2626: * Remove any resource reference with the specified name.
2627: *
2628: * @param name Name of the resource reference to remove
2629: */
2630: public void removeResource(String name) {
2631:
2632: namingResources.removeResource(name);
2633: fireContainerEvent("removeResource", name);
2634:
2635: }
2636:
2637: /**
2638: * Remove any resource environment reference with the specified name.
2639: *
2640: * @param name Name of the resource environment reference to remove
2641: */
2642: public void removeResourceEnvRef(String name) {
2643:
2644: namingResources.removeResourceEnvRef(name);
2645: fireContainerEvent("removeResourceEnvRef", name);
2646:
2647: }
2648:
2649: /**
2650: * Remove any resource link with the specified name.
2651: *
2652: * @param name Name of the resource link to remove
2653: */
2654: public void removeResourceLink(String name) {
2655:
2656: namingResources.removeResourceLink(name);
2657: fireContainerEvent("removeResourceLink", name);
2658:
2659: }
2660:
2661: /**
2662: * Remove any security role reference for the specified name
2663: *
2664: * @param role Security role (as used in the application) to remove
2665: */
2666: public void removeRoleMapping(String role) {
2667:
2668: synchronized (roleMappings) {
2669: roleMappings.remove(role);
2670: }
2671: fireContainerEvent("removeRoleMapping", role);
2672:
2673: }
2674:
2675: /**
2676: * Remove any security role with the specified name.
2677: *
2678: * @param role Security role to remove
2679: */
2680: public void removeSecurityRole(String role) {
2681:
2682: synchronized (securityRoles) {
2683:
2684: // Make sure this security role is currently present
2685: int n = -1;
2686: for (int i = 0; i < securityRoles.length; i++) {
2687: if (role.equals(securityRoles[i])) {
2688: n = i;
2689: break;
2690: }
2691: }
2692: if (n < 0)
2693: return;
2694:
2695: // Remove the specified security role
2696: int j = 0;
2697: String results[] = new String[securityRoles.length - 1];
2698: for (int i = 0; i < securityRoles.length; i++) {
2699: if (i != n)
2700: results[j++] = securityRoles[i];
2701: }
2702: securityRoles = results;
2703:
2704: }
2705:
2706: // Inform interested listeners
2707: fireContainerEvent("removeSecurityRole", role);
2708:
2709: }
2710:
2711: /**
2712: * Remove any servlet mapping for the specified pattern, if it exists;
2713: * otherwise, no action is taken.
2714: *
2715: * @param pattern URL pattern of the mapping to remove
2716: */
2717: public void removeServletMapping(String pattern) {
2718:
2719: synchronized (servletMappings) {
2720: servletMappings.remove(pattern);
2721: }
2722: fireContainerEvent("removeServletMapping", pattern);
2723:
2724: }
2725:
2726: /**
2727: * Remove the tag library location forthe specified tag library URI.
2728: *
2729: * @param uri URI, relative to the web.xml file
2730: */
2731: public void removeTaglib(String uri) {
2732:
2733: synchronized (taglibs) {
2734: taglibs.remove(uri);
2735: }
2736: fireContainerEvent("removeTaglib", uri);
2737: }
2738:
2739: /**
2740: * Remove the specified welcome file name from the list recognized
2741: * by this Context.
2742: *
2743: * @param name Name of the welcome file to be removed
2744: */
2745: public void removeWelcomeFile(String name) {
2746:
2747: synchronized (welcomeFiles) {
2748:
2749: // Make sure this welcome file is currently present
2750: int n = -1;
2751: for (int i = 0; i < welcomeFiles.length; i++) {
2752: if (welcomeFiles[i].equals(name)) {
2753: n = i;
2754: break;
2755: }
2756: }
2757: if (n < 0)
2758: return;
2759:
2760: // Remove the specified constraint
2761: int j = 0;
2762: String results[] = new String[welcomeFiles.length - 1];
2763: for (int i = 0; i < welcomeFiles.length; i++) {
2764: if (i != n)
2765: results[j++] = welcomeFiles[i];
2766: }
2767: welcomeFiles = results;
2768:
2769: }
2770:
2771: // Inform interested listeners
2772: postWelcomeFiles();
2773: fireContainerEvent("removeWelcomeFile", name);
2774:
2775: }
2776:
2777: /**
2778: * Remove a class name from the set of LifecycleListener classes that
2779: * will be added to newly created Wrappers.
2780: *
2781: * @param listener Class name of a LifecycleListener class to be removed
2782: */
2783: public void removeWrapperLifecycle(String listener) {
2784:
2785: synchronized (wrapperLifecycles) {
2786:
2787: // Make sure this welcome file is currently present
2788: int n = -1;
2789: for (int i = 0; i < wrapperLifecycles.length; i++) {
2790: if (wrapperLifecycles[i].equals(listener)) {
2791: n = i;
2792: break;
2793: }
2794: }
2795: if (n < 0)
2796: return;
2797:
2798: // Remove the specified constraint
2799: int j = 0;
2800: String results[] = new String[wrapperLifecycles.length - 1];
2801: for (int i = 0; i < wrapperLifecycles.length; i++) {
2802: if (i != n)
2803: results[j++] = wrapperLifecycles[i];
2804: }
2805: wrapperLifecycles = results;
2806:
2807: }
2808:
2809: // Inform interested listeners
2810: fireContainerEvent("removeWrapperLifecycle", listener);
2811:
2812: }
2813:
2814: /**
2815: * Remove a class name from the set of ContainerListener classes that
2816: * will be added to newly created Wrappers.
2817: *
2818: * @param listener Class name of a ContainerListener class to be removed
2819: */
2820: public void removeWrapperListener(String listener) {
2821:
2822: synchronized (wrapperListeners) {
2823:
2824: // Make sure this welcome file is currently present
2825: int n = -1;
2826: for (int i = 0; i < wrapperListeners.length; i++) {
2827: if (wrapperListeners[i].equals(listener)) {
2828: n = i;
2829: break;
2830: }
2831: }
2832: if (n < 0)
2833: return;
2834:
2835: // Remove the specified constraint
2836: int j = 0;
2837: String results[] = new String[wrapperListeners.length - 1];
2838: for (int i = 0; i < wrapperListeners.length; i++) {
2839: if (i != n)
2840: results[j++] = wrapperListeners[i];
2841: }
2842: wrapperListeners = results;
2843:
2844: }
2845:
2846: // Inform interested listeners
2847: fireContainerEvent("removeWrapperListener", listener);
2848:
2849: }
2850:
2851: // --------------------------------------------------------- Public Methods
2852:
2853: /**
2854: * Configure and initialize the set of filters for this Context.
2855: * Return <code>true</code> if all filter initialization completed
2856: * successfully, or <code>false</code> otherwise.
2857: */
2858: public boolean filterStart() {
2859:
2860: if (debug >= 1)
2861: log("Starting filters");
2862:
2863: // Instantiate and record a FilterConfig for each defined filter
2864: boolean ok = true;
2865: synchronized (filterConfigs) {
2866: filterConfigs.clear();
2867: Iterator names = filterDefs.keySet().iterator();
2868: while (names.hasNext()) {
2869: String name = (String) names.next();
2870: if (debug >= 1)
2871: log(" Starting filter '" + name + "'");
2872: ApplicationFilterConfig filterConfig = null;
2873: try {
2874: filterConfig = new ApplicationFilterConfig(this ,
2875: (FilterDef) filterDefs.get(name));
2876: filterConfigs.put(name, filterConfig);
2877: } catch (Throwable t) {
2878: log(sm.getString("standardContext.filterStart",
2879: name), t);
2880: ok = false;
2881: }
2882: }
2883: }
2884:
2885: return (ok);
2886:
2887: }
2888:
2889: /**
2890: * Finalize and release the set of filters for this Context.
2891: * Return <code>true</code> if all filter finalization completed
2892: * successfully, or <code>false</code> otherwise.
2893: */
2894: public boolean filterStop() {
2895:
2896: if (debug >= 1)
2897: log("Stopping filters");
2898:
2899: // Release all Filter and FilterConfig instances
2900: synchronized (filterConfigs) {
2901: Iterator names = filterConfigs.keySet().iterator();
2902: while (names.hasNext()) {
2903: String name = (String) names.next();
2904: if (debug >= 1)
2905: log(" Stopping filter '" + name + "'");
2906: ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) filterConfigs
2907: .get(name);
2908: filterConfig.release();
2909: }
2910: filterConfigs.clear();
2911: }
2912: return (true);
2913:
2914: }
2915:
2916: /**
2917: * Find and return the initialized <code>FilterConfig</code> for the
2918: * specified filter name, if any; otherwise return <code>null</code>.
2919: *
2920: * @param name Name of the desired filter
2921: */
2922: public FilterConfig findFilterConfig(String name) {
2923:
2924: synchronized (filterConfigs) {
2925: return ((FilterConfig) filterConfigs.get(name));
2926: }
2927:
2928: }
2929:
2930: /**
2931: * Configure the set of instantiated application event listeners
2932: * for this Context. Return <code>true</code> if all listeners wre
2933: * initialized successfully, or <code>false</code> otherwise.
2934: */
2935: public boolean listenerStart() {
2936:
2937: if (debug >= 1)
2938: log("Configuring application event listeners");
2939:
2940: // Instantiate the required listeners
2941: ClassLoader loader = getLoader().getClassLoader();
2942: String listeners[] = findApplicationListeners();
2943: Object results[] = new Object[listeners.length];
2944: boolean ok = true;
2945: for (int i = 0; i < results.length; i++) {
2946: if (debug >= 2)
2947: log(" Configuring event listener class '"
2948: + listeners[i] + "'");
2949: try {
2950: Class clazz = loader.loadClass(listeners[i]);
2951: results[i] = clazz.newInstance();
2952: } catch (Throwable t) {
2953: log(sm.getString("standardContext.applicationListener",
2954: listeners[i]), t);
2955: ok = false;
2956: }
2957: }
2958: if (!ok) {
2959: log(sm.getString("standardContext.applicationSkipped"));
2960: return (false);
2961: }
2962:
2963: // Send application start events
2964:
2965: if (debug >= 1)
2966: log("Sending application start events");
2967:
2968: setApplicationListeners(results);
2969: Object instances[] = getApplicationListeners();
2970: if (instances == null)
2971: return (ok);
2972: ServletContextEvent event = new ServletContextEvent(
2973: getServletContext());
2974: for (int i = 0; i < instances.length; i++) {
2975: if (instances[i] == null)
2976: continue;
2977: if (!(instances[i] instanceof ServletContextListener))
2978: continue;
2979: ServletContextListener listener = (ServletContextListener) instances[i];
2980: try {
2981: fireContainerEvent("beforeContextInitialized", listener);
2982: listener.contextInitialized(event);
2983: fireContainerEvent("afterContextInitialized", listener);
2984: } catch (Throwable t) {
2985: fireContainerEvent("afterContextInitialized", listener);
2986: log(sm.getString("standardContext.listenerStart",
2987: instances[i].getClass().getName()), t);
2988: ok = false;
2989: }
2990: }
2991: return (ok);
2992:
2993: }
2994:
2995: /**
2996: * Send an application stop event to all interested listeners.
2997: * Return <code>true</code> if all events were sent successfully,
2998: * or <code>false</code> otherwise.
2999: */
3000: public boolean listenerStop() {
3001:
3002: if (debug >= 1)
3003: log("Sending application stop events");
3004:
3005: boolean ok = true;
3006: Object listeners[] = getApplicationListeners();
3007: if (listeners == null)
3008: return (ok);
3009: ServletContextEvent event = new ServletContextEvent(
3010: getServletContext());
3011: for (int i = 0; i < listeners.length; i++) {
3012: int j = (listeners.length - 1) - i;
3013: if (listeners[j] == null)
3014: continue;
3015: if (!(listeners[j] instanceof ServletContextListener))
3016: continue;
3017: ServletContextListener listener = (ServletContextListener) listeners[j];
3018: try {
3019: fireContainerEvent("beforeContextDestroyed", listener);
3020: listener.contextDestroyed(event);
3021: fireContainerEvent("beforeContextDestroyed", listener);
3022: } catch (Throwable t) {
3023: fireContainerEvent("beforeContextDestroyed", listener);
3024: log(sm.getString("standardContext.listenerStop",
3025: listeners[j].getClass().getName()), t);
3026: ok = false;
3027: }
3028: }
3029: setApplicationListeners(null);
3030: return (ok);
3031:
3032: }
3033:
3034: /**
3035: * Load and initialize all servlets marked "load on startup" in the
3036: * web application deployment descriptor.
3037: *
3038: * @param children Array of wrappers for all currently defined
3039: * servlets (including those not declared load on startup)
3040: */
3041: public void loadOnStartup(Container children[]) {
3042:
3043: // Collect "load on startup" servlets that need to be initialized
3044: TreeMap map = new TreeMap();
3045: for (int i = 0; i < children.length; i++) {
3046: Wrapper wrapper = (Wrapper) children[i];
3047: int loadOnStartup = wrapper.getLoadOnStartup();
3048: if (loadOnStartup < 0)
3049: continue;
3050: if (loadOnStartup == 0) // Arbitrarily put them last
3051: loadOnStartup = Integer.MAX_VALUE;
3052: Integer key = new Integer(loadOnStartup);
3053: ArrayList list = (ArrayList) map.get(key);
3054: if (list == null) {
3055: list = new ArrayList();
3056: map.put(key, list);
3057: }
3058: list.add(wrapper);
3059: }
3060:
3061: // Load the collected "load on startup" servlets
3062: Iterator keys = map.keySet().iterator();
3063: while (keys.hasNext()) {
3064: Integer key = (Integer) keys.next();
3065: ArrayList list = (ArrayList) map.get(key);
3066: Iterator wrappers = list.iterator();
3067: while (wrappers.hasNext()) {
3068: Wrapper wrapper = (Wrapper) wrappers.next();
3069: try {
3070: wrapper.load();
3071: } catch (ServletException e) {
3072: log(sm.getString("standardWrapper.loadException",
3073: getName()), e);
3074: // NOTE: load errors (including a servlet that throws
3075: // UnavailableException from tht init() method) are NOT
3076: // fatal to application startup
3077: }
3078: }
3079: }
3080:
3081: }
3082:
3083: /**
3084: * Start this Context component.
3085: *
3086: * @exception LifecycleException if a startup error occurs
3087: */
3088: public synchronized void start() throws LifecycleException {
3089:
3090: if (started)
3091: throw new LifecycleException(sm.getString(
3092: "containerBase.alreadyStarted", logName()));
3093:
3094: if (debug >= 1)
3095: log("Starting");
3096:
3097: // Notify our interested LifecycleListeners
3098: lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
3099:
3100: if (debug >= 1)
3101: log("Processing start(), current available="
3102: + getAvailable());
3103: setAvailable(false);
3104: setConfigured(false);
3105: boolean ok = true;
3106:
3107: // Add missing components as necessary
3108: if (getResources() == null) { // (1) Required by Loader
3109: if (debug >= 1)
3110: log("Configuring default Resources");
3111: try {
3112: if ((docBase != null) && (docBase.endsWith(".war")))
3113: setResources(new WARDirContext());
3114: else
3115: setResources(new FileDirContext());
3116: } catch (IllegalArgumentException e) {
3117: log("Error initializing resources: " + e.getMessage());
3118: ok = false;
3119: }
3120: if (ok) {
3121: DirContext dirContext = ((ProxyDirContext) resources)
3122: .getDirContext();
3123: if ((dirContext != null)
3124: && (dirContext instanceof BaseDirContext)) {
3125: ((BaseDirContext) dirContext).allocate();
3126: }
3127: }
3128: }
3129: if (getLoader() == null) { // (2) Required by Manager
3130: if (getPrivileged()) {
3131: if (debug >= 1)
3132: log("Configuring privileged default Loader");
3133: setLoader(new WebappLoader(this .getClass()
3134: .getClassLoader()));
3135: } else {
3136: if (debug >= 1)
3137: log("Configuring non-privileged default Loader");
3138: setLoader(new WebappLoader(getParentClassLoader()));
3139: }
3140: }
3141: if (getManager() == null) { // (3) After prerequisites
3142: if (debug >= 1)
3143: log("Configuring default Manager");
3144: setManager(new StandardManager());
3145: }
3146:
3147: // Initialize character set mapper
3148: getCharsetMapper();
3149:
3150: // Post work directory
3151: postWorkDirectory();
3152:
3153: // Reading the "catalina.useNaming" environment variable
3154: String useNamingProperty = System
3155: .getProperty("catalina.useNaming");
3156: if ((useNamingProperty != null)
3157: && (useNamingProperty.equals("false"))) {
3158: useNaming = false;
3159: }
3160:
3161: if (ok && isUseNaming()) {
3162: if (namingContextListener == null) {
3163: namingContextListener = new NamingContextListener();
3164: namingContextListener.setDebug(getDebug());
3165: namingContextListener.setName(getNamingContextName());
3166: addLifecycleListener(namingContextListener);
3167: }
3168: }
3169:
3170: // Binding thread
3171: ClassLoader oldCCL = bindThread();
3172:
3173: // Standard container startup
3174: if (debug >= 1)
3175: log("Processing standard container startup");
3176:
3177: if (ok) {
3178:
3179: try {
3180:
3181: addDefaultMapper(this .mapperClass);
3182: started = true;
3183:
3184: // Start our subordinate components, if any
3185: if ((loader != null) && (loader instanceof Lifecycle))
3186: ((Lifecycle) loader).start();
3187: if ((logger != null) && (logger instanceof Lifecycle))
3188: ((Lifecycle) logger).start();
3189:
3190: // Unbinding thread
3191: unbindThread(oldCCL);
3192:
3193: // Binding thread
3194: oldCCL = bindThread();
3195:
3196: if ((cluster != null) && (cluster instanceof Lifecycle))
3197: ((Lifecycle) cluster).start();
3198: if ((realm != null) && (realm instanceof Lifecycle))
3199: ((Lifecycle) realm).start();
3200: if ((resources != null)
3201: && (resources instanceof Lifecycle))
3202: ((Lifecycle) resources).start();
3203:
3204: // Start our Mappers, if any
3205: Mapper mappers[] = findMappers();
3206: for (int i = 0; i < mappers.length; i++) {
3207: if (mappers[i] instanceof Lifecycle)
3208: ((Lifecycle) mappers[i]).start();
3209: }
3210:
3211: // Start our child containers, if any
3212: Container children[] = findChildren();
3213: for (int i = 0; i < children.length; i++) {
3214: if (children[i] instanceof Lifecycle)
3215: ((Lifecycle) children[i]).start();
3216: }
3217:
3218: // Start the Valves in our pipeline (including the basic),
3219: // if any
3220: if (pipeline instanceof Lifecycle)
3221: ((Lifecycle) pipeline).start();
3222:
3223: // Notify our interested LifecycleListeners
3224: lifecycle.fireLifecycleEvent(START_EVENT, null);
3225:
3226: if ((manager != null) && (manager instanceof Lifecycle))
3227: ((Lifecycle) manager).start();
3228:
3229: } finally {
3230: // Unbinding thread
3231: unbindThread(oldCCL);
3232: }
3233:
3234: }
3235: if (!getConfigured())
3236: ok = false;
3237:
3238: // We put the resources into the servlet context
3239: if (ok)
3240: getServletContext().setAttribute(Globals.RESOURCES_ATTR,
3241: getResources());
3242:
3243: // Binding thread
3244: oldCCL = bindThread();
3245:
3246: // Create context attributes that will be required
3247: if (ok) {
3248: if (debug >= 1)
3249: log("Posting standard context attributes");
3250: postWelcomeFiles();
3251: }
3252:
3253: // Configure and call application event listeners and filters
3254: if (ok) {
3255: if (!listenerStart())
3256: ok = false;
3257: }
3258: if (ok) {
3259: if (!filterStart())
3260: ok = false;
3261: }
3262:
3263: // Load and initialize all "load on startup" servlets
3264: if (ok)
3265: loadOnStartup(findChildren());
3266:
3267: // Unbinding thread
3268: unbindThread(oldCCL);
3269:
3270: // Set available status depending upon startup success
3271: if (ok) {
3272: if (debug >= 1)
3273: log("Starting completed");
3274: setAvailable(true);
3275: } else {
3276: log(sm.getString("standardContext.startFailed"));
3277: try {
3278: stop();
3279: } catch (Throwable t) {
3280: log(sm.getString("standardContext.startCleanup"), t);
3281: }
3282: setAvailable(false);
3283: }
3284:
3285: // Notify our interested LifecycleListeners
3286: lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
3287:
3288: }
3289:
3290: /**
3291: * Stop this Context component.
3292: *
3293: * @exception LifecycleException if a shutdown error occurs
3294: */
3295: public synchronized void stop() throws LifecycleException {
3296:
3297: // Validate and update our current component state
3298: if (!started)
3299: throw new LifecycleException(sm.getString(
3300: "containerBase.notStarted", logName()));
3301:
3302: if (debug >= 1)
3303: log("Stopping");
3304:
3305: // Notify our interested LifecycleListeners
3306: lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
3307:
3308: // Mark this application as unavailable while we shut down
3309: setAvailable(false);
3310:
3311: // Binding thread
3312: ClassLoader oldCCL = bindThread();
3313:
3314: // Stop our filters
3315: filterStop();
3316:
3317: // Finalize our character set mapper
3318: setCharsetMapper(null);
3319:
3320: if ((manager != null) && (manager instanceof Lifecycle)) {
3321: ((Lifecycle) manager).stop();
3322: }
3323:
3324: // Normal container shutdown processing
3325: if (debug >= 1)
3326: log("Processing standard container shutdown");
3327: // Notify our interested LifecycleListeners
3328: lifecycle.fireLifecycleEvent(STOP_EVENT, null);
3329: started = false;
3330:
3331: try {
3332:
3333: // Stop the Valves in our pipeline (including the basic), if any
3334: if (pipeline instanceof Lifecycle) {
3335: ((Lifecycle) pipeline).stop();
3336: }
3337:
3338: // Stop our child containers, if any
3339: Container children[] = findChildren();
3340: for (int i = 0; i < children.length; i++) {
3341: if (children[i] instanceof Lifecycle)
3342: ((Lifecycle) children[i]).stop();
3343: }
3344:
3345: // Stop our Mappers, if any
3346: Mapper mappers[] = findMappers();
3347: for (int i = 0; i < mappers.length; i++) {
3348: if (mappers[(mappers.length - 1) - i] instanceof Lifecycle)
3349: ((Lifecycle) mappers[(mappers.length - 1) - i])
3350: .stop();
3351: }
3352:
3353: // Stop our application listeners
3354: listenerStop();
3355:
3356: // Stop our subordinate components, if any
3357: if (resources != null) {
3358: if (resources instanceof Lifecycle) {
3359: ((Lifecycle) resources).stop();
3360: } else if (resources instanceof ProxyDirContext) {
3361: DirContext dirContext = ((ProxyDirContext) resources)
3362: .getDirContext();
3363: if (dirContext != null) {
3364: if (debug >= 1) {
3365: log("Releasing document base " + docBase);
3366: }
3367: if (dirContext instanceof BaseDirContext) {
3368: ((BaseDirContext) dirContext).release();
3369: if ((dirContext instanceof WARDirContext)
3370: || (dirContext instanceof FileDirContext)) {
3371: resources = null;
3372: }
3373: } else {
3374: log("Cannot release " + resources);
3375: }
3376: }
3377: }
3378: }
3379: if ((realm != null) && (realm instanceof Lifecycle)) {
3380: ((Lifecycle) realm).stop();
3381: }
3382: if ((cluster != null) && (cluster instanceof Lifecycle)) {
3383: ((Lifecycle) cluster).stop();
3384: }
3385: if ((logger != null) && (logger instanceof Lifecycle)) {
3386: ((Lifecycle) logger).stop();
3387: }
3388: if ((loader != null) && (loader instanceof Lifecycle)) {
3389: ((Lifecycle) loader).stop();
3390: }
3391:
3392: } finally {
3393:
3394: // Unbinding thread
3395: unbindThread(oldCCL);
3396:
3397: }
3398:
3399: // Reset application context
3400: context = null;
3401:
3402: // Notify our interested LifecycleListeners
3403: lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
3404:
3405: if (debug >= 1)
3406: log("Stopping complete");
3407:
3408: }
3409:
3410: /**
3411: * Return a String representation of this component.
3412: */
3413: public String toString() {
3414:
3415: StringBuffer sb = new StringBuffer();
3416: if (getParent() != null) {
3417: sb.append(getParent().toString());
3418: sb.append(".");
3419: }
3420: sb.append("StandardContext[");
3421: sb.append(getName());
3422: sb.append("]");
3423: return (sb.toString());
3424:
3425: }
3426:
3427: // ------------------------------------------------------ Protected Methods
3428:
3429: /**
3430: * Add a default Mapper implementation if none have been configured
3431: * explicitly.
3432: *
3433: * @param mapperClass Java class name of the default Mapper
3434: */
3435: protected void addDefaultMapper(String mapperClass) {
3436:
3437: super .addDefaultMapper(this .mapperClass);
3438:
3439: }
3440:
3441: /**
3442: * Adjust the URL pattern to begin with a leading slash, if appropriate
3443: * (i.e. we are running a servlet 2.2 application). Otherwise, return
3444: * the specified URL pattern unchanged.
3445: *
3446: * @param urlPattern The URL pattern to be adjusted (if needed)
3447: * and returned
3448: */
3449: protected String adjustURLPattern(String urlPattern) {
3450:
3451: if (urlPattern == null)
3452: return (urlPattern);
3453: if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
3454: return (urlPattern);
3455: if (!isServlet22())
3456: return (urlPattern);
3457: log(sm.getString("standardContext.urlPattern.patternWarning",
3458: urlPattern));
3459: return ("/" + urlPattern);
3460:
3461: }
3462:
3463: /**
3464: * Are we processing a version 2.2 deployment descriptor?
3465: */
3466: protected boolean isServlet22() {
3467:
3468: if (this .publicId == null)
3469: return (false);
3470: if (this .publicId
3471: .equals(org.apache.catalina.startup.Constants.WebDtdPublicId_22))
3472: return (true);
3473: else
3474: return (false);
3475:
3476: }
3477:
3478: /**
3479: * Return a File object representing the base directory for the
3480: * entire servlet container (i.e. the Engine container if present).
3481: */
3482: protected File engineBase() {
3483:
3484: return (new File(System.getProperty("catalina.base")));
3485:
3486: }
3487:
3488: // -------------------------------------------------------- Private Methods
3489:
3490: /**
3491: * Bind current thread, both for CL purposes and for JNDI ENC support
3492: * during : startup, shutdown and realoading of the context.
3493: *
3494: * @return the previous context class loader
3495: */
3496: private ClassLoader bindThread() {
3497:
3498: ClassLoader oldContextClassLoader = Thread.currentThread()
3499: .getContextClassLoader();
3500:
3501: if (getResources() == null)
3502: return oldContextClassLoader;
3503:
3504: Thread.currentThread().setContextClassLoader(
3505: getLoader().getClassLoader());
3506:
3507: DirContextURLStreamHandler.bind(getResources());
3508:
3509: if (isUseNaming()) {
3510: try {
3511: ContextBindings.bindThread(this , this );
3512: } catch (NamingException e) {
3513: // Silent catch, as this is a normal case during the early
3514: // startup stages
3515: }
3516: }
3517:
3518: return oldContextClassLoader;
3519:
3520: }
3521:
3522: /**
3523: * Unbind thread.
3524: */
3525: private void unbindThread(ClassLoader oldContextClassLoader) {
3526:
3527: Thread.currentThread().setContextClassLoader(
3528: oldContextClassLoader);
3529:
3530: oldContextClassLoader = null;
3531:
3532: if (isUseNaming()) {
3533: ContextBindings.unbindThread(this , this );
3534: }
3535:
3536: DirContextURLStreamHandler.unbind();
3537:
3538: }
3539:
3540: /**
3541: * Get base path.
3542: */
3543: private String getBasePath() {
3544: String docBase = null;
3545: Container container = this ;
3546: while (container != null) {
3547: if (container instanceof Host)
3548: break;
3549: container = container.getParent();
3550: }
3551: if (container == null) {
3552: docBase = (new File(engineBase(), getDocBase())).getPath();
3553: } else {
3554: File file = new File(getDocBase());
3555: if (!file.isAbsolute()) {
3556: // Use the "appBase" property of this container
3557: String appBase = ((Host) container).getAppBase();
3558: file = new File(appBase);
3559: if (!file.isAbsolute())
3560: file = new File(engineBase(), appBase);
3561: docBase = (new File(file, getDocBase())).getPath();
3562: } else {
3563: docBase = file.getPath();
3564: }
3565: }
3566: return docBase;
3567: }
3568:
3569: /**
3570: * Get naming context full name.
3571: */
3572: private String getNamingContextName() {
3573: if (namingContextName == null) {
3574: Container parent = getParent();
3575: if (parent == null) {
3576: namingContextName = getName();
3577: } else {
3578: Stack stk = new Stack();
3579: StringBuffer buff = new StringBuffer();
3580: while (parent != null) {
3581: stk.push(parent.getName());
3582: parent = parent.getParent();
3583: }
3584: while (!stk.empty()) {
3585: buff.append("/" + stk.pop());
3586: }
3587: buff.append(getName());
3588: namingContextName = buff.toString();
3589: }
3590: }
3591: return namingContextName;
3592: }
3593:
3594: /**
3595: * Return the request processing paused flag for this Context.
3596: */
3597: private boolean getPaused() {
3598:
3599: return (this .paused);
3600:
3601: }
3602:
3603: /**
3604: * Post a copy of our web application resources as a servlet context
3605: * attribute.
3606: */
3607: private void postResources() {
3608:
3609: getServletContext().setAttribute(Globals.RESOURCES_ATTR,
3610: getResources());
3611:
3612: }
3613:
3614: /**
3615: * Post a copy of our current list of welcome files as a servlet context
3616: * attribute, so that the default servlet can find them.
3617: */
3618: private void postWelcomeFiles() {
3619:
3620: getServletContext().setAttribute(
3621: "org.apache.catalina.WELCOME_FILES", welcomeFiles);
3622:
3623: }
3624:
3625: /**
3626: * Set the appropriate context attribute for our work directory.
3627: */
3628: private void postWorkDirectory() {
3629:
3630: // Acquire (or calculate) the work directory path
3631: String workDir = getWorkDir();
3632: if (workDir == null) {
3633:
3634: // Retrieve our parent (normally a host) name
3635: String hostName = null;
3636: String engineName = null;
3637: String hostWorkDir = null;
3638: Container parentHost = getParent();
3639: if (parentHost != null) {
3640: hostName = parentHost.getName();
3641: if (parentHost instanceof StandardHost) {
3642: hostWorkDir = ((StandardHost) parentHost)
3643: .getWorkDir();
3644: }
3645: Container parentEngine = parentHost.getParent();
3646: if (parentEngine != null) {
3647: engineName = parentEngine.getName();
3648: }
3649: }
3650: if ((hostName == null) || (hostName.length() < 1))
3651: hostName = "_";
3652: if ((engineName == null) || (engineName.length() < 1))
3653: engineName = "_";
3654:
3655: String temp = getPath();
3656: if (temp.startsWith("/"))
3657: temp = temp.substring(1);
3658: temp = temp.replace('/', '_');
3659: temp = temp.replace('\\', '_');
3660: if (temp.length() < 1)
3661: temp = "_";
3662: if (hostWorkDir != null) {
3663: workDir = hostWorkDir + File.separator + temp;
3664: } else {
3665: workDir = "work" + File.separator + engineName
3666: + File.separator + hostName + File.separator
3667: + temp;
3668: }
3669: setWorkDir(workDir);
3670: }
3671:
3672: // Create this directory if necessary
3673: File dir = new File(workDir);
3674: if (!dir.isAbsolute()) {
3675: File catalinaHome = new File(System
3676: .getProperty("catalina.base"));
3677: String catalinaHomePath = null;
3678: try {
3679: catalinaHomePath = catalinaHome.getCanonicalPath();
3680: dir = new File(catalinaHomePath, workDir);
3681: } catch (IOException e) {
3682: }
3683: }
3684: dir.mkdirs();
3685:
3686: // Set the appropriate servlet context attribute
3687: getServletContext().setAttribute(Globals.WORK_DIR_ATTR, dir);
3688: if (getServletContext() instanceof ApplicationContext)
3689: ((ApplicationContext) getServletContext())
3690: .setAttributeReadOnly(Globals.WORK_DIR_ATTR);
3691:
3692: }
3693:
3694: /**
3695: * Set the request processing paused flag for this Context.
3696: *
3697: * @param paused The new request processing paused flag
3698: */
3699: private void setPaused(boolean paused) {
3700:
3701: this .paused = paused;
3702:
3703: }
3704:
3705: /**
3706: * Validate the syntax of a proposed <code><url-pattern></code>
3707: * for conformance with specification requirements.
3708: *
3709: * @param urlPattern URL pattern to be validated
3710: */
3711: private boolean validateURLPattern(String urlPattern) {
3712:
3713: if (urlPattern == null)
3714: return (false);
3715: if (urlPattern.startsWith("*.")) {
3716: if (urlPattern.indexOf('/') < 0)
3717: return (true);
3718: else
3719: return (false);
3720: }
3721: if (urlPattern.startsWith("/"))
3722: return (true);
3723: else
3724: return (false);
3725:
3726: }
3727:
3728: }
|