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