e.g. Calendar Search Help
You must enter a value before pressing Search
tomcat

Class: org.apache.catalina.core.StandardContext   ©

 OK to copy?
0001 /*
0002  * Copyright 1999,2004 The Apache Software Foundation.
0003  * 
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  * 
0008  *      http://www.apache.org/licenses/LICENSE-2.0
0009  * 
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  */
0016 
0017 
0018 package org.apache.catalina.core;
0019 
0020 
0021 import java.io.BufferedReader;
0022 import java.io.File;
0023 import java.io.FileInputStream;
0024 import java.io.FileOutputStream;
0025 import java.io.IOException;
0026 import java.io.InputStream;
0027 import java.io.InputStreamReader;
0028 import java.io.ObjectOutputStream;
0029 import java.io.Serializable;
0030 import java.util.ArrayList;
0031 import java.util.HashMap;
0032 import java.util.Hashtable;
0033 import java.util.Iterator;
0034 import java.util.Stack;
0035 import java.util.TreeMap;
0036 
0037 import javax.management.ListenerNotFoundException;
0038 import javax.management.MBeanNotificationInfo;
0039 import javax.management.MBeanRegistrationException;
0040 import javax.management.MBeanServer;
0041 import javax.management.MalformedObjectNameException;
0042 import javax.management.Notification;
0043 import javax.management.NotificationBroadcasterSupport;
0044 import javax.management.NotificationEmitter;
0045 import javax.management.NotificationFilter;
0046 import javax.management.NotificationListener;
0047 import javax.management.ObjectName;
0048 import javax.naming.NamingException;
0049 import javax.naming.directory.DirContext;
0050 import javax.servlet.FilterConfig;
0051 import javax.servlet.ServletContext;
0052 import javax.servlet.ServletContextAttributeListener;
0053 import javax.servlet.ServletContextEvent;
0054 import javax.servlet.ServletContextListener;
0055 import javax.servlet.ServletException;
0056 import javax.servlet.ServletRequestAttributeListener;
0057 import javax.servlet.ServletRequestListener;
0058 import javax.servlet.http.HttpSessionAttributeListener;
0059 import javax.servlet.http.HttpSessionListener;
0060 
0061 import org.apache.catalina.Container;
0062 import org.apache.catalina.ContainerListener;
0063 import org.apache.catalina.Context;
0064 import org.apache.catalina.Engine;
0065 import org.apache.catalina.Globals;
0066 import org.apache.catalina.Host;
0067 import org.apache.catalina.InstanceListener;
0068 import org.apache.catalina.Lifecycle;
0069 import org.apache.catalina.LifecycleException;
0070 import org.apache.catalina.LifecycleListener;
0071 import org.apache.catalina.Loader;
0072 import org.apache.catalina.Wrapper;
0073 import org.apache.catalina.deploy.ApplicationParameter;
0074 import org.apache.catalina.deploy.ErrorPage;
0075 import org.apache.catalina.deploy.FilterDef;
0076 import org.apache.catalina.deploy.FilterMap;
0077 import org.apache.catalina.deploy.LoginConfig;
0078 import org.apache.catalina.deploy.MessageDestination;
0079 import org.apache.catalina.deploy.MessageDestinationRef;
0080 import org.apache.catalina.deploy.NamingResources;
0081 import org.apache.catalina.deploy.SecurityCollection;
0082 import org.apache.catalina.deploy.SecurityConstraint;
0083 import org.apache.catalina.loader.WebappLoader;
0084 import org.apache.catalina.startup.ContextConfig;
0085 import org.apache.catalina.startup.TldConfig;
0086 import org.apache.catalina.util.CharsetMapper;
0087 import org.apache.catalina.util.ExtensionValidator;
0088 import org.apache.catalina.util.RequestUtil;
0089 import org.apache.commons.logging.Log;
0090 import org.apache.commons.logging.LogFactory;
0091 import org.apache.commons.modeler.Registry;
0092 import org.apache.naming.ContextBindings;
0093 import org.apache.naming.resources.BaseDirContext;
0094 import org.apache.naming.resources.DirContextURLStreamHandler;
0095 import org.apache.naming.resources.FileDirContext;
0096 import org.apache.naming.resources.ProxyDirContext;
0097 import org.apache.naming.resources.WARDirContext;
0098 import org.apache.tomcat.util.compat.JdkCompat;
0099 
0100 /**
0101  * Standard implementation of the <b>Context</b> interface.  Each
0102  * child container must be a Wrapper implementation to process the
0103  * requests directed to a particular servlet.
0104  *
0105  * @author Craig R. McClanahan
0106  * @author Remy Maucherat
0107  * @version $Revision: 1.140 $ $Date: 2004/08/16 09:31:06 $
0108  */
0109 
0110 public class StandardContext
0111     extends ContainerBase
0112     implements Context, Serializable, NotificationEmitter
0113 {
0114     private static transient Log log = LogFactory.getLog(StandardContext.class);
0115 
0116 
0117     // ----------------------------------------------------------- Constructors
0118 
0119 
0120     /**
0121      * Create a new StandardContext component with the default basic Valve.
0122      */
0123     public StandardContext() {
0124 
0125         super();
0126         pipeline.setBasic(new StandardContextValve());
0127         broadcaster = new NotificationBroadcasterSupport();
0128 
0129     }
0130 
0131 
0132     // ----------------------------------------------------- Class Variables
0133 
0134 
0135     /**
0136      * The descriptive information string for this implementation.
0137      */
0138     private static final String info =
0139         "org.apache.catalina.core.StandardContext/1.0";
0140 
0141 
0142     /**
0143      * JDK compatibility support
0144      */
0145     private static final JdkCompat jdkCompat = JdkCompat.getJdkCompat();
0146 
0147 
0148     // ----------------------------------------------------- Instance Variables
0149 
0150 
0151     /**
0152      * The alternate deployment descriptor name.
0153      */
0154     private String altDDName = null;
0155 
0156 
0157     /**
0158      * Associated host name.
0159      */
0160     private String hostName;
0161 
0162 
0163     /**
0164      * The antiJARLocking flag for this Context.
0165      */
0166     private boolean antiJARLocking = false;
0167 
0168     
0169     /**
0170      * The antiResourceLocking flag for this Context.
0171      */
0172     private boolean antiResourceLocking = false;
0173 
0174     
0175     /**
0176      * The set of application listener class names configured for this
0177      * application, in the order they were encountered in the web.xml file.
0178      */
0179     private String applicationListeners[] = new String[0];
0180 
0181 
0182     /**
0183      * The set of instantiated application event listener objects</code>.
0184      */
0185     private transient Object applicationEventListenersObjects[] = 
0186         new Object[0];
0187 
0188 
0189     /**
0190      * The set of instantiated application lifecycle listener objects</code>.
0191      */
0192     private transient Object applicationLifecycleListenersObjects[] = 
0193         new Object[0];
0194 
0195 
0196     /**
0197      * The set of application parameters defined for this application.
0198      */
0199     private ApplicationParameter applicationParameters[] =
0200         new ApplicationParameter[0];
0201 
0202 
0203     /**
0204      * The application available flag for this Context.
0205      */
0206     private boolean available = false;
0207     
0208     /**
0209      * The broadcaster that sends j2ee notifications. 
0210      */
0211     private NotificationBroadcasterSupport broadcaster = null;
0212     
0213     /**
0214      * The Locale to character set mapper for this application.
0215      */
0216     private transient CharsetMapper charsetMapper = null;
0217 
0218 
0219     /**
0220      * The Java class name of the CharsetMapper class to be created.
0221      */
0222     private String charsetMapperClass =
0223       "org.apache.catalina.util.CharsetMapper";
0224 
0225 
0226     /**
0227      * The path to a file to save this Context information.
0228      */
0229     private String configFile = null;
0230 
0231 
0232     /**
0233      * The "correctly configured" flag for this Context.
0234      */
0235     private boolean configured = false;
0236 
0237 
0238     /**
0239      * The security constraints for this web application.
0240      */
0241     private SecurityConstraint constraints[] = new SecurityConstraint[0];
0242 
0243 
0244     /**
0245      * The ServletContext implementation associated with this Context.
0246      */
0247     private transient ApplicationContext context = null;
0248 
0249 
0250     /**
0251      * Compiler classpath to use.
0252      */
0253     private String compilerClasspath = null;
0254 
0255 
0256     /**
0257      * Should we attempt to use cookies for session id communication?
0258      */
0259     private boolean cookies = true;
0260 
0261 
0262     /**
0263      * Should we allow the <code>ServletContext.getContext()</code> method
0264      * to access the context of other web applications in this server?
0265      */
0266     private boolean crossContext = false;
0267 
0268 
0269     /**
0270      * The "follow standard delegation model" flag that will be used to
0271      * configure our ClassLoader.
0272      */
0273     private boolean delegate = false;
0274 
0275 
0276      /**
0277      * The display name of this web application.
0278      */
0279     private String displayName = null;
0280 
0281 
0282     /** 
0283      * Override the default web xml location. ContextConfig is not configurable
0284      * so the setter is not used.
0285      */
0286     private String defaultWebXml;
0287 
0288 
0289     /**
0290      * The distributable flag for this web application.
0291      */
0292     private boolean distributable = false;
0293 
0294 
0295     /**
0296      * The document root for this web application.
0297      */
0298     private String docBase = null;
0299 
0300 
0301     /**
0302      * The exception pages for this web application, keyed by fully qualified
0303      * class name of the Java exception.
0304      */
0305     private HashMap exceptionPages = new HashMap();
0306 
0307 
0308     /**
0309      * The set of filter configurations (and associated filter instances) we
0310      * have initialized, keyed by filter name.
0311      */
0312     private HashMap filterConfigs = new HashMap();
0313 
0314 
0315     /**
0316      * The set of filter definitions for this application, keyed by
0317      * filter name.
0318      */
0319     private HashMap filterDefs = new HashMap();
0320 
0321 
0322     /**
0323      * The set of filter mappings for this application, in the order
0324      * they were defined in the deployment descriptor.
0325      */
0326     private FilterMap filterMaps[] = new FilterMap[0];
0327 
0328 
0329     /**
0330      * The set of classnames of InstanceListeners that will be added
0331      * to each newly created Wrapper by <code>createWrapper()</code>.
0332      */
0333     private String instanceListeners[] = new String[0];
0334 
0335 
0336     /**
0337      * The login configuration descriptor for this web application.
0338      */
0339     private LoginConfig loginConfig = null;
0340 
0341 
0342     /**
0343      * The mapper associated with this context.
0344      */
0345     private org.apache.tomcat.util.http.mapper.Mapper mapper = 
0346         new org.apache.tomcat.util.http.mapper.Mapper();
0347 
0348 
0349     /**
0350      * The naming context listener for this web application.
0351      */
0352     private transient NamingContextListener namingContextListener = null;
0353 
0354 
0355     /**
0356      * The naming resources for this web application.
0357      */
0358     private NamingResources namingResources = null;
0359 
0360 
0361     /**
0362      * The message destinations for this web application.
0363      */
0364     private HashMap messageDestinations = new HashMap();
0365 
0366 
0367     /**
0368      * The MIME mappings for this web application, keyed by extension.
0369      */
0370     private HashMap mimeMappings = new HashMap();
0371 
0372 
0373      /**
0374       * Special case: error page for status 200.
0375       */
0376      private ErrorPage okErrorPage = null;
0377 
0378 
0379     /**
0380      * The context initialization parameters for this web application,
0381      * keyed by name.
0382      */
0383     private HashMap parameters = new HashMap();
0384 
0385 
0386     /**
0387      * The request processing pause flag (while reloading occurs)
0388      */
0389     private boolean paused = false;
0390 
0391 
0392     /**
0393      * The public identifier of the DTD for the web application deployment
0394      * descriptor version we are currently parsing.  This is used to support
0395      * relaxed validation rules when processing version 2.2 web.xml files.
0396      */
0397     private String publicId = null;
0398 
0399 
0400     /**
0401      * The reloadable flag for this web application.
0402      */
0403     private boolean reloadable = false;
0404 
0405 
0406     /**
0407      * Unpack WAR property.
0408      */
0409     private boolean unpackWAR = true;
0410 
0411 
0412     /**
0413      * The DefaultContext override flag for this web application.
0414      */
0415     private boolean override = false;
0416 
0417 
0418     /**
0419      * The privileged flag for this web application.
0420      */
0421     private boolean privileged = false;
0422 
0423 
0424     /**
0425      * Should the next call to <code>addWelcomeFile()</code> cause replacement
0426      * of any existing welcome files?  This will be set before processing the
0427      * web application's deployment descriptor, so that application specified
0428      * choices <strong>replace</strong>, rather than append to, those defined
0429      * in the global descriptor.
0430      */
0431     private boolean replaceWelcomeFiles = false;
0432 
0433 
0434     /**
0435      * The security role mappings for this application, keyed by role
0436      * name (as used within the application).
0437      */
0438     private HashMap roleMappings = new HashMap();
0439 
0440 
0441     /**
0442      * The security roles for this application, keyed by role name.
0443      */
0444     private String securityRoles[] = new String[0];
0445 
0446 
0447     /**
0448      * The servlet mappings for this web application, keyed by
0449      * matching pattern.
0450      */
0451     private HashMap servletMappings = new HashMap();
0452 
0453 
0454     /**
0455      * The session timeout (in minutes) for this web application.
0456      */
0457     private int sessionTimeout = 30;
0458 
0459     /**
0460      * The notification sequence number.
0461      */
0462     private long sequenceNumber = 0;
0463     
0464     /**
0465      * The status code error pages for this web application, keyed by
0466      * HTTP status code (as an Integer).
0467      */
0468     private HashMap statusPages = new HashMap();
0469 
0470 
0471     /**
0472      * Set flag to true to cause the system.out and system.err to be redirected
0473      * to the logger when executing a servlet.
0474      */
0475     private boolean swallowOutput = false;
0476 
0477 
0478     /**
0479      * The JSP tag libraries for this web application, keyed by URI
0480      */
0481     private HashMap taglibs = new HashMap();
0482 
0483 
0484     /**
0485      * The watched resources for this application.
0486      */
0487     private String watchedResources[] = new String[0];
0488 
0489 
0490     /**
0491      * The welcome files for this application.
0492      */
0493     private String welcomeFiles[] = new String[0];
0494 
0495 
0496     /**
0497      * The set of classnames of LifecycleListeners that will be added
0498      * to each newly created Wrapper by <code>createWrapper()</code>.
0499      */
0500     private String wrapperLifecycles[] = new String[0];
0501 
0502 
0503     /**
0504      * The set of classnames of ContainerListeners that will be added
0505      * to each newly created Wrapper by <code>createWrapper()</code>.
0506      */
0507     private String wrapperListeners[] = new String[0];
0508 
0509 
0510     /**
0511      * The pathname to the work directory for this context (relative to
0512      * the server's home if not absolute).
0513      */
0514     private String workDir = null;
0515 
0516 
0517     /**
0518      * Java class name of the Wrapper class implementation we use.
0519      */
0520     private String wrapperClass = "org.apache.catalina.core.StandardWrapper";
0521 
0522 
0523     /**
0524      * JNDI use flag.
0525      */
0526     private boolean useNaming = true;
0527 
0528 
0529     /**
0530      * Filesystem based flag.
0531      */
0532     private boolean filesystemBased = false;
0533 
0534 
0535     /**
0536      * Name of the associated naming context.
0537      */
0538     private String namingContextName = null;
0539 
0540 
0541     /**
0542      * Frequency of the session expiration, and related manager operations.
0543      * Manager operations will be done once for the specified amount of
0544      * backgrondProcess calls (ie, the lower the amount, the most often the
0545      * checks will occur).
0546      */
0547     private int managerChecksFrequency = 6;
0548 
0549 
0550     /**
0551      * Iteration count for background processing.
0552      */
0553     private int count = 0;
0554 
0555 
0556     /**
0557      * Caching allowed flag.
0558      */
0559     private boolean cachingAllowed = true;
0560 
0561 
0562     /**
0563      * Case sensitivity.
0564      */
0565     protected boolean caseSensitive = true;
0566 
0567 
0568     /**
0569      * Allow linking.
0570      */
0571     protected boolean allowLinking = false;
0572 
0573 
0574     /**
0575      * Cache max size in KB.
0576      */
0577     protected int cacheMaxSize = 10240; // 10 MB
0578 
0579 
0580     /**
0581      * Cache TTL in ms.
0582      */
0583     protected int cacheTTL = 5000;
0584 
0585 
0586     private boolean lazy=true;
0587 
0588     /**
0589      * Non proxied resources.
0590      */
0591     private transient DirContext webappResources = null;
0592 
0593     private long startupTime;
0594     private long startTime;
0595     private long tldScanTime;
0596 
0597     /** 
0598      * Name of the engine. If null, the domain is used.
0599      */ 
0600     private String engineName = null;
0601     private String j2EEApplication="none";
0602     private String j2EEServer="none";
0603 
0604 
0605     /**
0606      * Attribute value used to turn on/off XML validation
0607      */
0608      private boolean webXmlValidation = false;
0609 
0610 
0611     /**
0612      * Attribute value used to turn on/off XML namespace validation
0613      */
0614      private boolean webXmlNamespaceAware = false;
0615 
0616 
0617     /**
0618      * Attribute value used to turn on/off XML validation
0619      */
0620      private boolean tldValidation = false;
0621 
0622 
0623     /**
0624      * Attribute value used to turn on/off TLD XML namespace validation
0625      */
0626      private boolean tldNamespaceAware = false;
0627 
0628 
0629     /**
0630      * Should we save the configuration.
0631      */
0632     private boolean saveConfig = true;
0633 
0634 
0635     // ----------------------------------------------------- Context Properties
0636 
0637     public void setName( String name ) {
0638         super.setName( name );
0639     }
0640 
0641 
0642     /**
0643      * Is caching allowed ?
0644      */
0645     public boolean isCachingAllowed() {
0646         return cachingAllowed;
0647     }
0648 
0649 
0650     /**
0651      * Set caching allowed flag.
0652      */
0653     public void setCachingAllowed(boolean cachingAllowed) {
0654         this.cachingAllowed = cachingAllowed;
0655     }
0656 
0657 
0658     /**
0659      * Set case sensitivity.
0660      */
0661     public void setCaseSensitive(boolean caseSensitive) {
0662         this.caseSensitive = caseSensitive;
0663     }
0664 
0665 
0666     /**
0667      * Is case sensitive ?
0668      */
0669     public boolean isCaseSensitive() {
0670         return caseSensitive;
0671     }
0672 
0673 
0674     /**
0675      * Set allow linking.
0676      */
0677     public void setAllowLinking(boolean allowLinking) {
0678         this.allowLinking = allowLinking;
0679     }
0680 
0681 
0682     /**
0683      * Is linking allowed.
0684      */
0685     public boolean isAllowLinking() {
0686         return allowLinking;
0687     }
0688 
0689 
0690     /**
0691      * Set cache TTL.
0692      */
0693     public void setCacheTTL(int cacheTTL) {
0694         this.cacheTTL = cacheTTL;
0695     }
0696 
0697 
0698     /**
0699      * Get cache TTL.
0700      */
0701     public int getCacheTTL() {
0702         return cacheTTL;
0703     }
0704 
0705 
0706     /**
0707      * Return the maximum size of the cache in KB.
0708      */
0709     public int getCacheMaxSize() {
0710         return cacheMaxSize;
0711     }
0712 
0713 
0714     /**
0715      * Set the maximum size of the cache in KB.
0716      */
0717     public void setCacheMaxSize(int cacheMaxSize) {
0718         this.cacheMaxSize = cacheMaxSize;
0719     }
0720 
0721 
0722     /**
0723      * Return the "follow standard delegation model" flag used to configure
0724      * our ClassLoader.
0725      */
0726     public boolean getDelegate() {
0727 
0728         return (this.delegate);
0729 
0730     }
0731 
0732 
0733     /**
0734      * Set the "follow standard delegation model" flag used to configure
0735      * our ClassLoader.
0736      *
0737      * @param delegate The new flag
0738      */
0739     public void setDelegate(boolean delegate) {
0740 
0741         boolean oldDelegate = this.delegate;
0742         this.delegate = delegate;
0743         support.firePropertyChange("delegate", new Boolean(oldDelegate),
0744                                    new Boolean(this.delegate));
0745 
0746     }
0747 
0748 
0749     /**
0750      * Returns true if the internal naming support is used.
0751      */
0752     public boolean isUseNaming() {
0753 
0754         return (useNaming);
0755 
0756     }
0757 
0758 
0759     /**
0760      * Enables or disables naming.
0761      */
0762     public void setUseNaming(boolean useNaming) {
0763         this.useNaming = useNaming;
0764     }
0765 
0766 
0767     /**
0768      * Returns true if the resources associated with this context are
0769      * filesystem based.
0770      */
0771     public boolean isFilesystemBased() {
0772 
0773         return (filesystemBased);
0774 
0775     }
0776 
0777 
0778     /**
0779      * Return the set of initialized application event listener objects,
0780      * in the order they were specified in the web application deployment
0781      * descriptor, for this application.
0782      *
0783      * @exception IllegalStateException if this method is called before
0784      *  this application has started, or after it has been stopped
0785      */
0786     public Object[] getApplicationEventListeners() {
0787         return (applicationEventListenersObjects);
0788     }
0789 
0790 
0791     /**
0792      * Store the set of initialized application event listener objects,
0793      * in the order they were specified in the web application deployment
0794      * descriptor, for this application.
0795      *
0796      * @param listeners The set of instantiated listener objects.
0797      */
0798     public void setApplicationEventListeners(Object listeners[]) {
0799         applicationEventListenersObjects = listeners;
0800     }
0801 
0802 
0803     /**
0804      * Return the set of initialized application lifecycle listener objects,
0805      * in the order they were specified in the web application deployment
0806      * descriptor, for this application.
0807      *
0808      * @exception IllegalStateException if this method is called before
0809      *  this application has started, or after it has been stopped
0810      */
0811     public Object[] getApplicationLifecycleListeners() {
0812         return (applicationLifecycleListenersObjects);
0813     }
0814 
0815 
0816     /**
0817      * Store the set of initialized application lifecycle listener objects,
0818      * in the order they were specified in the web application deployment
0819      * descriptor, for this application.
0820      *
0821      * @param listeners The set of instantiated listener objects.
0822      */
0823     public void setApplicationLifecycleListeners(Object listeners[]) {
0824         applicationLifecycleListenersObjects = listeners;
0825     }
0826 
0827 
0828     /**
0829      * Return the antiJARLocking flag for this Context.
0830      */
0831     public boolean getAntiJARLocking() {
0832 
0833         return (this.antiJARLocking);
0834 
0835     }
0836 
0837 
0838     /**
0839      * Return the antiResourceLocking flag for this Context.
0840      */
0841     public boolean getAntiResourceLocking() {
0842 
0843         return (this.antiResourceLocking);
0844 
0845     }
0846 
0847 
0848     /**
0849      * Set the application available flag for this Context.
0850      *
0851      * @param available The new application available flag
0852      */
0853     public void setAntiJARLocking(boolean antiJARLocking) {
0854 
0855         boolean oldAntiJARLocking = this.antiJARLocking;
0856         this.antiJARLocking = antiJARLocking;
0857         support.firePropertyChange("antiJARLocking",
0858                                    new Boolean(oldAntiJARLocking),
0859                                    new Boolean(this.antiJARLocking));
0860 
0861     }
0862 
0863 
0864     /**
0865      * Set the application available flag for this Context.
0866      *
0867      * @param available The new application available flag
0868      */
0869     public void setAntiResourceLocking(boolean antiResourceLocking) {
0870 
0871         boolean oldAntiResourceLocking = this.antiResourceLocking;
0872         this.antiResourceLocking = antiResourceLocking;
0873         support.firePropertyChange("antiResourceLocking",
0874                                    new Boolean(oldAntiResourceLocking),
0875                                    new Boolean(this.antiResourceLocking));
0876 
0877     }
0878 
0879 
0880     /**
0881      * Return the application available flag for this Context.
0882      */
0883     public boolean getAvailable() {
0884 
0885         return (this.available);
0886 
0887     }
0888 
0889 
0890     /**
0891      * Set the application available flag for this Context.
0892      *
0893      * @param available The new application available flag
0894      */
0895     public void setAvailable(boolean available) {
0896 
0897         boolean oldAvailable = this.available;
0898         this.available = available;
0899         support.firePropertyChange("available",
0900                                    new Boolean(oldAvailable),
0901                                    new Boolean(this.available));
0902 
0903     }
0904 
0905 
0906     /**
0907      * Return the Locale to character set mapper for this Context.
0908      */
0909     public CharsetMapper getCharsetMapper() {
0910 
0911         // Create a mapper the first time it is requested
0912         if (this.charsetMapper == null) {
0913             try {
0914                 Class clazz = Class.forName(charsetMapperClass);
0915                 this.charsetMapper =
0916                   (CharsetMapper) clazz.newInstance();
0917             } catch (Throwable t) {
0918                 this.charsetMapper = new CharsetMapper();
0919             }
0920         }
0921 
0922         return (this.charsetMapper);
0923 
0924     }
0925 
0926 
0927     /**
0928      * Set the Locale to character set mapper for this Context.
0929      *
0930      * @param mapper The new mapper
0931      */
0932     public void setCharsetMapper(CharsetMapper mapper) {
0933 
0934         CharsetMapper oldCharsetMapper = this.charsetMapper;
0935         this.charsetMapper = mapper;
0936         if( mapper != null )
0937             this.charsetMapperClass= mapper.getClass().getName();
0938         support.firePropertyChange("charsetMapper", oldCharsetMapper,
0939                                    this.charsetMapper);
0940 
0941     }
0942 
0943     /**
0944      * Return the path to a file to save this Context information.
0945      */
0946     public String getConfigFile() {
0947 
0948         return (this.configFile);
0949 
0950     }
0951 
0952 
0953     /**
0954      * Set the path to a file to save this Context information.
0955      *
0956      * @param configFile The path to a file to save this Context information.
0957      */
0958     public void setConfigFile(String configFile) {
0959 
0960         this.configFile = configFile;
0961     }
0962 
0963 
0964     /**
0965      * Return the "correctly configured" flag for this Context.
0966      */
0967     public boolean getConfigured() {
0968 
0969         return (this.configured);
0970 
0971     }
0972 
0973 
0974     /**
0975      * Set the "correctly configured" flag for this Context.  This can be
0976      * set to false by startup listeners that detect a fatal configuration
0977      * error to avoid the application from being made available.
0978      *
0979      * @param configured The new correctly configured flag
0980      */
0981     public void setConfigured(boolean configured) {
0982 
0983         boolean oldConfigured = this.configured;
0984         this.configured = configured;
0985         support.firePropertyChange("configured",
0986                                    new Boolean(oldConfigured),
0987                                    new Boolean(this.configured));
0988 
0989     }
0990 
0991 
0992     /**
0993      * Return the "use cookies for session ids" flag.
0994      */
0995     public boolean getCookies() {
0996 
0997         return (this.cookies);
0998 
0999     }
1000 
1001 
1002     /**
1003      * Set the "use cookies for session ids" flag.
1004      *
1005      * @param cookies The new flag
1006      */
1007     public void setCookies(boolean cookies) {
1008 
1009         boolean oldCookies = this.cookies;
1010         this.cookies = cookies;
1011         support.firePropertyChange("cookies",
1012                                    new Boolean(oldCookies),
1013                                    new Boolean(this.cookies));
1014 
1015     }
1016 
1017 
1018     /**
1019      * Return the "allow crossing servlet contexts" flag.
1020      */
1021     public boolean getCrossContext() {
1022 
1023         return (this.crossContext);
1024 
1025     }
1026 
1027 
1028     /**
1029      * Set the "allow crossing servlet contexts" flag.
1030      *
1031      * @param crossContext The new cross contexts flag
1032      */
1033     public void setCrossContext(boolean crossContext) {
1034 
1035         boolean oldCrossContext = this.crossContext;
1036         this.crossContext = crossContext;
1037         support.firePropertyChange("crossContext",
1038                                    new Boolean(oldCrossContext),
1039                                    new Boolean(this.crossContext));
1040 
1041     }
1042 
1043     public String getDefaultWebXml() {
1044         return defaultWebXml;
1045     }
1046 
1047     /** Set the location of the default web xml that will be used.
1048      * If not absolute, it'll be made relative to the engine's base dir
1049      * ( which defaults to catalina.base system property ).
1050      *
1051      * XXX If a file is not found - we can attempt a getResource()
1052      *
1053      * @param defaultWebXml The default web xml 
1054      */
1055     public void setDefaultWebXml(String defaultWebXml) {
1056         this.defaultWebXml = defaultWebXml;
1057     }
1058 
1059     public long getStartupTime() {
1060         return startupTime;
1061     }
1062 
1063     public void setStartupTime(long startupTime) {
1064         this.startupTime = startupTime;
1065     }
1066 
1067     public long getTldScanTime() {
1068         return tldScanTime;
1069     }
1070 
1071     public void setTldScanTime(long tldScanTime) {
1072         this.tldScanTime = tldScanTime;
1073     }
1074 
1075     /**
1076      * Return the display name of this web application.
1077      */
1078     public String getDisplayName() {
1079 
1080         return (this.displayName);
1081 
1082     }
1083 
1084 
1085     /**
1086      * Return the alternate Deployment Descriptor name.
1087      */
1088     public String getAltDDName(){
1089         return altDDName;
1090     }
1091 
1092 
1093     /**
1094      * Set an alternate Deployment Descriptor name.
1095      */
1096     public void setAltDDName(String altDDName) {
1097         this.altDDName = altDDName;
1098         if (context != null) {
1099             context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
1100         }
1101     }
1102 
1103 
1104     /**
1105      * Return the compiler classpath.
1106      */
1107     public String getCompilerClasspath(){
1108         return compilerClasspath;
1109     }
1110 
1111 
1112     /**
1113      * Set the compiler classpath.
1114      */
1115     public void setCompilerClasspath(String compilerClasspath) {
1116         this.compilerClasspath = compilerClasspath;
1117     }
1118 
1119 
1120     /**
1121      * Set the display name of this web application.
1122      *
1123      * @param displayName The new display name
1124      */
1125     public void setDisplayName(String displayName) {
1126 
1127         String oldDisplayName = this.displayName;
1128         this.displayName = displayName;
1129         support.firePropertyChange("displayName", oldDisplayName,
1130                                    this.displayName);
1131     }
1132 
1133 
1134     /**
1135      * Return the distributable flag for this web application.
1136      */
1137     public boolean getDistributable() {
1138 
1139         return (this.distributable);
1140 
1141     }
1142 
1143     /**
1144      * Set the distributable flag for this web application.
1145      *
1146      * @param distributable The new distributable flag
1147      */
1148     public void setDistributable(boolean distributable) {
1149         boolean oldDistributable = this.distributable;
1150         this.distributable = distributable;
1151         support.firePropertyChange("distributable",
1152                                    new Boolean(oldDistributable),
1153                                    new Boolean(this.distributable));
1154     }
1155 
1156 
1157     /**
1158      * Return the document root for this Context.  This can be an absolute
1159      * pathname, a relative pathname, or a URL.
1160      */
1161     public String getDocBase() {
1162 
1163         return (this.docBase);
1164 
1165     }
1166 
1167 
1168     /**
1169      * Set the document root for this Context.  This can be an absolute
1170      * pathname, a relative pathname, or a URL.
1171      *
1172      * @param docBase The new document root
1173      */
1174     public void setDocBase(String docBase) {
1175 
1176         this.docBase = docBase;
1177 
1178     }
1179 
1180     // experimental
1181     public boolean isLazy() {
1182         return lazy;
1183     }
1184 
1185     public void setLazy(boolean lazy) {
1186         this.lazy = lazy;
1187     }
1188 
1189 
1190     /**
1191      * Return the frequency of manager checks.
1192      */
1193     public int getManagerChecksFrequency() {
1194 
1195         return (this.managerChecksFrequency);
1196 
1197     }
1198 
1199 
1200     /**
1201      * Set the manager checks frequency.
1202      *
1203      * @param managerChecksFrequency the new manager checks frequency
1204      */
1205     public void setManagerChecksFrequency(int managerChecksFrequency) {
1206 
1207         if (managerChecksFrequency <= 0) {
1208             return;
1209         }
1210 
1211         int oldManagerChecksFrequency = this.managerChecksFrequency;
1212         this.managerChecksFrequency = managerChecksFrequency;
1213         support.firePropertyChange("managerChecksFrequency",
1214                                    new Integer(oldManagerChecksFrequency),
1215                                    new Integer(this.managerChecksFrequency));
1216 
1217     }
1218 
1219 
1220     /**
1221      * Return descriptive information about this Container implementation and
1222      * the corresponding version number, in the format
1223      * <code>&lt;description&gt;/&lt;version&gt;</code>.
1224      */
1225     public String getInfo() {
1226 
1227         return (info);
1228 
1229     }
1230 
1231     public String getEngineName() {
1232         if( engineName != null ) return engineName;
1233         return domain;
1234     }
1235 
1236     public void setEngineName(String engineName) {
1237         this.engineName = engineName;
1238     }
1239 
1240     public String getJ2EEApplication() {
1241         return j2EEApplication;
1242     }
1243 
1244     public void setJ2EEApplication(String j2EEApplication) {
1245         this.j2EEApplication = j2EEApplication;
1246     }
1247 
1248     public String getJ2EEServer() {
1249         return j2EEServer;
1250     }
1251 
1252     public void setJ2EEServer(String j2EEServer) {
1253         this.j2EEServer = j2EEServer;
1254     }
1255 
1256 
1257     /**
1258      * Set the Loader with which this Context is associated.
1259      *
1260      * @param loader The newly associated loader
1261      */
1262     public synchronized void setLoader(Loader loader) {
1263 
1264         super.setLoader(loader);
1265 
1266     }
1267 
1268 
1269     /**
1270      * Return the login configuration descriptor for this web application.
1271      */
1272     public LoginConfig getLoginConfig() {
1273 
1274         return (this.loginConfig);
1275 
1276     }
1277 
1278 
1279     /**
1280      * Set the login configuration descriptor for this web application.
1281      *
1282      * @param config The new login configuration
1283      */
1284     public void setLoginConfig(LoginConfig config) {
1285 
1286         // Validate the incoming property value
1287         if (config == null)
1288             throw new IllegalArgumentException
1289                 (sm.getString("standardContext.loginConfig.required"));
1290         String loginPage = config.getLoginPage();
1291         if ((loginPage != null) && !loginPage.startsWith("/")) {
1292             if (isServlet22()) {
1293                 log.debug(sm.getString("standardContext.loginConfig.loginWarning",
1294                                  loginPage));
1295                 config.setLoginPage("/" + loginPage);
1296             } else {
1297                 throw new IllegalArgumentException
1298                     (sm.getString("standardContext.loginConfig.loginPage",
1299                                   loginPage));
1300             }
1301         }
1302         String errorPage = config.getErrorPage();
1303         if ((errorPage != null) && !errorPage.startsWith("/")) {
1304             if (isServlet22()) {
1305                 log.debug(sm.getString("standardContext.loginConfig.errorWarning",
1306                                  errorPage));
1307                 config.setErrorPage("/" + errorPage);
1308             } else {
1309                 throw new IllegalArgumentException
1310                     (sm.getString("standardContext.loginConfig.errorPage",
1311                                   errorPage));
1312             }
1313         }
1314 
1315         // Process the property setting change
1316         LoginConfig oldLoginConfig = this.loginConfig;
1317         this.loginConfig = config;
1318         support.firePropertyChange("loginConfig",
1319                                    oldLoginConfig, this.loginConfig);
1320 
1321     }
1322 
1323 
1324     /**
1325      * Get the mapper associated with the context.
1326      */
1327     public org.apache.tomcat.util.http.mapper.Mapper getMapper() {
1328         return (mapper);
1329     }
1330 
1331 
1332     /**
1333      * Return the naming resources associated with this web application.
1334      */
1335     public NamingResources getNamingResources() {
1336 
1337         if (namingResources == null) {
1338             setNamingResources(new NamingResources());
1339         }
1340         return (namingResources);
1341 
1342     }
1343 
1344 
1345     /**
1346      * Set the naming resources for this web application.
1347      *
1348      * @param namingResources The new naming resources
1349      */
1350     public void setNamingResources(NamingResources namingResources) {
1351 
1352         // Process the property setting change
1353         NamingResources oldNamingResources = this.namingResources;
1354         this.namingResources = namingResources;
1355         namingResources.setContainer(this);
1356         support.firePropertyChange("namingResources",
1357                                    oldNamingResources, this.namingResources);
1358 
1359     }
1360 
1361 
1362     /**
1363      * Return the context path for this Context.
1364      */
1365     public String getPath() {
1366 
1367         return (getName());
1368 
1369     }
1370 
1371     
1372     /**
1373      * Set the context path for this Context.
1374      * <p>
1375      * <b>IMPLEMENTATION NOTE</b>:  The context path is used as the "name" of
1376      * a Context, because it must be unique.
1377      *
1378      * @param path The new context path
1379      */
1380     public void setPath(String path) {
1381         // XXX Use host in name
1382         setName(RequestUtil.URLDecode(path));
1383 
1384     }
1385 
1386 
1387     /**
1388      * Return the public identifier of the deployment descriptor DTD that is
1389      * currently being parsed.
1390      */
1391     public String getPublicId() {
1392 
1393         return (this.publicId);
1394 
1395     }
1396 
1397 
1398     /**
1399      * Set the public identifier of the deployment descriptor DTD that is
1400      * currently being parsed.
1401      *
1402      * @param publicId The public identifier
1403      */
1404     public void setPublicId(String publicId) {
1405 
1406         if (log.isDebugEnabled())
1407             log.debug("Setting deployment descriptor public ID to '" +
1408                 publicId + "'");
1409 
1410         String oldPublicId = this.publicId;
1411         this.publicId = publicId;
1412         support.firePropertyChange("publicId", oldPublicId, publicId);
1413 
1414     }
1415 
1416 
1417     /**
1418      * Return the reloadable flag for this web application.
1419      */
1420     public boolean getReloadable() {
1421 
1422         return (this.reloadable);
1423 
1424     }
1425 
1426 
1427     /**
1428      * Return the DefaultContext override flag for this web application.
1429      */
1430     public boolean getOverride() {
1431 
1432         return (this.override);
1433 
1434     }
1435 
1436 
1437     /**
1438      * Return the privileged flag for this web application.
1439      */
1440     public boolean getPrivileged() {
1441 
1442         return (this.privileged);
1443 
1444     }
1445 
1446 
1447     /**
1448      * Set the privileged flag for this web application.
1449      *
1450      * @param privileged The new privileged flag
1451      */
1452     public void setPrivileged(boolean privileged) {
1453 
1454         boolean oldPrivileged = this.privileged;
1455         this.privileged = privileged;
1456         support.firePropertyChange("privileged",
1457                                    new Boolean(oldPrivileged),
1458                                    new Boolean(this.privileged));
1459 
1460     }
1461 
1462 
1463     /**
1464      * Set the reloadable flag for this web application.
1465      *
1466      * @param reloadable The new reloadable flag
1467      */
1468     public void setReloadable(boolean reloadable) {
1469 
1470         boolean oldReloadable = this.reloadable;
1471         this.reloadable = reloadable;
1472         support.firePropertyChange("reloadable",
1473                                    new Boolean(oldReloadable),
1474                                    new Boolean(this.reloadable));
1475 
1476     }
1477 
1478 
1479     /**
1480      * Set the DefaultContext override flag for this web application.
1481      *
1482      * @param override The new override flag
1483      */
1484     public void setOverride(boolean override) {
1485 
1486         boolean oldOverride = this.override;
1487         this.override = override;
1488         support.firePropertyChange("override",
1489                                    new Boolean(oldOverride),
1490                                    new Boolean(this.override));
1491 
1492     }
1493 
1494 
1495     /**
1496      * Return the "replace welcome files" property.
1497      */
1498     public boolean isReplaceWelcomeFiles() {
1499 
1500         return (this.replaceWelcomeFiles);
1501 
1502     }
1503 
1504 
1505     /**
1506      * Set the "replace welcome files" property.
1507      *
1508      * @param replaceWelcomeFiles The new property value
1509      */
1510     public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
1511 
1512         boolean oldReplaceWelcomeFiles = this.replaceWelcomeFiles;
1513         this.replaceWelcomeFiles = replaceWelcomeFiles;
1514         support.firePropertyChange("replaceWelcomeFiles",
1515                                    new Boolean(oldReplaceWelcomeFiles),
1516                                    new Boolean(this.replaceWelcomeFiles));
1517 
1518     }
1519 
1520 
1521     /**
1522      * Return the servlet context for which this Context is a facade.
1523      */
1524     public ServletContext getServletContext() {
1525 
1526         if (context == null) {
1527             context = new ApplicationContext(getBasePath(), this);
1528             if (altDDName != null)
1529                 context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
1530         }
1531         return (context.getFacade());
1532 
1533     }
1534 
1535 
1536     /**
1537      * Return the default session timeout (in minutes) for this
1538      * web application.
1539      */
1540     public int getSessionTimeout() {
1541 
1542         return (this.sessionTimeout);
1543 
1544     }
1545 
1546 
1547     /**
1548      * Set the default session timeout (in minutes) for this
1549      * web application.
1550      *
1551      * @param timeout The new default session timeout
1552      */
1553     public void setSessionTimeout(int timeout) {
1554 
1555         int oldSessionTimeout = this.sessionTimeout;
1556         /*
1557          * SRV.13.4 ("Deployment Descriptor"):
1558          * If the timeout is 0 or less, the container ensures the default
1559          * behaviour of sessions is never to time out.
1560          */
1561         this.sessionTimeout = (timeout == 0) ? -1 : timeout;
1562         support.firePropertyChange("sessionTimeout",
1563                                    new Integer(oldSessionTimeout),
1564                                    new Integer(this.sessionTimeout));
1565 
1566     }
1567 
1568 
1569     /**
1570      * Return the value of the swallowOutput flag.
1571      */
1572     public boolean getSwallowOutput() {
1573 
1574         return (this.swallowOutput);
1575 
1576     }
1577 
1578 
1579     /**
1580      * Set the value of the swallowOutput flag. If set to true, the system.out
1581      * and system.err will be redirected to the logger during a servlet
1582      * execution.
1583      *
1584      * @param swallowOutput The new value
1585      */
1586     public void setSwallowOutput(boolean swallowOutput) {
1587 
1588         boolean oldSwallowOutput = this.swallowOutput;
1589         this.swallowOutput = swallowOutput;
1590         support.firePropertyChange("swallowOutput",
1591                                    new Boolean(oldSwallowOutput),
1592                                    new Boolean(this.swallowOutput));
1593 
1594     }
1595 
1596 
1597     /**
1598      * Unpack WAR flag accessor.
1599      */
1600     public boolean getUnpackWAR() {
1601 
1602         return (unpackWAR);
1603 
1604     }
1605 
1606 
1607     /**
1608      * Unpack WAR flag mutator.
1609      */
1610     public void setUnpackWAR(boolean unpackWAR) {
1611 
1612         this.unpackWAR = unpackWAR;
1613 
1614     }
1615 
1616     /**
1617      * Return the Java class name of the Wrapper implementation used
1618      * for servlets registered in this Context.
1619      */
1620     public String getWrapperClass() {
1621 
1622         return (this.wrapperClass);
1623 
1624     }
1625 
1626 
1627     /**
1628      * Set the Java class name of the Wrapper implementation used
1629      * for servlets registered in this Context.
1630      *
1631      * @param wrapperClass The new wrapper class
1632      */
1633     public void setWrapperClass(String wrapperClass) {
1634 
1635         this.wrapperClass = wrapperClass;
1636 
1637     }
1638 
1639 
1640     /**
1641      * Set the resources DirContext object with which this Container is
1642      * associated.
1643      *
1644      * @param resources The newly associated DirContext
1645      */
1646     public synchronized void setResources(DirContext resources) {
1647 
1648         if (started) {
1649             throw new IllegalStateException
1650                 (sm.getString("standardContext.resources.started"));
1651         }
1652 
1653         DirContext oldResources = this.webappResources;
1654         if (oldResources == resources)
1655             return;
1656 
1657         if (resources instanceof BaseDirContext) {
1658             ((BaseDirContext) resources).setCached(isCachingAllowed());
1659             ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
1660             ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
1661         }
1662         if (resources instanceof FileDirContext) {
1663             filesystemBased = true;
1664             ((FileDirContext) resources).setCaseSensitive(isCaseSensitive());
1665             ((FileDirContext) resources).setAllowLinking(isAllowLinking());
1666         }
1667         this.webappResources = resources;
1668 
1669         // The proxied resources will be refreshed on start
1670         this.resources = null;
1671 
1672         support.firePropertyChange("resources", oldResources,
1673                                    this.webappResources);
1674 
1675     }
1676 
1677 
1678     // ------------------------------------------------------ Public Properties
1679 
1680 
1681     /**
1682      * Return the Locale to character set mapper class for this Context.
1683      */
1684     public String getCharsetMapperClass() {
1685 
1686         return (this.charsetMapperClass);
1687 
1688     }
1689 
1690 
1691     /**
1692      * Set the Locale to character set mapper class for this Context.
1693      *
1694      * @param mapper The new mapper class
1695      */
1696     public void setCharsetMapperClass(String mapper) {
1697 
1698         String oldCharsetMapperClass = this.charsetMapperClass;
1699         this.charsetMapperClass = mapper;
1700         support.firePropertyChange("charsetMapperClass",
1701                                    oldCharsetMapperClass,
1702                                    this.charsetMapperClass);
1703 
1704     }
1705 
1706 
1707     /** Get the absolute path to the work dir.
1708      *  To avoid duplication.
1709      * 
1710      * @return The work path
1711      */ 
1712     public String getWorkPath() {
1713         File workDir = new File(getWorkDir());
1714         if (!workDir.isAbsolute()) {
1715             File catalinaHome = engineBase();
1716             String catalinaHomePath = null;
1717             try {
1718                 catalinaHomePath = catalinaHome.getCanonicalPath();
1719                 workDir = new File(catalinaHomePath,
1720                         getWorkDir());
1721             } catch (IOException e) {
1722             }
1723         }
1724         return workDir.getAbsolutePath();
1725     }
1726     
1727     /**
1728      * Return the work directory for this Context.
1729      */
1730     public String getWorkDir() {
1731 
1732         return (this.workDir);
1733 
1734     }
1735 
1736 
1737     /**
1738      * Set the work directory for this Context.
1739      *
1740      * @param workDir The new work directory
1741      */
1742     public void setWorkDir(String workDir) {
1743 
1744         this.workDir = workDir;
1745 
1746         if (started)
1747             postWorkDirectory();
1748 
1749     }
1750 
1751 
1752     /**
1753      * Save config ?
1754      */
1755     public boolean isSaveConfig() {
1756         return saveConfig;
1757     }
1758 
1759 
1760     /**
1761      * Set save config flag.
1762      */
1763     public void setSaveConfig(boolean saveConfig) {
1764         this.saveConfig = saveConfig;
1765     }
1766 
1767 
1768     // -------------------------------------------------------- Context Methods
1769 
1770 
1771     /**
1772      * Add a new Listener class name to the set of Listeners
1773      * configured for this application.
1774      *
1775      * @param listener Java class name of a listener class
1776      */
1777     public void addApplicationListener(String listener) {
1778 
1779         synchronized (applicationListeners) {
1780             String results[] =new String[applicationListeners.length + 1];
1781             for (int i = 0; i < applicationListeners.length; i++) {
1782                 if (listener.equals(applicationListeners[i]))
1783                     return;
1784                 results[i] = applicationListeners[i];
1785             }
1786             results[applicationListeners.length] = listener;
1787             applicationListeners = results;
1788         }
1789         fireContainerEvent("addApplicationListener", listener);
1790 
1791         // FIXME - add instance if already started?
1792 
1793     }
1794 
1795 
1796     /**
1797      * Add a new application parameter for this application.
1798      *
1799      * @param parameter The new application parameter
1800      */
1801     public void addApplicationParameter(ApplicationParameter parameter) {
1802 
1803         synchronized (applicationParameters) {
1804             String newName = parameter.getName();
1805             for (int i = 0; i < applicationParameters.length; i++) {
1806                 if (newName.equals(applicationParameters[i].getName()) &&
1807                     !applicationParameters[i].getOverride())
1808                     return;
1809             }
1810             ApplicationParameter results[] =
1811                 new ApplicationParameter[applicationParameters.length + 1];
1812             System.arraycopy(applicationParameters, 0, results, 0,
1813                              applicationParameters.length);
1814             results[applicationParameters.length] = parameter;
1815             applicationParameters = results;
1816         }
1817         fireContainerEvent("addApplicationParameter", parameter);
1818 
1819     }
1820 
1821 
1822     /**
1823      * Add a child Container, only if the proposed child is an implementation
1824      * of Wrapper.
1825      *
1826      * @param child Child container to be added
1827      *
1828      * @exception IllegalArgumentException if the proposed container is
1829      *  not an implementation of Wrapper
1830      */
1831     public void addChild(Container child) {
1832 
1833         // Global JspServlet
1834         Wrapper oldJspServlet = null;
1835 
1836         if (!(child instanceof Wrapper)) {
1837             throw new IllegalArgumentException
1838                 (sm.getString("standardContext.notWrapper"));
1839         }
1840 
1841         Wrapper wrapper = (Wrapper) child;
1842         boolean isJspServlet = "jsp".equals(child.getName());
1843 
1844         // Allow webapp to override JspServlet inherited from global web.xml.
1845         if (isJspServlet) {
1846             oldJspServlet = (Wrapper) findChild("jsp");
1847             if (oldJspServlet != null) {
1848                 removeChild(oldJspServlet);
1849             }
1850         }
1851 
1852         String jspFile = wrapper.getJspFile();
1853         if ((jspFile != null) && !jspFile.startsWith("/")) {
1854             if (isServlet22()) {
1855                 log.debug(sm.getString("standardContext.wrapper.warning", 
1856                                        jspFile));
1857                 wrapper.setJspFile("/" + jspFile);
1858             } else {
1859                 throw new IllegalArgumentException
1860                     (sm.getString("standardContext.wrapper.error", jspFile));
1861             }
1862         }
1863 
1864         super.addChild(child);
1865 
1866         if (isJspServlet && oldJspServlet != null) {
1867             /*
1868              * The webapp-specific JspServlet inherits all the mappings
1869              * specified in the global web.xml, and may add additional ones.
1870              */
1871             String[] jspMappings = oldJspServlet.findMappings();
1872             for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
1873                 addServletMapping(jspMappings[i], child.getName());
1874             }
1875         }
1876     }
1877 
1878 
1879     /**
1880      * Add a security constraint to the set for this web application.
1881      */
1882     public void addConstraint(SecurityConstraint constraint) {
1883 
1884         // Validate the proposed constraint
1885         SecurityCollection collections[] = constraint.findCollections();
1886         for (int i = 0; i < collections.length; i++) {
1887             String patterns[] = collections[i].findPatterns();
1888             for (int j = 0; j < patterns.length; j++) {
1889                 patterns[j] = adjustURLPattern(patterns[j]);
1890                 if (!validateURLPattern(patterns[j]))
1891                     throw new IllegalArgumentException
1892                         (sm.getString
1893                          ("standardContext.securityConstraint.pattern",
1894                           patterns[j]));
1895             }
1896         }
1897 
1898         // Add this constraint to the set for our web application
1899         synchronized (constraints) {
1900             SecurityConstraint results[] =
1901                 new SecurityConstraint[constraints.length + 1];
1902             for (int i = 0; i < constraints.length; i++)
1903                 results[i] = constraints[i];
1904             results[constraints.length] = constraint;
1905             constraints = results;
1906         }
1907 
1908     }
1909 
1910 
1911 
1912     /**
1913      * Add an error page for the specified error or Java exception.
1914      *
1915      * @param errorPage The error page definition to be added
1916      */
1917     public void addErrorPage(ErrorPage errorPage) {
1918         // Validate the input parameters
1919         if (errorPage == null)
1920             throw new IllegalArgumentException
1921                 (sm.getString("standardContext.errorPage.required"));
1922         String location = errorPage.getLocation();
1923         if ((location != null) && !location.startsWith("/")) {
1924             if (isServlet22()) {
1925                 log.debug(sm.getString("standardContext.errorPage.warning",
1926                                  location));
1927                 errorPage.setLocation("/" + location);
1928             } else {
1929                 throw new IllegalArgumentException
1930                     (sm.getString("standardContext.errorPage.error",
1931                                   location));
1932             }
1933         }
1934 
1935         // Add the specified error page to our internal collections
1936         String exceptionType = errorPage.getExceptionType();
1937         if (exceptionType != null) {
1938             synchronized (exceptionPages) {
1939                 exceptionPages.put(exceptionType, errorPage);
1940             }
1941         } else {
1942             synchronized (statusPages) {
1943                 if (errorPage.getErrorCode() == 200) {
1944                     this.okErrorPage = errorPage;
1945                 }
1946                 statusPages.put(new Integer(errorPage.getErrorCode()),
1947                                 errorPage);
1948             }
1949         }
1950         fireContainerEvent("addErrorPage", errorPage);
1951 
1952     }
1953 
1954 
1955     /**
1956      * Add a filter definition to this Context.
1957      *
1958      * @param filterDef The filter definition to be added
1959      */
1960     public void addFilterDef(FilterDef filterDef) {
1961 
1962         synchronized (filterDefs) {
1963             filterDefs.put(filterDef.getFilterName(), filterDef);
1964         }
1965         fireContainerEvent("addFilterDef", filterDef);
1966 
1967     }
1968 
1969 
1970     /**
1971      * Add a filter mapping to this Context.
1972      *
1973      * @param filterMap The filter mapping to be added
1974      *
1975      * @exception IllegalArgumentException if the specified filter name
1976      *  does not match an existing filter definition, or the filter mapping
1977      *  is malformed
1978      */
1979     public void addFilterMap(FilterMap filterMap) {
1980 
1981         // Validate the proposed filter mapping
1982         String filterName = filterMap.getFilterName();
1983         String servletName = filterMap.getServletName();
1984         String urlPattern = filterMap.getURLPattern();
1985         if (findFilterDef(filterName) == null)
1986             throw new IllegalArgumentException
1987                 (sm.getString("standardContext.filterMap.name", filterName));
1988         if ((servletName == null) && (urlPattern == null))
1989             throw new IllegalArgumentException
1990                 (sm.getString("standardContext.filterMap.either"));
1991         if ((servletName != null) && (urlPattern != null))
1992             throw new IllegalArgumentException
1993                 (sm.getString("standardContext.filterMap.either"));
1994         // Because filter-pattern is new in 2.3, no need to adjust
1995         // for 2.2 backwards compatibility
1996         if ((urlPattern != null) && !validateURLPattern(urlPattern))
1997             throw new IllegalArgumentException
1998                 (sm.getString("standardContext.filterMap.pattern",
1999                               urlPattern));
2000 
2001         // Add this filter mapping to our registered set
2002         synchronized (filterMaps) {
2003             FilterMap results[] =new FilterMap[filterMaps.length + 1];
2004             System.arraycopy(filterMaps, 0, results, 0, filterMaps.length);
2005             results[filterMaps.length] = filterMap;
2006             filterMaps = results;
2007         }
2008         fireContainerEvent("addFilterMap", filterMap);
2009 
2010     }
2011 
2012 
2013     /**
2014      * Add the classname of an InstanceListener to be added to each
2015      * Wrapper appended to this Context.
2016      *
2017      * @param listener Java class name of an InstanceListener class
2018      */
2019     public void addInstanceListener(String listener) {
2020 
2021         synchronized (instanceListeners) {
2022             String results[] =new String[instanceListeners.length + 1];
2023             for (int i = 0; i < instanceListeners.length; i++)
2024                 results[i] = instanceListeners[i];
2025             results[instanceListeners.length] = listener;
2026             instanceListeners = results;
2027         }
2028         fireContainerEvent("addInstanceListener", listener);
2029 
2030     }
2031 
2032     /**
2033      * Add the given URL pattern as a jsp-property-group.  This maps
2034      * resources that match the given pattern so they will be passed
2035      * to the JSP container.  Though there are other elements in the
2036      * property group, we only care about the URL pattern here.  The
2037      * JSP container will parse the rest.
2038      *
2039      * @param pattern URL pattern to be mapped
2040      */
2041     public void addJspMapping(String pattern) {
2042         String servletName = findServletMapping("*.jsp");
2043         if (servletName == null) {
2044             servletName = "jsp";
2045         }
2046 
2047         if( findChild(servletName) != null) {
2048             addServletMapping(pattern, servletName, true);
2049         } else {
2050             log.debug("Skiping " + pattern + " , no servlet " + servletName);
2051         }
2052     }
2053 
2054 
2055     /**
2056      * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
2057      *
2058      * @param locale locale to map an encoding for
2059      * @param encoding encoding to be used for a give locale
2060      */
2061     public void addLocaleEncodingMappingParameter(String locale, String encoding){
2062         getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
2063     }
2064 
2065 
2066     /**
2067      * Add a message destination for this web application.
2068      *
2069      * @param md New message destination
2070      */
2071     public void addMessageDestination(MessageDestination md) {
2072 
2073         synchronized (messageDestinations) {
2074             messageDestinations.put(md.getName(), md);
2075         }
2076         fireContainerEvent("addMessageDestination", md.getName());
2077 
2078     }
2079 
2080 
2081     /**
2082      * Add a message destination reference for this web application.
2083      *
2084      * @param mdr New message destination reference
2085      */
2086     public void addMessageDestinationRef
2087         (MessageDestinationRef mdr) {
2088 
2089         namingResources.addMessageDestinationRef(mdr);
2090         fireContainerEvent("addMessageDestinationRef", mdr.getName());
2091 
2092     }
2093 
2094 
2095     /**
2096      * Add a new MIME mapping, replacing any existing mapping for
2097      * the specified extension.
2098      *
2099      * @param extension Filename extension being mapped
2100      * @param mimeType Corresponding MIME type
2101      */
2102     public void addMimeMapping(String extension, String mimeType) {
2103 
2104         synchronized (mimeMappings) {
2105             mimeMappings.put(extension, mimeType);
2106         }
2107         fireContainerEvent("addMimeMapping", extension);
2108 
2109     }
2110 
2111 
2112     /**
2113      * Add a new context initialization parameter.
2114      *
2115      * @param name Name of the new parameter
2116      * @param value Value of the new  parameter
2117      *
2118      * @exception IllegalArgumentException if the name or value is missing,
2119      *  or if this context initialization parameter has already been
2120      *  registered
2121      */
2122     public void addParameter(String name, String value) {
2123         // Validate the proposed context initialization parameter
2124         if ((name == null) || (value == null))
2125             throw new IllegalArgumentException
2126                 (sm.getString("standardContext.parameter.required"));
2127         if (parameters.get(name) != null)
2128             throw new IllegalArgumentException
2129                 (sm.getString("standardContext.parameter.duplicate", name));
2130 
2131         // Add this parameter to our defined set
2132         synchronized (parameters) {
2133             parameters.put(name, value);
2134         }
2135         fireContainerEvent("addParameter", name);
2136 
2137     }
2138 
2139 
2140     /**
2141      * Add a security role reference for this web application.
2142      *
2143      * @param role Security role used in the application
2144      * @param link Actual security role to check for
2145      */
2146     public void addRoleMapping(String role, String link) {
2147 
2148         synchronized (roleMappings) {
2149             roleMappings.put(role, link);
2150         }
2151         fireContainerEvent("addRoleMapping", role);
2152 
2153     }
2154 
2155 
2156     /**
2157      * Add a new security role for this web application.
2158      *
2159      * @param role New security role
2160      */
2161     public void addSecurityRole(String role) {
2162 
2163         synchronized (securityRoles) {
2164             String results[] =new String[securityRoles.length + 1];
2165             for (int i = 0; i < securityRoles.length; i++)
2166                 results[i] = securityRoles[i];
2167             results[securityRoles.length] = role;
2168             securityRoles = results;
2169         }
2170         fireContainerEvent("addSecurityRole", role);
2171 
2172     }
2173 
2174 
2175     /**
2176      * Add a new servlet mapping, replacing any existing mapping for
2177      * the specified pattern.
2178      *
2179      * @param pattern URL pattern to be mapped
2180      * @param name Name of the corresponding servlet to execute
2181      *
2182      * @exception IllegalArgumentException if the specified servlet name
2183      *  is not known to this Context
2184      */
2185     public void addServletMapping(String pattern, String name) {
2186         addServletMapping(pattern, name, false);
2187     }
2188 
2189 
2190     /**
2191      * Add a new servlet mapping, replacing any existing mapping for
2192      * the specified pattern.
2193      *
2194      * @param pattern URL pattern to be mapped
2195      * @param name Name of the corresponding servlet to execute
2196      * @param jspWildCard true if name identifies the JspServlet
2197      * and pattern contains a wildcard; false otherwise
2198      *
2199      * @exception IllegalArgumentException if the specified servlet name
2200      *  is not known to this Context
2201      */
2202     public void addServletMapping(String pattern, String name,
2203                                   boolean jspWildCard) {
2204         // Validate the proposed mapping
2205         if (findChild(name) == null)
2206             throw new IllegalArgumentException
2207                 (sm.getString("standardContext.servletMap.name", name));
2208         pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
2209         if (!validateURLPattern(pattern))
2210             throw new IllegalArgumentException
2211                 (sm.getString("standardContext.servletMap.pattern", pattern));
2212 
2213         // Add this mapping to our registered set
2214         synchronized (servletMappings) {
2215             String name2 = (String) servletMappings.get(pattern);
2216             if (name2 != null) {
2217                 // Don't allow more than one servlet on the same pattern
2218                 Wrapper wrapper = (Wrapper) findChild(name2);
2219                 wrapper.removeMapping(pattern);
2220                 mapper.removeWrapper(pattern);
2221             }
2222             servletMappings.put(pattern, name);
2223         }
2224         Wrapper wrapper = (Wrapper) findChild(name);
2225         wrapper.addMapping(pattern);
2226 
2227         // Update context mapper
2228         mapper.addWrapper(pattern, wrapper, jspWildCard);
2229 
2230         fireContainerEvent("addServletMapping", pattern);
2231 
2232     }
2233 
2234 
2235     /**
2236      * Add a JSP tag library for the specified URI.
2237      *
2238      * @param uri URI, relative to the web.xml file, of this tag library
2239      * @param location Location of the tag library descriptor
2240      */
2241     public void addTaglib(String uri, String location) {
2242 
2243         synchronized (taglibs) {
2244             taglibs.put(uri, location);
2245         }
2246         fireContainerEvent("addTaglib", uri);
2247 
2248     }
2249 
2250 
2251     /**
2252      * Add a new watched resource to the set recognized by this Context.
2253      *
2254      * @param name New watched resource file name
2255      */
2256     public void addWatchedResource(String name) {
2257 
2258         synchronized (watchedResources) {
2259             String results[] = new String[watchedResources.length + 1];
2260             for (int i = 0; i < watchedResources.length; i++)
2261                 results[i] = watchedResources[i];
2262             results[watchedResources.length] = name;
2263             watchedResources = results;
2264         }
2265         fireContainerEvent("addWatchedResource", name);
2266 
2267     }
2268 
2269 
2270     /**
2271      * Add a new welcome file to the set recognized by this Context.
2272      *
2273      * @param name New welcome file name
2274      */
2275     public void addWelcomeFile(String name) {
2276 
2277         synchronized (welcomeFiles) {
2278             // Welcome files from the application deployment descriptor
2279             // completely replace those from the default conf/web.xml file
2280             if (replaceWelcomeFiles) {
2281                 welcomeFiles = new String[0];
2282                 setReplaceWelcomeFiles(false);
2283             }
2284             String results[] =new String[welcomeFiles.length + 1];
2285             for (int i = 0; i < welcomeFiles.length; i++)
2286                 results[i] = welcomeFiles[i];
2287             results[welcomeFiles.length] = name;
2288             welcomeFiles = results;
2289         }
2290         postWelcomeFiles();
2291         fireContainerEvent("addWelcomeFile", name);
2292 
2293     }
2294 
2295 
2296     /**
2297      * Add the classname of a LifecycleListener to be added to each
2298      * Wrapper appended to this Context.
2299      *
2300      * @param listener Java class name of a LifecycleListener class
2301      */
2302     public void addWrapperLifecycle(String listener) {
2303 
2304         synchronized (wrapperLifecycles) {
2305             String results[] =new String[wrapperLifecycles.length + 1];
2306             for (int i = 0; i < wrapperLifecycles.length; i++)
2307                 results[i] = wrapperLifecycles[i];
2308             results[wrapperLifecycles.length] = listener;
2309             wrapperLifecycles = results;
2310         }
2311         fireContainerEvent("addWrapperLifecycle", listener);
2312 
2313     }
2314 
2315 
2316     /**
2317      * Add the classname of a ContainerListener to be added to each
2318      * Wrapper appended to this Context.
2319      *
2320      * @param listener Java class name of a ContainerListener class
2321      */
2322     public void addWrapperListener(String listener) {
2323 
2324         synchronized (wrapperListeners) {
2325             String results[] =new String[wrapperListeners.length + 1];
2326             for (int i = 0; i < wrapperListeners.length; i++)
2327                 results[i] = wrapperListeners[i];
2328             results[wrapperListeners.length] = listener;
2329             wrapperListeners = results;
2330         }
2331         fireContainerEvent("addWrapperListener", listener);
2332 
2333     }
2334 
2335 
2336     /**
2337      * Factory method to create and return a new Wrapper instance, of
2338      * the Java implementation class appropriate for this Context
2339      * implementation.  The constructor of the instantiated Wrapper
2340      * will have been called, but no properties will have been set.
2341      */
2342     public Wrapper createWrapper() {
2343         //log.info( "Create wrapper" );
2344         Wrapper wrapper = new StandardWrapper();
2345 
2346         synchronized (instanceListeners) {
2347             for (int i = 0; i < instanceListeners.length; i++) {
2348                 try {
2349                     Class clazz = Class.forName(instanceListeners[i]);
2350                     InstanceListener listener =
2351                       (InstanceListener) clazz.newInstance();
2352                     wrapper.addInstanceListener(listener);
2353                 } catch (Throwable t) {
2354                     log.error("createWrapper", t);
2355                     return (null);
2356                 }
2357             }
2358         }
2359 
2360         synchronized (wrapperLifecycles) {
2361             for (int i = 0; i < wrapperLifecycles.length; i++) {
2362                 try {
2363                     Class clazz = Class.forName(wrapperLifecycles[i]);
2364                     LifecycleListener listener =
2365                       (LifecycleListener) clazz.newInstance();
2366                     if (wrapper instanceof Lifecycle)
2367                         ((Lifecycle) wrapper).addLifecycleListener(listener);
2368                 } catch (Throwable t) {
2369                     log.error("createWrapper", t);
2370                     return (null);
2371                 }
2372             }
2373         }
2374 
2375         synchronized (wrapperListeners) {
2376             for (int i = 0; i < wrapperListeners.length; i++) {
2377                 try {
2378                     Class clazz = Class.forName(wrapperListeners[i]);
2379                     ContainerListener listener =
2380                       (ContainerListener) clazz.newInstance();
2381                     wrapper.addContainerListener(listener);
2382                 } catch (Throwable t) {
2383                     log.error("createWrapper", t);
2384                     return (null);
2385                 }
2386             }
2387         }
2388 
2389         return (wrapper);
2390 
2391     }
2392 
2393 
2394     /**
2395      * Return the set of application listener class names configured
2396      * for this application.
2397      */
2398     public String[] findApplicationListeners() {
2399 
2400         return (applicationListeners);
2401 
2402     }
2403 
2404 
2405     /**
2406      * Return the set of application parameters for this application.
2407      */
2408     public ApplicationParameter[] findApplicationParameters() {
2409 
2410         return (applicationParameters);
2411 
2412     }
2413 
2414 
2415     /**
2416      * Return the security constraints for this web application.
2417      * If there are none, a zero-length array is returned.
2418      */
2419     public SecurityConstraint[] findConstraints() {
2420 
2421         return (constraints);
2422 
2423     }
2424 
2425 
2426     /**
2427      * Return the error page entry for the specified HTTP error code,
2428      * if any; otherwise return <code>null</code>.
2429      *
2430      * @param errorCode Error code to look up
2431      */
2432     public ErrorPage findErrorPage(int errorCode) {
2433         if (errorCode == 200) {
2434             return (okErrorPage);
2435         } else {
2436             return ((ErrorPage) statusPages.get(new Integer(errorCode)));
2437         }
2438 
2439     }
2440 
2441 
2442     /**
2443      * Return the error page entry for the specified Java exception type,
2444      * if any; otherwise return <code>null</code>.
2445      *
2446      * @param exceptionType Exception type to look up
2447      */
2448     public ErrorPage findErrorPage(String exceptionType) {
2449 
2450         synchronized (exceptionPages) {
2451             return ((ErrorPage) exceptionPages.get(exceptionType));
2452         }
2453 
2454     }
2455 
2456 
2457     /**
2458      * Return the set of defined error pages for all specified error codes
2459      * and exception types.
2460      */
2461     public ErrorPage[] findErrorPages() {
2462 
2463         synchronized(exceptionPages) {
2464             synchronized(statusPages) {
2465                 ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
2466                 results1 =
2467                     (ErrorPage[]) exceptionPages.values().toArray(results1);
2468                 ErrorPage results2[] = new ErrorPage[statusPages.size()];
2469                 results2 =
2470                     (ErrorPage[]) statusPages.values().toArray(results2);
2471                 ErrorPage results[] =
2472                     new ErrorPage[results1.length + results2.length];
2473                 for (int i = 0; i < results1.length; i++)
2474                     results[i] = results1[i];
2475                 for (int i = results1.length; i < results.length; i++)
2476                     results[i] = results2[i - results1.length];
2477                 return (results);
2478             }
2479         }
2480 
2481     }
2482 
2483 
2484     /**
2485      * Return the filter definition for the specified filter name, if any;
2486      * otherwise return <code>null</code>.
2487      *
2488      * @param filterName Filter name to look up
2489      */
2490     public FilterDef findFilterDef(String filterName) {
2491 
2492         synchronized (filterDefs) {
2493             return ((FilterDef) filterDefs.get(filterName));
2494         }
2495 
2496     }
2497 
2498 
2499     /**
2500      * Return the set of defined filters for this Context.
2501      */
2502     public FilterDef[] findFilterDefs() {
2503 
2504         synchronized (filterDefs) {
2505             FilterDef results[] = new FilterDef[filterDefs.size()];
2506             return ((FilterDef[]) filterDefs.values().toArray(results));
2507         }
2508 
2509     }
2510 
2511 
2512     /**
2513      * Return the set of filter mappings for this Context.
2514      */
2515     public FilterMap[] findFilterMaps() {
2516 
2517         return (filterMaps);
2518 
2519     }
2520 
2521 
2522     /**
2523      * Return the set of InstanceListener classes that will be added to
2524      * newly created Wrappers automatically.
2525      */
2526     public String[] findInstanceListeners() {
2527 
2528         return (instanceListeners);
2529 
2530     }
2531 
2532 
2533     /**
2534      * FIXME: Fooling introspection ...
2535      */
2536     public Context findMappingObject() {
2537         return (Context) getMappingObject();
2538     }
2539     
2540     
2541     /**
2542      * Return the message destination with the specified name, if any;
2543      * otherwise, return <code>null</code>.
2544      *
2545      * @param name Name of the desired message destination
2546      */
2547     public MessageDestination findMessageDestination(String name) {
2548 
2549         synchronized (messageDestinations) {
2550             return ((MessageDestination) messageDestinations.get(name));
2551         }
2552 
2553     }
2554 
2555 
2556     /**
2557      * Return the set of defined message destinations for this web
2558      * application.  If none have been defined, a zero-length array
2559      * is returned.
2560      */
2561     public MessageDestination[] findMessageDestinations() {
2562 
2563         synchronized (messageDestinations) {
2564             MessageDestination results[] =
2565                 new MessageDestination[messageDestinations.size()];
2566             return ((MessageDestination[])
2567                     messageDestinations.values().toArray(results));
2568         }
2569 
2570     }
2571 
2572 
2573     /**
2574      * Return the message destination ref with the specified name, if any;
2575      * otherwise, return <code>null</code>.
2576      *
2577      * @param name Name of the desired message destination ref
2578      */
2579     public MessageDestinationRef
2580         findMessageDestinationRef(String name) {
2581 
2582         return namingResources.findMessageDestinationRef(name);
2583 
2584     }
2585 
2586 
2587     /**
2588      * Return the set of defined message destination refs for this web
2589      * application.  If none have been defined, a zero-length array
2590      * is returned.
2591      */
2592     public MessageDestinationRef[]
2593         findMessageDestinationRefs() {
2594 
2595         return namingResources.findMessageDestinationRefs();
2596 
2597     }
2598 
2599 
2600     /**
2601      * Return the MIME type to which the specified extension is mapped,
2602      * if any; otherwise return <code>null</code>.
2603      *
2604      * @param extension Extension to map to a MIME type
2605      */
2606     public String findMimeMapping(String extension) {
2607 
2608         return ((String) mimeMappings.get(extension));
2609 
2610     }
2611 
2612 
2613     /**
2614      * Return the extensions for which MIME mappings are defined.  If there
2615      * are none, a zero-length array is returned.
2616      */
2617     public String[] findMimeMappings() {
2618 
2619         synchronized (mimeMappings) {
2620             String results[] = new String[mimeMappings.size()];
2621             return
2622                 ((String[]) mimeMappings.keySet().toArray(results));
2623         }
2624 
2625     }
2626 
2627 
2628     /**
2629      * Return the value for the specified context initialization
2630      * parameter name, if any; otherwise return <code>null</code>.
2631      *
2632      * @param name Name of the parameter to return
2633      */
2634     public String findParameter(String name) {
2635 
2636         synchronized (parameters) {
2637             return ((String) parameters.get(name));
2638         }
2639 
2640     }
2641 
2642 
2643     /**
Rate2644      * Return the names of all defined context initialization parameters
2645      * for this Context.  If no parameters are defined, a zero-length
2646      * array is returned.
2647      */
2648     public String[] findParameters() {
2649 
2650         synchronized (parameters) {
2651             String results[] = new String[parameters.size()];
2652             return ((String[]) parameters.keySet().toArray(results));
2653         }
2654 
2655     }
2656 
2657 
2658     /**
2659      * For the given security role (as used by an application), return the
2660      * corresponding role name (as defined by the underlying Realm) if there
2661      * is one.  Otherwise, return the specified role unchanged.
2662      *
2663      * @param role Security role to map
2664      */
2665     public String findRoleMapping(String role) {
2666 
2667         String realRole = null;
2668         synchronized (roleMappings) {
2669             realRole = (String) roleMappings.get(role);
2670         }
2671         if (realRole != null)
2672             return (realRole);
2673         else
2674             return (role);
Rate2675 
2676     }
2677 
2678 
2679     /**
2680      * Return <code>true</code> if the specified security role is defined
2681      * for this application; otherwise return <code>false</code>.
2682      *
2683      * @param role Security role to verify
2684      */
2685     public boolean findSecurityRole(String role) {
2686 
2687         synchronized (securityRoles) {
2688             for (int i = 0; i < securityRoles.length; i++) {
2689                 if (role.equals(securityRoles[i]))
2690                     return (true);
2691             }
2692         }
2693         return (false);
2694 
2695     }
2696 
2697 
2698     /**
2699      * Return the security roles defined for this application.  If none
2700      * have been defined, a zero-length array is returned.
2701      */
2702     public String[] findSecurityRoles() {
2703 
2704         return (securityRoles);
2705 
2706     }
2707 
2708 
2709     /**
2710      * Return the servlet name mapped by the specified pattern (if any);
2711      * otherwise return <code>null</code>.
2712      *
2713      * @param pattern Pattern for which a mapping is requested
2714      */
2715     public String findServletMapping(String pattern) {
2716 
2717         synchronized (servletMappings) {
2718             return ((String) servletMappings.get(pattern));
2719         }
2720 
2721     }
2722 
2723 
2724     /**
2725      * Return the patterns of all defined servlet mappings for this
2726      * Context.  If no mappings are defined, a zero-length array is returned.
2727      */
2728     public String[] findServletMappings() {
2729 
2730         synchronized (servletMappings) {
2731             String results[] = new String[servletMappings.size()];
2732             return
2733                ((String[]) servletMappings.keySet().toArray(results));
2734         }
2735 
2736     }
2737 
2738 
2739     /**
2740      * Return the context-relative URI of the error page for the specified
2741      * HTTP status code, if any; otherwise return <code>null</code>.
2742      *
2743      * @param status HTTP status code to look up
2744      */
2745     public String findStatusPage(int status) {
2746 
2747         return ((String) statusPages.get(new Integer(status)));
2748 
2749     }
2750 
2751 
2752     /**
2753      * Return the set of HTTP status codes for which error pages have
2754      * been specified.  If none are specified, a zero-length array
Rate2755      * is returned.
2756      */
2757     public int[] findStatusPages() {
2758 
2759         synchronized (statusPages) {
2760             int results[] = new int[statusPages.size()];
2761             Iterator elements = statusPages.keySet().iterator();
2762             int i = 0;
2763             while (elements.hasNext())
2764                 results[i++] = ((Integer) elements.next()).intValue();
2765             return (results);
2766         }
2767 
2768     }
2769 
2770 
2771     /**
2772      * Return the tag library descriptor location for the specified taglib
2773      * URI, if any; otherwise, return <code>null</code>.
2774      *
2775      * @param uri URI, relative to the web.xml file
2776      */
2777     public String findTaglib(String uri) {
2778 
2779         synchronized (taglibs) {
2780             return ((String) taglibs.get(uri));
2781         }
2782 
2783     }
Rate2784 
2785 
2786     /**
2787      * Return the URIs of all tag libraries for which a tag library
2788      * descriptor location has been specified.  If none are specified,
2789      * a zero-length array is returned.
2790      */
2791     public String[] findTaglibs() {
2792 
2793         synchronized (taglibs) {
2794             String results[] = new String[taglibs.size()];
2795             return ((String[]) taglibs.keySet().toArray(results));
2796         }
2797 
2798     }
2799 
2800 
2801     /**
2802      * Return <code>true</code> if the specified welcome file is defined
2803      * for this Context; otherwise return <code>false</code>.
2804      *
2805      * @param name Welcome file to verify
2806      */
2807     public boolean findWelcomeFile(String name) {
2808 
2809         synchronized (welcomeFiles) {
2810             for (int i = 0; i < welcomeFiles.length; i++) {
2811                 if (name.equals(welcomeFiles[i]))
2812                     return (true);
2813             }
2814         }
2815         return (false);
2816 
2817     }
Rate2818 
2819 
2820     /**
2821      * Return the set of watched resources for this Context. If none are 
2822      * defined, a zero length array will be returned.
2823      */
2824     public String[] findWatchedResources() {
2825         return watchedResources;
2826     }
2827     
2828     
2829     /**
2830      * Return the set of welcome files defined for this Context.  If none are
2831      * defined, a zero-length array is returned.
2832      */
2833     public String[] findWelcomeFiles() {
2834 
2835         return (welcomeFiles);
2836 
2837     }
2838 
2839 
2840     /**
2841      * Return the set of LifecycleListener classes that will be added to
2842      * newly created Wrappers automatically.
2843      */
2844     public String[] findWrapperLifecycles() {
2845 
2846         return (wrapperLifecycles);
2847 
2848     }
2849 
2850 
2851     /**
2852      * Return the set of ContainerListener classes that will be added to
2853      * newly created Wrappers automatically.
2854      */
2855     public String[] findWrapperListeners() {
2856 
2857         return (wrapperListeners);
2858 
2859     }
2860 
2861 
2862     /**
2863      * Reload this web application, if reloading is supported.
2864      * <p>
2865      * <b>IMPLEMENTATION NOTE</b>:  This method is designed to deal with
2866      * reloads required by changes to classes in the underlying repositories
2867      * of our class loader.  It does not handle changes to the web application
2868      * deployment descriptor.  If that has occurred, you should stop this
2869      * Context and create (and start) a new Context instance instead.
2870      *
2871      * @exception IllegalStateException if the <code>reloadable</code>
2872      *  property is set to <code>false</code>.
2873      */
2874     public synchronized void reload() {
2875 
2876         // Validate our current component state
2877         if (!started)
2878             throw new IllegalStateException
2879                 (sm.getString("containerBase.notStarted", logName()));
2880 
2881         // Make sure reloading is enabled
2882         //      if (!reloadable)
2883         //          throw new IllegalStateException
2884         //              (sm.getString("standardContext.notReloadable"));
2885         log.info(sm.getString("standardContext.reloadingStarted"));
2886 
2887         // Stop accepting requests temporarily
2888         setPaused(true);
2889 
2890         try {
2891             stop();
2892         } catch (LifecycleException e) {
2893             log.error(sm.getString("standardContext.stoppingContext"), e);
2894         }
2895 
2896         try {
2897             start();
2898         } catch (LifecycleException e) {
2899             log.error(sm.getString("standardContext.startingContext"), e);
2900         }
2901 
2902         setPaused(false);
2903 
2904     }
2905 
2906 
2907     /**
2908      * Remove the specified application listener class from the set of
2909      * listeners for this application.
2910      *
2911      * @param listener Java class name of the listener to be removed
2912      */
2913     public void removeApplicationListener(String listener) {
2914 
2915         synchronized (applicationListeners) {
2916 
2917             // Make sure this welcome file is currently present
2918             int n = -1;
2919             for (int i = 0; i < applicationListeners.length; i++) {
2920                 if (applicationListeners[i].equals(listener)) {
2921                     n = i;
2922                     break;
2923                 }
2924             }
2925             if (n < 0)
2926                 return;
2927 
2928             // Remove the specified constraint
2929             int j = 0;
2930             String results[] = new String[applicationListeners.length - 1];
2931             for (int i = 0; i < applicationListeners.length; i++) {
2932                 if (i != n)
2933                     results[j++] = applicationListeners[i];
2934             }
2935             applicationListeners = results;
2936 
2937         }
2938 
2939         // Inform interested listeners
2940         fireContainerEvent("removeApplicationListener", listener);
2941 
2942         // FIXME - behavior if already started?
2943 
2944     }
2945 
2946 
2947     /**
2948      * Remove the application parameter with the specified name from
2949      * the set for this application.
2950      *
2951      * @param name Name of the application parameter to remove
2952      */
2953     public void removeApplicationParameter(String name) {
2954 
2955         synchronized (applicationParameters) {
2956 
2957             // Make sure this parameter is currently present
2958             int n = -1;
2959             for (int i = 0; i < applicationParameters.length; i++) {
2960                 if (name.equals(applicationParameters[i].getName())) {
2961                     n = i;
2962                     break;
2963                 }
2964             }
2965             if (n < 0)
2966                 return;
2967 
2968             // Remove the specified parameter
2969             int j = 0;
2970             ApplicationParameter results[] =
2971                 new ApplicationParameter[applicationParameters.length - 1];
2972             for (int i = 0; i < applicationParameters.length; i++) {
2973                 if (i != n)
2974                     results[j++] = applicationParameters[i];
2975             }
2976             applicationParameters = results;
2977 
2978         }
2979 
2980         // Inform interested listeners
2981         fireContainerEvent("removeApplicationParameter", name);
2982 
2983     }
2984 
2985 
2986     /**
2987      * Add a child Container, only if the proposed child is an implementation
2988      * of Wrapper.
2989      *
2990      * @param child Child container to be added
2991      *
2992      * @exception IllegalArgumentException if the proposed container is
2993      *  not an implementation of Wrapper
2994      */
2995     public void removeChild(Container child) {
2996 
2997         if (!(child instanceof Wrapper)) {
2998             throw new IllegalArgumentException
2999                 (sm.getString("standardContext.notWrapper"));
3000         }
3001 
3002         super.removeChild(child);
3003 
3004     }
3005 
3006 
3007     /**
3008      * Remove the specified security constraint from this web application.
3009      *
3010      * @param constraint Constraint to be removed
3011      */
3012     public void removeConstraint(SecurityConstraint constraint) {
3013 
3014         synchronized (constraints) {
3015 
3016             // Make sure this constraint is currently present
3017             int n = -1;
3018             for (int i = 0; i < constraints.length; i++) {
3019                 if (constraints[i].equals(constraint)) {
3020                     n = i;
3021                     break;
3022                 }
3023             }
3024             if (n < 0)
3025                 return;
3026 
3027             // Remove the specified constraint
3028             int j = 0;
3029             SecurityConstraint results[] =
3030                 new SecurityConstraint[constraints.length - 1];
3031             for (int i = 0; i < constraints.length; i++) {
3032                 if (i != n)
3033                     results[j++] = constraints[i];
3034             }
3035             constraints = results;
3036 
3037         }
3038 
3039         // Inform interested listeners
3040         fireContainerEvent("removeConstraint", constraint);
3041 
3042     }
3043 
3044 
3045     /**
3046      * Remove the error page for the specified error code or
3047      * Java language exception, if it exists; otherwise, no action is taken.
3048      *
3049      * @param errorPage The error page definition to be removed
3050      */
3051     public void removeErrorPage(ErrorPage errorPage) {
3052 
3053         String exceptionType = errorPage.getExceptionType();
3054         if (exceptionType != null) {
3055             synchronized (exceptionPages) {
3056                 exceptionPages.remove(exceptionType);
3057             }
3058         } else {
3059             synchronized (statusPages) {
3060                 if (errorPage.getErrorCode() == 200) {
3061                     this.okErrorPage = null;
3062                 }
3063                 statusPages.remove(new Integer(errorPage.getErrorCode()));
3064             }
3065         }
3066         fireContainerEvent("removeErrorPage", errorPage);
3067 
3068     }
3069 
3070 
3071     /**
3072      * Remove the specified filter definition from this Context, if it exists;
3073      * otherwise, no action is taken.
3074      *
3075      * @param filterDef Filter definition to be removed
3076      */
3077     public void removeFilterDef(FilterDef filterDef) {
3078 
3079         synchronized (filterDefs) {
3080             filterDefs.remove(filterDef.getFilterName());
3081         }
3082         fireContainerEvent("removeFilterDef", filterDef);
3083 
3084     }
3085 
3086 
3087     /**
3088      * Remove a filter mapping from this Context.
3089      *
3090      * @param filterMap The filter mapping to be removed
3091      */
3092     public void removeFilterMap(FilterMap filterMap) {
3093 
3094         synchronized (filterMaps) {
3095 
3096             // Make sure this filter mapping is currently present
3097             int n = -1;
3098             for (int i = 0; i < filterMaps.length; i++) {
3099                 if (filterMaps[i] == filterMap) {
3100                     n = i;
3101                     break;
3102                 }
3103             }
3104             if (n < 0)
3105                 return;
3106 
3107             // Remove the specified filter mapping
3108             FilterMap results[] = new FilterMap[filterMaps.length - 1];
3109             System.arraycopy(filterMaps, 0, results, 0, n);
3110             System.arraycopy(filterMaps, n + 1, results, n,
3111                              (filterMaps.length - 1) - n);
3112             filterMaps = results;
3113 
3114         }
3115 
3116         // Inform interested listeners
3117         fireContainerEvent("removeFilterMap", filterMap);
3118 
3119     }
3120 
3121 
3122     /**
3123      * Remove a class name from the set of InstanceListener classes that
3124      * will be added to newly created Wrappers.
3125      *
3126      * @param listener Class name of an InstanceListener class to be removed
3127      */
3128     public void removeInstanceListener(String listener) {
3129 
3130         synchronized (instanceListeners) {
3131 
3132             // Make sure this welcome file is currently present
3133             int n = -1;
3134             for (int i = 0; i < instanceListeners.length; i++) {
3135                 if (instanceListeners[i].equals(listener)) {
3136                     n = i;
3137                     break;
3138                 }
3139             }
3140             if (n < 0)
3141                 return;
3142 
3143             // Remove the specified constraint
3144             int j = 0;
3145             String results[] = new String[instanceListeners.length - 1];
3146             for (int i = 0; i < instanceListeners.length; i++) {
3147                 if (i != n)
3148                     results[j++] = instanceListeners[i];
3149             }
3150             instanceListeners = results;
3151 
3152         }
3153 
3154         // Inform interested listeners
3155         fireContainerEvent("removeInstanceListener", listener);
3156 
3157     }
3158 
3159 
3160     /**
3161      * Remove any message destination with the specified name.
3162      *
3163      * @param name Name of the message destination to remove
3164      */
3165     public void removeMessageDestination(String name) {
3166 
3167         synchronized (messageDestinations) {
3168             messageDestinations.remove(name);
3169         }
3170         fireContainerEvent("removeMessageDestination", name);
3171 
3172     }
3173 
3174 
3175     /**
3176      * Remove any message destination ref with the specified name.
3177      *
3178      * @param name Name of the message destination ref to remove
3179      */
3180     public void removeMessageDestinationRef(String name) {
3181 
3182         namingResources.removeMessageDestinationRef(name);
3183         fireContainerEvent("removeMessageDestinationRef", name);
3184 
3185     }
3186 
3187 
3188     /**
3189      * Remove the MIME mapping for the specified extension, if it exists;
3190      * otherwise, no action is taken.
3191      *
3192      * @param extension Extension to remove the mapping for
3193      */
3194     public void removeMimeMapping(String extension) {
3195 
3196         synchronized (mimeMappings) {
3197             mimeMappings.remove(extension);
3198         }
3199         fireContainerEvent("removeMimeMapping", extension);
3200 
3201     }
3202 
3203 
3204     /**
3205      * Remove the context initialization parameter with the specified
3206      * name, if it exists; otherwise, no action is taken.
3207      *
3208      * @param name Name of the parameter to remove
3209      */
3210     public void removeParameter(String name) {
3211 
3212         synchronized (parameters) {
3213             parameters.remove(name);
3214         }
3215         fireContainerEvent("removeParameter", name);
3216 
3217     }
3218 
3219 
3220     /**
3221      * Remove any security role reference for the specified name
3222      *
3223      * @param role Security role (as used in the application) to remove
3224      */
3225     public void removeRoleMapping(String role) {
3226 
3227         synchronized (roleMappings) {
3228             roleMappings.remove(role);
3229         }
3230         fireContainerEvent("removeRoleMapping", role);
3231 
3232     }
3233 
3234 
3235     /**
3236      * Remove any security role with the specified name.
3237      *
3238      * @param role Security role to remove
3239      */
3240     public void removeSecurityRole(String role) {
3241 
3242         synchronized (securityRoles) {
3243 
3244             // Make sure this security role is currently present
3245             int n = -1;
3246             for (int i = 0; i < securityRoles.length; i++) {
3247                 if (role.equals(securityRoles[i])) {
3248                     n = i;
3249                     break;
3250                 }
3251             }
3252             if (n < 0)
3253                 return;
3254 
3255             // Remove the specified security role
3256             int j = 0;
3257             String results[] = new String[securityRoles.length - 1];
3258             for (int i = 0; i < securityRoles.length; i++) {
3259                 if (i != n)
3260                     results[j++] = securityRoles[i];
3261             }
3262             securityRoles = results;
3263 
3264         }
3265 
3266         // Inform interested listeners
3267         fireContainerEvent("removeSecurityRole", role);
3268 
3269     }
3270 
3271 
3272     /**
3273      * Remove any servlet mapping for the specified pattern, if it exists;
3274      * otherwise, no action is taken.
3275      *
3276      * @param pattern URL pattern of the mapping to remove
3277      */
3278     public void removeServletMapping(String pattern) {
3279 
3280         String name = null;
3281         synchronized (servletMappings) {
3282             name = (String) servletMappings.remove(pattern);
3283         }
3284         Wrapper wrapper = (Wrapper) findChild(name);
3285         if( wrapper != null ) {
3286             wrapper.removeMapping(pattern);
3287         }
3288         mapper.removeWrapper(pattern);
3289         fireContainerEvent("removeServletMapping", pattern);
3290 
3291     }
3292 
3293 
3294     /**
3295      * Remove the tag library location forthe specified tag library URI.
3296      *
3297      * @param uri URI, relative to the web.xml file
3298      */
3299     public void removeTaglib(String uri) {
3300 
3301         synchronized (taglibs) {
3302             taglibs.remove(uri);
3303         }
3304         fireContainerEvent("removeTaglib", uri);
3305     }
3306 
3307 
3308     /**
3309      * Remove the specified watched resource name from the list associated
3310      * with this Context.
3311      * 
3312      * @param name Name of the watched resource to be removed
3313      */
3314     public void removeWatchedResource(String name) {
3315         
3316         synchronized (watchedResources) {
3317 
3318             // Make sure this watched resource is currently present
3319             int n = -1;
3320             for (int i = 0; i < watchedResources.length; i++) {
3321                 if (watchedResources[i].equals(name)) {
3322                     n = i;
3323                     break;
3324                 }
3325             }
3326             if (n < 0)
3327                 return;
3328 
3329             // Remove the specified watched resource
3330             int j = 0;
3331             String results[] = new String[watchedResources.length - 1];
3332             for (int i = 0; i < watchedResources.length; i++) {
3333                 if (i != n)
3334                     results[j++] = watchedResources[i];
3335             }
3336             watchedResources = results;
3337 
3338         }
3339 
3340         fireContainerEvent("removeWatchedResource", name);
3341 
3342     }
3343     
3344     
3345     /**
3346      * Remove the specified welcome file name from the list recognized
3347      * by this Context.
3348      *
3349      * @param name Name of the welcome file to be removed
3350      */
3351     public void removeWelcomeFile(String name) {
3352 
3353         synchronized (welcomeFiles) {
3354 
3355             // Make sure this welcome file is currently present
3356             int n = -1;
3357             for (int i = 0; i < welcomeFiles.length; i++) {
3358                 if (welcomeFiles[i].equals(name)) {
3359                     n = i;
3360                     break;
3361                 }
3362             }
3363             if (n < 0)
3364                 return;
3365 
3366             // Remove the specified constraint
3367             int j = 0;
3368             String results[] = new String[welcomeFiles.length - 1];
3369             for (int i = 0; i < welcomeFiles.length; i++) {
3370                 if (i != n)
3371                     results[j++] = welcomeFiles[i];
3372             }
3373             welcomeFiles = results;
3374 
3375         }
3376 
3377         // Inform interested listeners
3378         postWelcomeFiles();
3379         fireContainerEvent("removeWelcomeFile", name);
3380 
3381     }
3382 
3383 
3384     /**
3385      * Remove a class name from the set of LifecycleListener classes that
3386      * will be added to newly created Wrappers.
3387      *
3388      * @param listener Class name of a LifecycleListener class to be removed
3389      */
3390     public void removeWrapperLifecycle(String listener) {
3391 
3392 
3393         synchronized (wrapperLifecycles) {
3394 
3395             // Make sure this welcome file is currently present
3396             int n = -1;
3397             for (int i = 0; i < wrapperLifecycles.length; i++) {
3398                 if (wrapperLifecycles[i].equals(listener)) {
3399                     n = i;
3400                     break;
3401                 }
3402             }
3403             if (n < 0)
3404                 return;
3405 
3406             // Remove the specified constraint
3407             int j = 0;
3408             String results[] = new String[wrapperLifecycles.length - 1];
3409             for (int i = 0; i < wrapperLifecycles.length; i++) {
3410                 if (i != n)
3411                     results[j++] = wrapperLifecycles[i];
3412             }
3413             wrapperLifecycles = results;
3414 
3415         }
3416 
3417         // Inform interested listeners
3418         fireContainerEvent("removeWrapperLifecycle", listener);
3419 
3420     }
3421 
3422 
3423     /**
3424      * Remove a class name from the set of ContainerListener classes that
3425      * will be added to newly created Wrappers.
3426      *
3427      * @param listener Class name of a ContainerListener class to be removed
3428      */
3429     public void removeWrapperListener(String listener) {
3430 
3431 
3432         synchronized (wrapperListeners) {
3433 
3434             // Make sure this welcome file is currently present
3435             int n = -1;
3436             for (int i = 0; i < wrapperListeners.length; i++) {
3437                 if (wrapperListeners[i].equals(listener)) {
3438                     n = i;
3439                     break;
3440                 }
3441             }
3442             if (n < 0)
3443                 return;
3444 
3445             // Remove the specified constraint
3446             int j = 0;
3447             String results[] = new String[wrapperListeners.length - 1];
3448             for (int i = 0; i < wrapperListeners.length; i++) {
3449                 if (i != n)
3450                     results[j++] = wrapperListeners[i];
3451             }
3452             wrapperListeners = results;
3453 
3454         }
3455 
3456         // Inform interested listeners
3457         fireContainerEvent("removeWrapperListener", listener);
3458 
3459     }
3460 
3461 
3462     // --------------------------------------------------------- Public Methods
3463 
3464 
3465     /**
3466      * Configure and initialize the set of filters for this Context.
3467      * Return <code>true</code> if all filter initialization completed
3468      * successfully, or <code>false</code> otherwise.
3469      */
3470     public boolean filterStart() {
3471 
3472         if (log.isDebugEnabled())
3473             log.debug("Starting filters");
3474         // Instantiate and record a FilterConfig for each defined filter
3475         boolean ok = true;
3476         synchronized (filterConfigs) {
3477             filterConfigs.clear();
3478             Iterator names = filterDefs.keySet().iterator();
3479             while (names.hasNext()) {
3480                 String name = (String) names.next();
3481                 if (log.isDebugEnabled())
3482                     log.debug(" Starting filter '" + name + "'");
3483                 ApplicationFilterConfig filterConfig = null;
3484                 try {
3485                     filterConfig = new ApplicationFilterConfig
3486                       (this, (FilterDef) filterDefs.get(name));
3487                     filterConfigs.put(name, filterConfig);
3488                 } catch (Throwable t) {
3489                     getServletContext().log
3490                         (sm.getString("standardContext.filterStart", name), t);
3491                     ok = false;
3492                 }
3493             }
3494         }
3495 
3496         return (ok);
3497 
3498     }
3499 
3500 
Rate3501     /**
3502      * Finalize and release the set of filters for this Context.
3503      * Return <code>true</code> if all filter finalization completed
3504      * successfully, or <code>false</code> otherwise.
3505      */
3506     public boolean filterStop() {
3507 
3508         if (log.isDebugEnabled())
3509             log.debug("Stopping filters");
3510 
3511         // Release all Filter and FilterConfig instances
3512         synchronized (filterConfigs) {
3513             Iterator names = filterConfigs.keySet().iterator();
3514             while (names.hasNext()) {
3515                 String name = (String) names.next();
3516                 if (log.isDebugEnabled())
3517                     log.debug(" Stopping filter '" + name + "'");
3518                 ApplicationFilterConfig filterConfig =
3519                   (ApplicationFilterConfig) filterConfigs.get(name);
3520                 filterConfig.release();
3521             }
3522             filterConfigs.clear();
3523         }
3524         return (true);
3525 
3526     }
3527 
3528 
3529     /**
3530      * Find and return the initialized <code>FilterConfig</code> for the
3531      * specified filter name, if any; otherwise return <code>null</code>.
3532      *
3533      * @param name Name of the desired filter
3534      */
3535     public FilterConfig findFilterConfig(String name) {
Rate3536 
3537         return ((FilterConfig) filterConfigs.get(name));
3538 
3539     }
3540 
3541 
3542     /**
3543      * Configure the set of instantiated application event listeners
3544      * for this Context.  Return <code>true</code> if all listeners wre
3545      * initialized successfully, or <code>false</code> otherwise.
3546      */
3547     public boolean listenerStart() {
3548 
3549         if (log.isDebugEnabled())
3550             log.debug("Configuring application event listeners");
3551 
3552         // Instantiate the required listeners
3553         ClassLoader loader = getLoader().getClassLoader();
3554         String listeners[] = findApplicationListeners();
3555         Object results[] = new Object[listeners.length];
3556         boolean ok = true;
3557         for (int i = 0; i < results.length; i++) {
3558             if (log.isDebugEnabled())
3559                 log.debug(" Configuring event listener class '" +
3560                     listeners[i] + "'");
3561             try {
3562                 Class clazz = loader.loadClass(listeners[i]);
3563                 results[i] = clazz.newInstance();
3564             } catch (Throwable t) {
3565                 getServletContext().log
3566                     (sm.getString("standardContext.applicationListener",
3567                                   listeners[i]), t);
3568                 ok = false;
3569             }
3570         }
3571         if (!ok) {
3572             log.error(sm.getString("standardContext.applicationSkipped"));
3573             return (false);
3574         }
3575 
3576         // Sort listeners in two arrays
3577         ArrayList eventListeners = new ArrayList();
3578         ArrayList lifecycleListeners = new ArrayList();
3579         for (int i = 0; i < results.length; i++) {
3580             if ((results[i] instanceof ServletContextAttributeListener)
3581                 || (results[i] instanceof ServletRequestAttributeListener)
3582                 || (results[i] instanceof ServletRequestListener)
3583                 || (results[i] instanceof HttpSessionAttributeListener)) {
3584                 eventListeners.add(results[i]);
3585             }
3586             if ((results[i] instanceof ServletContextListener)
3587                 || (results[i] instanceof HttpSessionListener)) {
3588                 lifecycleListeners.add(results[i]);
3589             }
3590         }
3591 
3592         setApplicationEventListeners(eventListeners.toArray());
3593         setApplicationLifecycleListeners(lifecycleListeners.toArray());
3594 
3595         // Send application start events
3596 
3597         if (log.isDebugEnabled())
3598             log.debug("Sending application start events");
3599 
3600         Object instances[] = getApplicationLifecycleListeners();
3601         if (instances == null)
3602             return (ok);
3603         ServletContextEvent event =
3604           new ServletContextEvent(getServletContext());
3605         for (int i = 0; i < instances.length; i++) {
3606             if (instances[i] == null)
3607                 continue;
3608             if (!(instances[i] instanceof ServletContextListener))
3609                 continue;
3610             ServletContextListener listener =
3611                 (ServletContextListener) instances[i];
3612             try {
3613                 fireContainerEvent("beforeContextInitialized", listener);
3614                 listener.contextInitialized(event);
3615                 fireContainerEvent("afterContextInitialized", listener);
3616             } catch (Throwable t) {
3617                 fireContainerEvent("afterContextInitialized", listener);
3618                 getServletContext().log
3619                     (sm.getString("standardContext.listenerStart",
3620                                   instances[i].getClass().getName()), t);
3621                 ok = false;
3622             }
3623         }
3624         return (ok);
3625 
3626     }
3627 
3628 
3629     /**
3630      * Send an application stop event to all interested listeners.
3631      * Return <code>true</code> if all events were sent successfully,
3632      * or <code>false</code> otherwise.
3633      */
3634     public boolean listenerStop() {
3635 
3636         if (log.isDebugEnabled())
3637             log.debug("Sending application stop events");
3638 
3639         boolean ok = true;
3640         Object listeners[] = getApplicationLifecycleListeners();
3641         if (listeners == null)
3642             return (ok);
3643         ServletContextEvent event =
3644           new ServletContextEvent(getServletContext());
3645         for (int i = 0; i < listeners.length; i++) {
3646             int j = (listeners.length - 1) - i;
3647             if (listeners[j] == null)
3648                 continue;
3649             if (!(listeners[j] instanceof ServletContextListener))
3650                 continue;
3651             ServletContextListener listener =
3652                 (ServletContextListener) listeners[j];
3653             try {
3654                 fireContainerEvent("beforeContextDestroyed", listener);
3655                 listener.contextDestroyed(event);
3656                 fireContainerEvent("beforeContextDestroyed", listener);
3657             } catch (Throwable t) {
3658                 fireContainerEvent("beforeContextDestroyed", listener);
3659                 getServletContext().log
3660                     (sm.getString("standardContext.listenerStop",
3661                                   listeners[j].getClass().getName()), t);
3662                 ok = false;
3663             }
3664         }
3665         setApplicationEventListeners(null);
3666         setApplicationLifecycleListeners(null);
3667         return (ok);
3668 
3669     }
3670 
3671 
3672     /**
3673      * Allocate resources, including proxy.
3674      * Return <code>true</code> if initialization was successfull,
3675      * or <code>false</code> otherwise.
3676      */
3677     public boolean resourcesStart() {
3678 
3679         boolean ok = true;
3680 
3681         Hashtable env = new Hashtable();
3682         if (getParent() != null)
3683             env.put(ProxyDirContext.HOST, getParent().getName());
3684         env.put(ProxyDirContext.CONTEXT, getName());
3685 
3686         try {
3687             ProxyDirContext proxyDirContext =
3688                 new ProxyDirContext(env, webappResources);
3689             if (webappResources instanceof FileDirContext) {
3690                 filesystemBased = true;
3691                 ((FileDirContext) webappResources).setCaseSensitive
3692                     (isCaseSensitive());
3693                 ((FileDirContext) webappResources).setAllowLinking
3694                     (isAllowLinking());
3695             }
3696             if (webappResources instanceof BaseDirContext) {
3697                 ((BaseDirContext) webappResources).setDocBase(getBasePath());
3698                 ((BaseDirContext) webappResources).setCached
3699                     (isCachingAllowed());
3700                 ((BaseDirContext) webappResources).setCacheTTL(getCacheTTL());
3701                 ((BaseDirContext) webappResources).setCacheMaxSize
3702                     (getCacheMaxSize());
3703                 ((BaseDirContext) webappResources).allocate();
3704             }
3705             // Register the cache in JMX
3706             if (isCachingAllowed()) {
3707                 ObjectName resourcesName = 
3708                     new ObjectName(this.getDomain() + ":type=Cache,host=" 
3709                                    + getHostname() + ",path=" 
3710                                    + (("".equals(getPath()))?"/":getPath()));
3711                 Registry.getRegistry(null, null).registerComponent
3712                     (proxyDirContext.getCache(), resourcesName, null);
3713             }
3714             this.resources = proxyDirContext;
3715         } catch (Throwable t) {
3716             log.error(sm.getString("standardContext.resourcesStart"), t);
3717             ok = false;
3718         }
3719 
3720         return (ok);
3721 
3722     }
3723 
3724 
3725     /**
3726      * Deallocate resources and destroy proxy.
3727      */
3728     public boolean resourcesStop() {
3729 
3730         boolean ok = true;
3731 
3732         try {
3733             if (resources != null) {
3734                 if (resources instanceof Lifecycle) {
3735                     ((Lifecycle) resources).stop();
3736                 }
3737                 if (webappResources instanceof BaseDirContext) {
3738                     ((BaseDirContext) webappResources).release();
3739                 }
3740                 // Unregister the cache in JMX
3741                 if (isCachingAllowed()) {
3742                     ObjectName resourcesName = 
3743                         new ObjectName(this.getDomain()
3744                                        + ":type=Cache,host=" 
3745                                        + getHostname() + ",path=" 
3746                                        + (("".equals(getPath()))?"/"
3747                                           :getPath()));
3748                     Registry.getRegistry(null, null)
3749                         .unregisterComponent(resourcesName);
3750                 }
3751             }
3752         } catch (Throwable t) {
3753             log.error(sm.getString("standardContext.resourcesStop"), t);
3754             ok = false;
3755         }
3756 
3757         this.resources = null;
3758 
3759         return (ok);
3760 
3761     }
3762 
3763 
3764     /**
3765      * Load and initialize all servlets marked "load on startup" in the
3766      * web application deployment descriptor.
3767      *
3768      * @param children Array of wrappers for all currently defined
3769      *  servlets (including those not declared load on startup)
3770      */
3771     public void loadOnStartup(Container children[]) {
3772 
3773         // Collect "load on startup" servlets that need to be initialized
3774         TreeMap map = new TreeMap();
3775         for (int i = 0; i < children.length; i++) {
3776             Wrapper wrapper = (Wrapper) children[i];
3777             int loadOnStartup = wrapper.getLoadOnStartup();
3778             if (loadOnStartup < 0)
3779                 continue;
3780             if (loadOnStartup == 0)     // Arbitrarily put them last
3781                 loadOnStartup = Integer.MAX_VALUE;
3782             Integer key = new Integer(loadOnStartup);
3783             ArrayList list = (ArrayList) map.get(key);
3784             if (list == null) {
3785                 list = new ArrayList();
3786                 map.put(key, list);
3787             }
3788             list.add(wrapper);
3789         }
3790 
3791         // Load the collected "load on startup" servlets
3792         Iterator keys = map.keySet().iterator();
3793         while (keys.hasNext()) {
3794             Integer key = (Integer) keys.next();
3795             ArrayList list = (ArrayList) map.get(key);
3796             Iterator wrappers = list.iterator();
3797             while (wrappers.hasNext()) {
3798                 Wrapper wrapper = (Wrapper) wrappers.next();
3799                 try {
3800                     wrapper.load();
3801                 } catch (ServletException e) {
3802                     getServletContext().log
3803                         (sm.getString("standardWrapper.loadException",
3804                                       getName()), e);
3805                     // NOTE: load errors (including a servlet that throws
3806                     // UnavailableException from tht init() method) are NOT
3807                     // fatal to application startup
3808                 }
3809             }
3810         }
3811 
3812     }
3813 
3814 
3815     /**
3816      * Start this Context component.
3817      *
3818      * @exception LifecycleException if a startup error occurs
3819      */
3820     public synchronized void start() throws LifecycleException {
3821         //if (lazy ) return;
3822         if (started) {
3823             log.info(sm.getString("containerBase.alreadyStarted", logName()));
3824             return;
3825         }
3826         if( !initialized ) { 
3827             try {
3828                 init();
3829             } catch( Exception ex ) {
3830                 throw new LifecycleException("Error initializaing ", ex);
3831             }
3832         }
3833 
3834         log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName()));
3835 
3836         // Set JMX object name for proper pipeline registration
3837         preRegisterJMX();
3838 
3839         if ((oname != null) && 
3840             (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {
3841             // As things depend on the JMX registration, the context
3842             // must be reregistered again once properly initialized
3843             Registry.getRegistry(null, null).unregisterComponent(oname);
3844         }
3845 
3846         // Notify our interested LifecycleListeners
3847         lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
3848 
3849         setAvailable(false);
3850         setConfigured(false);
3851         boolean ok = true;
3852 
3853         // Set config file name
3854         /*
3855         File configBase = getConfigBase();
3856         if ((configBase != null) && saveConfig) {
3857             if (getConfigFile() == null) {
3858                 File file = new File(configBase, getDefaultConfigFile());
3859                 setConfigFile(file.getPath());
3860                 // If the docbase is outside the appBase, we should save our
3861                 // config
3862                 try {
3863                     File appBaseFile = new File(getAppBase());
3864                     if (!appBaseFile.isAbsolute()) {
3865                         appBaseFile = new File(engineBase(), getAppBase());
3866                     }
3867                     String appBase = appBaseFile.getCanonicalPath();
3868                     String basePath = 
3869                         (new File(getBasePath())).getCanonicalPath();
3870                     if (!basePath.startsWith(appBase)) {
3871                         Server server = ServerFactory.getServer();
3872                         ((StandardServer) server).storeContext(this);
3873                     }
3874                 } catch (Exception e) {
3875                     log.warn("Error storing config file", e);
3876                 }
3877             } else {
3878                 try {
3879                     String canConfigFile = 
3880                         (new File(getConfigFile())).getCanonicalPath();
3881                     if (!canConfigFile.startsWith
3882                         (configBase.getCanonicalPath())) {
3883                         File file = 
3884                             new File(configBase, getDefaultConfigFile());
3885                         if (copy(new File(canConfigFile), file)) {
3886                             setConfigFile(file.getPath());
3887                         }
3888                     }
3889                 } catch (Exception e) {
3890                     log.warn("Error setting config file", e);
3891                 }
3892             }
3893         }
3894         */
3895 
3896         // Add missing components as necessary
3897         if (webappResources == null) {   // (1) Required by Loader
3898             if (log.isDebugEnabled())
3899                 log.debug("Configuring default Resources");
3900             try {
3901                 if ((docBase != null) && (docBase.endsWith(".war")))
3902                     setResources(new WARDirContext());
3903                 else
3904                     setResources(new FileDirContext());
3905             } catch (IllegalArgumentException e) {
3906                 log.error("Error initializing resources: " + e.getMessage());
3907                 ok = false;
3908             }
3909         }
3910         if (ok) {
3911             if (!resourcesStart()) {
3912                 log.error( "Error in resourceStart()");
3913                 ok = false;
3914             }
3915         }
3916 
3917         // Look for a realm - that may have been configured earlier. 
3918         // If the realm is added after context - it'll set itself.
3919         if( realm == null ) {
3920             ObjectName realmName=null;
3921             try {
3922                 realmName=new ObjectName( getEngineName() + ":type=Host,host=" + 
3923                         getHostname() + ",path=" + getPath());
3924                 if( mserver.isRegistered(realmName ) ) {
3925                     mserver.invoke(realmName, "init", 
3926                             new Object[] {},
3927                             new String[] {}
3928                     );            
3929                 }
3930             } catch( Throwable t ) {
3931                 log.debug("No realm for this host " + realmName);
3932             }
3933         }
3934         
3935         if (getLoader() == null) {
3936             ClassLoader parent = null;
3937             if (getPrivileged()) {
3938                 if (log.isDebugEnabled())
3939                     log.debug("Configuring privileged default Loader");
3940                 parent = this.getClass().getClassLoader();
3941             } else {
3942                 if (log.isDebugEnabled())
3943                     log.debug("Configuring non-privileged default Loader");
3944                 parent = getParentClassLoader();
3945             }
3946             WebappLoader webappLoader = new WebappLoader(parent);
3947             webappLoader.setDelegate(getDelegate());
3948             setLoader(webappLoader);
3949         }
3950 
3951         // Initialize character set mapper
3952         getCharsetMapper();
3953 
3954         // Post work directory
3955         postWorkDirectory();
3956 
3957         // Validate required extensions
3958         boolean dependencyCheck = true;
3959         try {
3960             dependencyCheck = ExtensionValidator.validateApplication
3961                 (getResources(), this);
3962         } catch (IOException ioe) {
3963             log.error("Error in dependencyCheck", ioe);
3964             dependencyCheck = false;
3965         }
3966 
3967         if (!dependencyCheck) {
3968             // do not make application available if depency check fails
3969             ok = false;
3970         }
3971 
3972         // Reading the "catalina.useNaming" environment variable
3973         String useNamingProperty = System.getProperty("catalina.useNaming");
3974         if ((useNamingProperty != null)
3975             && (useNamingProperty.equals("false"))) {
3976             useNaming = false;
3977         }
3978 
3979         if (ok && isUseNaming()) {
3980             if (namingContextListener == null) {
3981                 namingContextListener = new NamingContextListener();
3982                 namingContextListener.setName(getNamingContextName());
3983                 addLifecycleListener(namingContextListener);
3984             }
3985         }
3986 
3987         // Binding thread
3988         ClassLoader oldCCL = bindThread();
3989 
3990         // Standard container startup
3991         if (log.isDebugEnabled())
3992             log.debug("Processing standard container startup");
3993 
3994         if (ok) {
3995 
3996             boolean mainOk = false;
3997             try {
3998 
3999                 started = true;
4000 
4001                 // Start our subordinate components, if any
4002                 if ((loader != null) && (loader instanceof Lifecycle))
4003                     ((Lifecycle) loader).start();
4004                 if ((logger != null) && (logger instanceof Lifecycle))
4005                     ((Lifecycle) logger).start();
4006 
4007                 // Unbinding thread
4008                 unbindThread(oldCCL);
4009 
4010                 // Binding thread
4011                 oldCCL = bindThread();
4012 
4013                 if ((cluster != null) && (cluster instanceof Lifecycle))
4014                     ((Lifecycle) cluster).start();
4015                 if ((realm != null) && (realm instanceof Lifecycle))
4016                     ((Lifecycle) realm).start();
4017                 if ((resources != null) && (resources instanceof Lifecycle))
4018                     ((Lifecycle) resources).start();
4019 
4020                 // Start our child containers, if any
4021                 Container children[] = findChildren();
4022                 for (int i = 0; i < children.length; i++) {
4023                     if (children[i] instanceof Lifecycle)
4024                         ((Lifecycle) children[i]).start();
4025                 }
4026 
4027                 // Start the Valves in our pipeline (including the basic),
4028                 // if any
4029                 if (pipeline instanceof Lifecycle)
4030                     ((Lifecycle) pipeline).start();
4031 
4032                 // Read tldListeners. XXX Option to disable
4033                 TldConfig tldConfig = new TldConfig();
4034                 tldConfig.setContext(this);
4035 
4036                 // (1)  check if the attribute has been defined
4037                 //      on the context element.
4038                 tldConfig.setTldValidation(tldValidation);
4039                 tldConfig.setTldNamespaceAware(tldNamespaceAware);
4040 
4041                 // (2) if the attribute wasn't defined on the context
4042                 //     try the host.
4043                 if (!tldValidation){
4044                     tldConfig.setTldValidation
4045                         (((StandardHost) getParent()).getXmlValidation());
4046                 }
4047 
4048                 if (!tldNamespaceAware){
4049                     tldConfig.setTldNamespaceAware
4050                         (((StandardHost) getParent()).getXmlNamespaceAware());
4051                 }
4052                     
4053                 try {
4054                     tldConfig.execute();
4055                 } catch (Exception ex) {
4056                     log.error("Error reading tld listeners " 
4057                               + ex.toString(), ex);
4058                     //ok=false;
4059                 }
4060 
4061                 // Notify our interested LifecycleListeners
4062                 lifecycle.fireLifecycleEvent(START_EVENT, null);
4063 
4064                 // Start manager
4065                 if ((manager != null) && (manager instanceof Lifecycle)) {
4066                     ((Lifecycle) getManager()).start();
4067                 }
4068 
4069                 // Start ContainerBackgroundProcessor thread
4070                 super.threadStart();
4071 
4072                 mainOk = true;
4073 
4074             } finally {
4075                 // Unbinding thread
4076                 unbindThread(oldCCL);
4077                 if (!mainOk) {
4078                     // An exception occurred
4079                     // Register with JMX anyway, to allow management
4080                     registerJMX();
4081                 }
4082             }
4083 
4084         }
4085         if (!getConfigured()) {
4086             log.error( "Error getConfigured");
4087             ok = false;
4088         }
4089 
4090         // We put the resources into the servlet context
4091         if (ok)
4092             getServletContext().setAttribute
4093                 (Globals.RESOURCES_ATTR, getResources());
4094 
4095         // Initialize associated mapper
4096         mapper.setContext(getPath(), welcomeFiles, resources);
4097 
4098         // Binding thread
4099         oldCCL = bindThread();
4100 
4101         // Create context attributes that will be required
4102         if (ok) {
4103             if (log.isDebugEnabled())
4104                 log.debug("Posting standard context attributes");
4105             postWelcomeFiles();
4106         }
4107 
4108         if (ok) {
4109             // Notify our interested LifecycleListeners
4110             lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
4111         }
4112 
4113         // Configure and call application event listeners and filters
4114         if (ok) {
4115             if (!listenerStart()) {
4116                 log.error( "Error listenerStart");
4117                 ok = false;
4118             }
4119         }
4120         if (ok) {
4121             if (!filterStart()) {
4122                 log.error( "Error filterStart");
4123                 ok = false;
4124             }
4125         }
4126 
4127         // Load and initialize all "load on startup" servlets
4128         if (ok) {
4129             loadOnStartup(findChildren());
4130         }
4131 
4132         // Unbinding thread
4133         unbindThread(oldCCL);
4134 
4135         // Set available status depending upon startup success
4136         if (ok) {
4137             if (log.isDebugEnabled())
4138                 log.debug("Starting completed");
4139             setAvailable(true);
4140         } else {
4141             log.error(sm.getString("standardContext.startFailed"));
4142             try {
4143                 stop();
4144             } catch (Throwable t) {
4145                 log.error(sm.getString("standardContext.startCleanup"), t);
4146             }
4147             setAvailable(false);
4148         }
4149 
4150         // JMX registration
4151         registerJMX();
4152 
4153         startTime=System.currentTimeMillis();
4154         
4155         // Send j2ee.state.running notification 
4156         if (ok && (this.getObjectName() != null)) {
4157             Notification notification = 
4158                 new Notification("j2ee.state.running", this.getObjectName(), 
4159                                 sequenceNumber++);
4160             broadcaster.sendNotification(notification);
4161         }
4162 
4163         // Close all JARs right away to avoid always opening a peak number 
4164         // of files on startup
4165         if (getLoader() instanceof WebappLoader) {
4166             ((WebappLoader) getLoader()).closeJARs(true);
4167         }
4168 
4169         // Reinitializing if something went wrong
4170         if (!ok && started) {
4171             stop();
4172         }
4173 
4174         //cacheContext();
4175     }
4176     
4177     private void cacheContext() {
4178         try {
4179             File workDir=new File( getWorkPath() );
4180             
4181             File ctxSer=new File( workDir, "_tomcat_context.ser");
4182             FileOutputStream fos=new FileOutputStream( ctxSer );
4183             ObjectOutputStream oos=new ObjectOutputStream( fos );
4184             oos.writeObject(this);
4185             oos.close();
4186             fos.close();
4187         } catch( Throwable t ) {
4188             log.info("Error saving context.ser ", t);
4189         }
4190     }
4191 
4192     /**
4193      * Stop this Context component. Experimental, please ignore.
4194      *
4195      * @exception LifecycleException if a shutdown error occurs
4196      */
4197     public synchronized void stopNew() throws LifecycleException {
4198         // Mark this application as unavailable while we shut down
4199         setAvailable(false);
4200 
4201         // Binding thread
4202         ClassLoader oldCCL = bindThread();
4203 
4204         try {
4205             // Stop our filters
4206             filterStop();
4207             
4208             // Finalize our character set mapper
4209             setCharsetMapper(null);
4210             
4211             // Stop our application listeners
4212             listenerStop();
4213             
4214             // Stop resources
4215             resourcesStop();
4216             
4217             super.stop();
4218         } finally {
4219             
4220             // Unbinding thread
4221             unbindThread(oldCCL);
4222             
4223         }
4224         
4225         // Reset application context
4226         context = null;
4227     }
4228 
4229     /**
4230      * Stop this Context component.
4231      *
4232      * @exception LifecycleException if a shutdown error occurs
4233      */
4234     public synchronized void stop() throws LifecycleException {
4235 
4236         // Validate and update our current component state
4237         if (!started)
4238             throw new LifecycleException
4239                 (sm.getString("containerBase.notStarted", logName()));
4240 
4241         if (log.isDebugEnabled())
4242             log.debug("Stopping");
4243 
4244         // Notify our interested LifecycleListeners
4245         lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
4246         
4247         // Send j2ee.state.stopping notification 
4248         if (this.getObjectName() != null) {
4249             Notification notification = 
4250                 new Notification("j2ee.state.stopping", this.getObjectName(), 
4251                                 sequenceNumber++);
4252             broadcaster.sendNotification(notification);
4253         }
4254         
4255         // Mark this application as unavailable while we shut down
4256         setAvailable(false);
4257 
4258         // Binding thread
4259         ClassLoader oldCCL = bindThread();
4260 
4261         // Stop our filters
4262         filterStop();
4263 
4264         // Stop ContainerBackgroundProcessor thread
4265         super.threadStop();
4266 
4267         if ((manager != null) && (manager instanceof Lifecycle)) {
4268             ((Lifecycle) manager).stop();
4269         }
4270 
4271         // Stop our application listeners
4272         listenerStop();
4273 
4274         // Finalize our character set mapper
4275         setCharsetMapper(null);
4276 
4277         // Normal container shutdown processing
4278         if (log.isDebugEnabled())
4279             log.debug("Processing standard container shutdown");
4280         // Notify our interested LifecycleListeners
4281         lifecycle.fireLifecycleEvent(STOP_EVENT, null);
4282         started = false;
4283 
4284         try {
4285 
4286             // Stop the Valves in our pipeline (including the basic), if any
4287             if (pipeline instanceof Lifecycle) {
4288                 ((Lifecycle) pipeline).stop();
4289             }
4290 
4291             // Stop our child containers, if any
4292             Container[] children = findChildren();
4293             for (int i = 0; i < children.length; i++) {
4294                 if (children[i] instanceof Lifecycle)
4295                     ((Lifecycle) children[i]).stop();
4296             }
4297 
4298             // Stop resources
4299             resourcesStop();
4300 
4301             if ((realm != null) && (realm instanceof Lifecycle)) {
4302                 ((Lifecycle) realm).stop();
4303             }
4304             if ((cluster != null) && (cluster instanceof Lifecycle)) {
4305                 ((Lifecycle) cluster).stop();
4306             }
4307             if ((logger != null) && (logger instanceof Lifecycle)) {
4308                 ((Lifecycle) logger).stop();
4309             }
4310             if ((loader != null) && (loader instanceof Lifecycle)) {
4311                 ((Lifecycle) loader).stop();
4312             }
4313 
4314         } finally {
4315 
4316             // Unbinding thread
4317             unbindThread(oldCCL);
4318 
4319         }
4320 
4321         // Send j2ee.state.stopped notification 
4322         if (this.getObjectName() != null) {
4323             Notification notification = 
4324                 new Notification("j2ee.state.stopped", this.getObjectName(), 
4325                                 sequenceNumber++);
4326             broadcaster.sendNotification(notification);
4327         }
4328         
4329         // Reset application context
4330         context = null;
4331 
4332         // This object will no longer be visible or used. 
4333         try {
4334             resetContext();
4335         } catch( Exception ex ) {
4336             log.error( "Error reseting context " + this + " " + ex, ex );
4337         }
4338         
4339         // Notify our interested LifecycleListeners
4340         lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
4341 
4342         if (log.isDebugEnabled())
4343             log.debug("Stopping complete");
4344 
4345     }
4346 
4347     /** Destroy needs to clean up the context completely.
4348      * 
4349      * The problem is that undoing all the config in start() and restoring 
4350      * a 'fresh' state is impossible. After stop()/destroy()/init()/start()
4351      * we should have the same state as if a fresh start was done - i.e
4352      * read modified web.xml, etc. This can only be done by completely 
4353      * removing the context object and remapping a new one, or by cleaning
4354      * up everything.
4355      * 
4356      * XXX Should this be done in stop() ?
4357      * 
4358      */ 
4359     public void destroy() throws Exception {
4360         if( oname != null ) { 
4361             // Send j2ee.object.deleted notification 
4362             Notification notification = 
4363                 new Notification("j2ee.object.deleted", this.getObjectName(), 
4364                                 sequenceNumber++);
4365             broadcaster.sendNotification(notification);
4366         } 
4367         super.destroy();
4368 
4369         // Notify our interested LifecycleListeners
4370         lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);
4371 
4372         instanceListeners = new String[0];
4373         applicationListeners = new String[0];
4374     }
4375     
4376     private void resetContext() throws Exception, MBeanRegistrationException {
4377         // Restore the original state ( pre reading web.xml in start )
4378         // If you extend this - override this method and make sure to clean up
4379         children=new HashMap();
4380         log.debug("resetContext " + oname + " " + mserver);
4381     }
4382 
4383     /**
4384      * Return a String representation of this component.
4385      */
4386     public String toString() {
4387 
4388         StringBuffer sb = new StringBuffer();
4389         if (getParent() != null) {
4390             sb.append(getParent().toString());
4391             sb.append(".");
4392         }
4393         sb.append("StandardContext[");
4394         sb.append(getName());
4395         sb.append("]");
4396         return (sb.toString());
4397 
4398     }
4399 
4400 
4401     /**
4402      * Execute a periodic task, such as reloading, etc. This method will be
4403      * invoked inside the classloading context of this container. Unexpected
4404      * throwables will be caught and logged.
4405      */
4406     public void backgroundProcess() {
4407 
4408         if (!started)
4409             return;
4410 
4411         count = (count + 1) % managerChecksFrequency;
4412 
4413         if ((getManager() != null) && (count == 0)) {
4414             try {
4415                 getManager().backgroundProcess();
4416             } catch ( Exception x ) {
4417                 log.warn("Unable to perform background process on manager",x);
4418             }
4419         }
4420 
4421         if (getLoader() != null) {
4422             if (reloadable && (getLoader().modified())) {
4423                 try {
4424                     Thread.currentThread().setContextClassLoader
4425                         (StandardContext.class.getClassLoader());
4426                     reload();
4427                 } finally {
4428                     if (getLoader() != null) {
4429                         Thread.currentThread().setContextClassLoader
4430                             (getLoader().getClassLoader());
4431                     }
4432                 }
4433             }
4434             if (getLoader() instanceof WebappLoader) {
4435                 ((WebappLoader) getLoader()).closeJARs(false);
4436             }
4437         }
4438 
4439     }
4440 
4441 
4442     // ------------------------------------------------------ Protected Methods
4443 
4444 
4445     /**
4446      * Adjust the URL pattern to begin with a leading slash, if appropriate
4447      * (i.e. we are running a servlet 2.2 application).  Otherwise, return
4448      * the specified URL pattern unchanged.
4449      *
4450      * @param urlPattern The URL pattern to be adjusted (if needed)
4451      *  and returned
4452      */
4453     protected String adjustURLPattern(String urlPattern) {
4454 
4455         if (urlPattern == null)
4456             return (urlPattern);
4457         if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
4458             return (urlPattern);
4459         if (!isServlet22())
4460             return (urlPattern);
4461         log.debug(sm.getString("standardContext.urlPattern.patternWarning",
4462                          urlPattern));
4463         return ("/" + urlPattern);
4464 
4465     }
4466 
4467 
4468     /**
4469      * Are we processing a version 2.2 deployment descriptor?
4470      */
4471     protected boolean isServlet22() {
4472 
4473         if (this.publicId == null)
4474             return (false);
4475         if (this.publicId.equals
4476             (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
4477             return (true);
4478         else
4479             return (false);
4480 
4481     }
4482 
4483 
4484     /**
4485      * Return a File object representing the base directory for the
4486      * entire servlet container (i.e. the Engine container if present).
4487      */
4488     protected File engineBase() {
4489         String base=System.getProperty("catalina.base");
4490         if( base == null ) {
4491             StandardEngine eng=(StandardEngine)this.getParent().getParent();
4492             base=eng.getBaseDir();
4493         }
4494         return (new File(base));
4495     }
4496 
4497 
4498     /**
4499      * Return the abbreviated name of this container for logging messsages
4500      */
4501     protected String logName() {
4502 
4503         if (logName != null) {
4504             return logName;
4505         }
4506         String loggerName = ((getName() == null) || (getName().equals(""))) 
4507                              ? "[/]" : ("[" + getName() + "]");
4508         Container current = getParent();
4509         while (current != null) {
4510             loggerName = "[" + current.getName() + "]" 
4511                 + ((loggerName != null) ? ("." + loggerName) : "");
4512             current = current.getParent();
4513         }
4514         logName = ContainerBase.class.getName() + "." + loggerName;
4515         return logName;
4516         
4517     }
4518 
4519     
4520     // -------------------------------------------------------- Private Methods
4521 
4522 
4523     /**
4524      * Bind current thread, both for CL purposes and for JNDI ENC support
4525      * during : startup, shutdown and realoading of the context.
4526      *
4527      * @return the previous context class loader
4528      */
4529     private ClassLoader bindThread() {
4530 
4531         ClassLoader oldContextClassLoader =
4532             Thread.currentThread().getContextClassLoader();
4533 
4534         if (getResources() == null)
4535             return oldContextClassLoader;
4536 
4537         Thread.currentThread().setContextClassLoader
4538             (getLoader().getClassLoader());
4539 
4540         DirContextURLStreamHandler.bind(getResources());
4541 
4542         if (isUseNaming()) {
4543             try {
4544                 ContextBindings.bindThread(this, this);
4545             } catch (NamingException e) {
4546                 // Silent catch, as this is a normal case during the early
4547                 // startup stages
4548             }
4549         }
4550 
4551         return oldContextClassLoader;
4552 
4553     }
4554 
4555 
4556     /**
4557      * Unbind thread.
4558      */
4559     private void unbindThread(ClassLoader oldContextClassLoader) {
4560 
4561         Thread.currentThread().setContextClassLoader(oldContextClassLoader);
4562 
4563         oldContextClassLoader = null;
4564 
4565         if (isUseNaming()) {
4566             ContextBindings.unbindThread(this, this);
4567         }
4568 
4569         DirContextURLStreamHandler.unbind();
4570 
4571     }
4572 
4573 
4574 
4575     /**
4576      * Get base path.
4577      */
4578     private String getBasePath() {
4579         String docBase = null;
4580         Container container = this;
4581         while (container != null) {
4582             if (container instanceof Host)
4583                 break;
4584             container = container.getParent();
4585         }
4586         File file = new File(getDocBase());
4587         if (!file.isAbsolute()) {
4588             if (container == null) {
4589                 docBase = (new File(engineBase(), getDocBase())).getPath();
4590             } else {
4591                 // Use the "appBase" property of this container
4592                 String appBase = ((Host) container).getAppBase();
4593                 file = new File(appBase);
4594                 if (!file.isAbsolute())
4595                     file = new File(engineBase(), appBase);
4596                 docBase = (new File(file, getDocBase())).getPath();
4597             }
4598         } else {
4599             docBase = file.getPath();
4600         }
4601         return docBase;
4602     }
4603 
4604 
4605     /**
4606      * Get app base.
4607      */
4608     private String getAppBase() {
4609         String appBase = null;
4610         Container container = this;
4611         while (container != null) {
4612             if (container instanceof Host)
4613                 break;
4614             container = container.getParent();
4615         }
4616         if (container != null) {
4617             appBase = ((Host) container).getAppBase();
4618         }
4619         return appBase;
4620     }
4621 
4622 
4623     /**
4624      * Get config base.
4625      */
4626     public File getConfigBase() {
4627         File configBase = 
4628             new File(System.getProperty("catalina.base"), "conf");
4629         if (!configBase.exists()) {
4630             return null;
4631         }
4632         Container container = this;
4633         Container host = null;
4634         Container engine = null;
4635         while (container != null) {
4636             if (container instanceof Host)
4637                 host = container;
4638             if (container instanceof Engine)
4639                 engine = container;
4640             container = container.getParent();
4641         }
4642         if (engine != null) {
4643             configBase = new File(configBase, engine.getName());
4644         }
4645         if (host != null) {
4646             configBase = new File(configBase, host.getName());
4647         }
4648         configBase.mkdirs();
4649         return configBase;
4650     }
4651 
4652 
4653     /**
4654      * Given a context path, get the config file name.
4655      */
4656     protected String getDefaultConfigFile() {
4657         String basename = null;
4658         String path = getPath();
4659         if (path.equals("")) {
4660             basename = "ROOT";
4661         } else {
4662             basename = path.substring(1).replace('/', '#');
4663         }
4664         return (basename + ".xml");
4665     }
4666 
4667 
4668     /**
4669      * Copy a file.
4670      */
4671     private boolean copy(File src, File dest) {
4672         FileInputStream is = null;
4673         FileOutputStream os = null;
4674         try {
4675             is = new FileInputStream(src);
4676             os = new FileOutputStream(dest);
4677             byte[] buf = new byte[4096];
4678             while (true) {
4679                 int len = is.read(buf);
4680                 if (len < 0)
4681                     break;
4682                 os.write(buf, 0, len);
4683             }
4684             is.close();
4685             os.close();
4686         } catch (IOException e) {
4687             return false;
4688         } finally {
4689             try {
4690                 if (is != null) {
4691                     is.close();
4692                 }
4693             } catch (Exception e) {
4694                 // Ignore
4695             }
4696             try {
4697                 if (os != null) {
4698                     os.close();
4699                 }
4700             } catch (Exception e) {
4701                 // Ignore
4702             }
4703         }
4704         return true;
4705     }
4706 
4707 
4708     /**
4709      * Get naming context full name.
4710      */
4711     private String getNamingContextName() {
4712     if (namingContextName == null) {
4713         Container parent = getParent();
4714         if (parent == null) {
4715         namingContextName = getName();
4716         } else {
4717         Stack stk = new Stack();
4718         StringBuffer buff = new StringBuffer();
4719         while (parent != null) {
4720             stk.push(parent.getName());
4721             parent = parent.getParent();
4722         }
4723         while (!stk.empty()) {
4724             buff.append("/" + stk.pop());
4725         }
4726         buff.append(getName());
4727         namingContextName = buff.toString();
4728         }
4729     }
4730     return namingContextName;
4731     }
4732 
4733 
4734     /**
4735      * Return the request processing paused flag for this Context.
4736      */
4737     public boolean getPaused() {
4738 
4739         return (this.paused);
4740 
4741     }
4742 
4743 
4744     /**
4745      * Post a copy of our web application resources as a servlet context
4746      * attribute.
4747      */
4748     private void postResources() {
4749 
4750         getServletContext().setAttribute
4751             (Globals.RESOURCES_ATTR, getResources());
4752 
4753     }
4754 
4755 
4756     /**
4757      * Post a copy of our current list of welcome files as a servlet context
4758      * attribute, so that the default servlet can find them.
4759      */
4760     private void postWelcomeFiles() {
4761 
4762         getServletContext().setAttribute("org.apache.catalina.WELCOME_FILES",
4763                                          welcomeFiles);
4764 
4765     }
4766 
4767     public String getHostname() {
4768         Container parentHost = getParent();
4769         if (parentHost != null) {
4770             hostName = parentHost.getName();
4771         }
4772         if ((hostName == null) || (hostName.length() < 1))
4773             hostName = "_";
4774         return hostName;
4775     }
4776 
4777     /**
4778      * Set the appropriate context attribute for our work directory.
4779      */
4780     private void postWorkDirectory() {
4781 
4782         // Acquire (or calculate) the work directory path
4783         String workDir = getWorkDir();
4784         if (workDir == null) {
4785 
4786             // Retrieve our parent (normally a host) name
4787             String hostName = null;
4788             String engineName = null;
4789             String hostWorkDir = null;
4790             Container parentHost = getParent();
4791             if (parentHost != null) {
4792                 hostName = parentHost.getName();
4793                 if (parentHost instanceof StandardHost) {
4794                     hostWorkDir = ((StandardHost)parentHost).getWorkDir();
4795                 }
4796                 Container parentEngine = parentHost.getParent();
4797                 if (parentEngine != null) {
4798                    engineName = parentEngine.getName();
4799                 }
4800             }
4801             if ((hostName == null) || (hostName.length() < 1))
4802                 hostName = "_";
4803             if ((engineName == null) || (engineName.length() < 1))
4804                 engineName = "_";
4805 
4806             String temp = getPath();
4807             if (temp.startsWith("/"))
4808                 temp = temp.substring(1);
4809             temp = temp.replace('/', '_');
4810             temp = temp.replace('\\', '_');
4811             if (temp.length() < 1)
4812                 temp = "_";
4813             if (hostWorkDir != null ) {
4814                 workDir = hostWorkDir + File.separator + temp;
4815             } else {
4816                 workDir = "work" + File.separator + engineName +
4817                     File.separator + hostName + File.separator + temp;
4818             }
4819             setWorkDir(workDir);
4820         }
4821 
4822         // Create this directory if necessary
4823         File dir = new File(workDir);
4824         if (!dir.isAbsolute()) {
4825             File catalinaHome = engineBase();
4826             String catalinaHomePath = null;
4827             try {
4828                 catalinaHomePath = catalinaHome.getCanonicalPath();
4829                 dir = new File(catalinaHomePath, workDir);
4830             } catch (IOException e) {
4831             }
4832         }
4833         dir.mkdirs();
4834 
4835         // Set the appropriate servlet context attribute
4836         getServletContext().setAttribute(Globals.WORK_DIR_ATTR, dir);
4837         if (getServletContext() instanceof ApplicationContext)
4838             ((ApplicationContext) getServletContext()).setAttributeReadOnly
4839                 (Globals.WORK_DIR_ATTR);
4840 
4841     }
4842 
4843 
4844     /**
4845      * Set the request processing paused flag for this Context.
4846      *
4847      * @param paused The new request processing paused flag
4848      */
4849     private void setPaused(boolean paused) {
4850 
4851         this.paused = paused;
4852 
4853     }
4854 
4855 
4856     /**
4857      * Validate the syntax of a proposed <code>&lt;url-pattern&gt;</code>
4858      * for conformance with specification requirements.
4859      *
4860      * @param urlPattern URL pattern to be validated
4861      */
4862     private boolean validateURLPattern(String urlPattern) {
4863 
4864         if (urlPattern == null)
4865             return (false);
4866         if (urlPattern.startsWith("*.")) {
4867             if (urlPattern.indexOf('/') < 0)
4868                 return (true);
4869             else
4870                 return (false);
4871         }
4872         if ( (urlPattern.startsWith("/")) &&
4873                 (urlPattern.indexOf("*.") < 0))
4874             return (true);
4875         else
4876             return (false);
4877 
4878     }
4879 
4880 
4881     // ------------------------------------------------------------- Operations
4882 
4883 
4884     /**
4885      * JSR77 deploymentDescriptor attribute
4886      *
4887      * @return string deployment descriptor 
4888      */
4889     public String getDeploymentDescriptor() {
4890     
4891         InputStream stream = null;
4892         ServletContext servletContext = getServletContext();
4893         if (servletContext != null) {
4894             stream = servletContext.getResourceAsStream(
4895                 org.apache.catalina.startup.Constants.ApplicationWebXml);
4896         }
4897         if (stream == null) {
4898             return "";
4899         }
4900         BufferedReader br = new BufferedReader(
4901                                 new InputStreamReader(stream));
4902         StringBuffer sb = new StringBuffer();
4903         String strRead = "";
4904         try {
4905             while (strRead != null) {
4906                 sb.append(strRead);
4907                 strRead = br.readLine();
4908             }
4909         } catch (IOException e) {
4910             return "";
4911         }
4912 
4913         return sb.toString(); 
4914     
4915     }
4916     
4917     
4918     /**
4919      * JSR77 servlets attribute
4920      *
4921      * @return list of all servlets ( we know about )
4922      */
4923     public String[] getServlets() {
4924         
4925         String[] result = null;
4926 
4927         Container[] children = findChildren();
4928         if (children != null) {
4929             result = new String[children.length];
4930             for( int i=0; i< children.length; i++ ) {
4931                 result[i] = ((StandardWrapper)children[i]).getObjectName();
4932             }
4933         }
4934 
4935         return result;
4936     }
4937     
4938 
4939     public ObjectName createObjectName(String hostDomain, ObjectName parentName)
4940             throws MalformedObjectNameException
4941     {
4942         String onameStr;
4943         StandardHost hst=(StandardHost)getParent();
4944         
4945         String pathName=getName();
4946         String hostName=getParent().getName();
4947         String name= "//" + ((hostName==null)? "DEFAULT" : hostName) +
4948                 (("".equals(pathName))?"/":pathName );
4949 
4950         String suffix=",J2EEApplication=" +
4951                 getJ2EEApplication() + ",J2EEServer=" +
4952                 getJ2EEServer();
4953 
4954         onameStr="j2eeType=WebModule,name=" + name + suffix;
4955         if( log.isDebugEnabled())
4956             log.debug("Registering " + onameStr + " for " + oname);
4957         
4958         // default case - no domain explictely set.
4959         if( getDomain() == null ) domain=hst.getDomain();
4960 
4961         ObjectName oname=new ObjectName(getDomain() + ":" + onameStr);
4962         return oname;        
4963     }    
4964     
4965     private void preRegisterJMX() {
4966         try {
4967             StandardHost host = (StandardHost) getParent();
4968             if ((oname == null) 
4969                 || (oname.getKeyProperty("j2eeType") == null)) {
4970                 oname = createObjectName(host.getDomain(), host.getJmxName());
4971                 controller = oname;
4972             }
4973         } catch(Exception ex) {
4974             log.info("Error registering ctx with jmx " + this + " " +
4975                      oname + " " + ex.toString(), ex );
4976         }
4977     }
4978 
4979     private void registerJMX() {
4980         try {
4981             if (log.isDebugEnabled()) {
4982                 log.debug("Checking for " + oname );
4983             }
4984             if(! Registry.getRegistry(null, null)
4985                 .getMBeanServer().isRegistered(oname)) {
4986                 controller = oname;
4987                 Registry.getRegistry(null, null)
4988                     .registerComponent(this, oname, null);
4989                 
4990                 // Send j2ee.object.created notification 
4991                 if (this.getObjectName() != null) {
4992                     Notification notification = new Notification(
4993                                                         "j2ee.object.created", 
4994                                                         this.getObjectName(), 
4995                                                         sequenceNumber++);
4996                     broadcaster.sendNotification(notification);
4997                 }
4998             }
4999             Container children[] = findChildren();
5000             for (int i=0; children!=null && i<children.length; i++) {
5001                 ((StandardWrapper)children[i]).registerJMX( this );
5002             }
5003         } catch (Exception ex) {
5004             log.info("Error registering wrapper with jmx " + this + " " +
5005                     oname + " " + ex.toString(), ex );
5006         }
5007     }
5008 
5009     /** There are 2 cases:
5010      *   1.The context is created and registered by internal APIS
5011      *   2. The context is created by JMX, and it'll self-register.
5012      *
5013      * @param server The server
5014      * @param name The object name
5015      * @return ObjectName The name of the object
5016      * @throws Exception If an error occurs
5017      */
5018     public ObjectName preRegister(MBeanServer server,
5019                                   ObjectName name)
5020             throws Exception
5021     {
5022         if( oname != null ) {
5023             //log.info( "Already registered " + oname + " " + name);
5024             // Temporary - /admin uses the old names
5025             return name;
5026         }
5027         ObjectName result=super.preRegister(server,name);
5028         return name;
5029     }
5030 
5031     public void preDeregister() throws Exception {
5032         if( started ) {
5033             try {
5034                 stop();
5035             } catch( Exception ex ) {
5036                 log.error( "error stopping ", ex);
5037             }
5038         }
5039     }
5040 
5041     public void init() throws Exception {
5042 
5043         if( this.getParent() == null ) {
5044             ObjectName parentName=getParentName();
5045             
5046             if( ! mserver.isRegistered(parentName)) {
5047                 log.debug("No host, creating one " + parentName);
5048                 StandardHost host=new StandardHost();
5049                 host.setName(hostName);
5050                 host.setAutoDeploy(false);
5051                 Registry.getRegistry(null, null)
5052                     .registerComponent(host, parentName, null);
5053                 mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );
5054             }
5055             ContextConfig config = new ContextConfig();
5056             this.addLifecycleListener(config);
5057 
5058             log.debug( "AddChild " + parentName + " " + this);
5059             try {
5060                 mserver.invoke(parentName, "addChild", new Object[] { this },
5061                                new String[] {"org.apache.catalina.Container"});
5062             } catch (Exception e) {
5063                 destroy();
5064                 throw e;
5065             }
5066         }
5067         super.init();
5068         
5069         // Notify our interested LifecycleListeners
5070         lifecycle.fireLifecycleEvent(INIT_EVENT, null);
5071 
5072         // Send j2ee.state.starting notification 
5073         if (this.getObjectName() != null) {
5074             Notification notification = new Notification("j2ee.state.starting", 
5075                                                         this.getObjectName(), 
5076                                                         sequenceNumber++);
5077             broadcaster.sendNotification(notification);
5078         }
5079         
5080     }
5081 
5082     public ObjectName getParentName() throws MalformedObjectNameException {
5083         // "Life" update
5084         String path=oname.getKeyProperty("name");
5085         if( path == null ) {
5086             log.error( "No name attribute " +name );
5087             return null;
5088         }
5089         if( ! path.startsWith( "//")) {
5090             log.error("Invalid name " + name);
5091         }
5092         path=path.substring(2);
5093         int delim=path.indexOf( "/" );
5094         hostName="localhost"; // Should be default...
5095         if( delim > 0 ) {
5096             hostName=path.substring(0, delim);
5097             path = path.substring(delim);
5098             if (path.equals("/")) {
5099                 this.setName("");
5100             } else {
5101                 this.setName(path);
5102             }
5103         } else {
5104             log.debug("Setting path " +  path );
5105             this.setName( path );
5106         }
5107         // XXX The service and domain should be the same.
5108         String parentDomain=getEngineName();
5109         if( parentDomain == null ) parentDomain=domain;
5110         ObjectName parentName=new ObjectName( parentDomain + ":" +
5111                 "type=Host,host=" + hostName);
5112         return parentName;
5113     }
5114     
5115     public void create() throws Exception{
5116         init();
5117     }
5118 
5119     /* Remove a JMX notficationListener 
5120      * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
5121      */
5122     public void removeNotificationListener(NotificationListener listener, 
5123             NotificationFilter filter, Object object) throws ListenerNotFoundException {
5124         broadcaster.removeNotificationListener(listener,filter,object);
5125         
5126     }
5127     
5128     private MBeanNotificationInfo[] notificationInfo;
5129     
5130     /* Get JMX Broadcaster Info
5131      * @TODO use StringManager for international support!
5132      * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
5133      * @see javax.management.NotificationBroadcaster#getNotificationInfo()
5134      */
5135     public MBeanNotificationInfo[] getNotificationInfo() {
5136         // FIXME: i18n
5137         if(notificationInfo == null) {
5138             notificationInfo = new MBeanNotificationInfo[]{
5139                     new MBeanNotificationInfo(new String[] {
5140                     "j2ee.object.created"},
5141                     Notification.class.getName(),
5142                     "web application is created"
5143                     ), 
5144                     new MBeanNotificationInfo(new String[] {
5145                     "j2ee.state.starting"},
5146                     Notification.class.getName(),
5147                     "change web application is starting"
5148                     ),
5149                     new MBeanNotificationInfo(new String[] {
5150                     "j2ee.state.running"},
5151                     Notification.class.getName(),
5152                     "web application is running"
5153                     ),
5154                     new MBeanNotificationInfo(new String[] {
5155                     "j2ee.state.stopped"},
5156                     Notification.class.getName(),
5157                     "web application start to stopped"
5158                     ),
5159                     new MBeanNotificationInfo(new String[] {
5160                     "j2ee.object.stopped"},
5161                     Notification.class.getName(),
5162                     "web application is stopped"
5163                     ),
5164                     new MBeanNotificationInfo(new String[] {
5165                     "j2ee.object.deleted"},
5166                     Notification.class.getName(),
5167                     "web application is deleted"
5168                     )
5169             };
5170             
5171         }
5172         
5173         return notificationInfo;
5174     }
5175     
5176     
5177     /* Add a JMX-NotificationListener
5178      * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
5179      */
5180     public void addNotificationListener(NotificationListener listener, 
5181             NotificationFilter filter, Object object) throws IllegalArgumentException {
5182         broadcaster.addNotificationListener(listener,filter,object);
5183         
5184     }
5185     
5186     
5187     /**
5188      * Remove a JMX-NotificationListener 
5189      * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
5190      */
5191     public void removeNotificationListener(NotificationListener listener) 
5192     throws ListenerNotFoundException {
5193         broadcaster.removeNotificationListener(listener);
5194         
5195     }
5196     
5197     
5198     // ------------------------------------------------------------- Attributes
5199 
5200 
5201     /**
5202      * Return the naming resources associated with this web application.
5203      */
5204     public javax.naming.directory.DirContext getStaticResources() {
5205 
5206         return getResources();
5207 
5208     }
5209 
5210 
5211     /**
5212      * Return the naming resources associated with this web application.
5213      * FIXME: Fooling introspection ... 
5214      */
5215     public javax.naming.directory.DirContext findStaticResources() {
5216 
5217         return getResources();
5218 
5219     }
5220 
5221 
5222     /**
5223      * Return the naming resources associated with this web application.
5224      */
5225     public String[] getWelcomeFiles() {
5226 
5227         return findWelcomeFiles();
5228 
5229     }
5230 
5231      /**
5232      * Set the validation feature of the XML parser used when
5233      * parsing xml instances.
5234      * @param webXmlValidation true to enable xml instance validation
5235      */
5236     public void setXmlValidation(boolean webXmlValidation){
5237         
5238         this.webXmlValidation = webXmlValidation;
5239 
5240     }
5241 
5242     /**
5243      * Get the server.xml <context> attribute's xmlValidation.
5244      * @return true if validation is enabled.
5245      *
5246      */
5247     public boolean getXmlValidation(){
5248         return webXmlValidation;
5249     }
5250 
5251 
5252     /**
5253      * Get the server.xml <context> attribute's xmlNamespaceAware.
5254      * @return true if namespace awarenes is enabled.
5255      */
5256     public boolean getXmlNamespaceAware(){
5257         return webXmlNamespaceAware;
5258     }
5259 
5260 
5261     /**
5262      * Set the namespace aware feature of the XML parser used when
5263      * parsing xml instances.
5264      * @param webXmlNamespaceAware true to enable namespace awareness
5265      */
5266     public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
5267         this.webXmlNamespaceAware= webXmlNamespaceAware;
5268     }    
5269 
5270 
5271     /**
5272      * Set the validation feature of the XML parser used when
5273      * parsing tlds files. 
5274      * @param tldValidation true to enable xml instance validation
5275      */
5276     public void setTldValidation(boolean tldValidation){
5277         
5278         this.tldValidation = tldValidation;
5279 
5280     }
5281 
5282     /**
5283      * Get the server.xml <context> attribute's webXmlValidation.
5284      * @return true if validation is enabled.
5285      *
5286      */
5287     public boolean getTldValidation(){
5288         return tldValidation;
5289     }
5290 
5291 
5292     /**
5293      * Get the server.xml <host> attribute's xmlNamespaceAware.
5294      * @return true if namespace awarenes is enabled.
5295      */
5296     public boolean getTldNamespaceAware(){
5297         return tldNamespaceAware;
5298     }
5299 
5300 
5301     /**
5302      * Set the namespace aware feature of the XML parser used when
5303      * parsing xml instances.
5304      * @param tldNamespaceAware true to enable namespace awareness
5305      */
5306     public void setTldNamespaceAware(boolean tldNamespaceAware){
5307         this.tldNamespaceAware= tldNamespaceAware;
5308     }    
5309 
5310 
5311     /** 
5312      * Support for "stateManageable" JSR77 
5313      */
5314     public boolean isStateManageable() {
5315         return true;
5316     }
5317     
5318     public void startRecursive() throws LifecycleException {
5319         // nothing to start recursive, the servlets will be started by load-on-startup
5320         start();
5321     }
5322     
5323     public int getState() {
5324         if( started ) {
5325             return 1; // RUNNING
5326         }
5327         if( initialized ) {
5328             return 0; // starting ? 
5329         }
5330         if( ! available ) { 
5331             return 4; //FAILED
5332         }
5333         // 2 - STOPPING
5334         return 3; // STOPPED
5335     }
5336     
5337     /**
5338      * The J2EE Server ObjectName this module is deployed on.
5339      */     
5340     private String server = null;
5341     
5342     /**
5343      * The Java virtual machines on which this module is running.
5344      */       
5345     private String[] javaVMs = null;
5346     
5347     public String getServer() {
5348         return server;
5349     }
5350         
5351     public String setServer(String server) {
5352         return this.server=server;
5353     }
5354         
5355     public String[] getJavaVMs() {
5356         return javaVMs;
5357     }
5358         
5359     public String[] setJavaVMs(String[] javaVMs) {
5360         return this.javaVMs = javaVMs;
5361     }
5362     
5363     public long getStartTime() {
5364         return startupTime;
5365     }
5366     
5367     public boolean isEventProvider() {
5368         return false;
5369     }
5370     
5371     public boolean isStatisticsProvider() {
5372         return false;
5373     }
5374     
5375 }

            
All Examples in File:
Example
Line
Rating (found
useful by...)
2644 0% of 0
2675 0% of 0
2755 0% of 0
2784 0% of 0
2818 0% of 0
3501 0% of 0
3536 0% of 0