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