/** *CreateanewStandardContextcomponentwiththedefaultbasicValve.
*/ public StandardContext() {
super();
pipeline.setBasic(new StandardContextValve());
broadcaster = new NotificationBroadcasterSupport(); // Set defaults if (!Globals.STRICT_SERVLET_COMPLIANCE) { // Strict servlet compliance requires all extension mapped servlets // to be checked against welcome files
resourceOnlyServlets.add("jsp");
}
}
/** *@returntheLocaletocharactersetmapperforthisContext.
*/ public CharsetMapper getCharsetMapper() {
// Create a mapper the first time it is requested if (this.charsetMapper == null) { try { Class<?> clazz = Class.forName(charsetMapperClass); this.charsetMapper = (CharsetMapper) clazz.getConstructor().newInstance();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t); this.charsetMapper = new CharsetMapper();
}
}
// Process the property setting change
NamingResourcesImpl oldNamingResources = this.namingResources; this.namingResources = namingResources; if (namingResources != null) {
namingResources.setContainer(this);
}
support.firePropertyChange("namingResources", oldNamingResources, this.namingResources);
if (getState() == LifecycleState.NEW || getState() == LifecycleState.INITIALIZING ||
getState() == LifecycleState.INITIALIZED) { // NEW will occur if Context is defined in server.xml // At this point getObjectKeyPropertiesNameOnly() will trigger an // NPE. // INITIALIZED will occur if the Context is defined in a context.xml // file // If started now, a second start will be attempted when the context // starts
// In both cases, return and let context init the namingResources // when it starts return;
}
/**
* @return the value of the swallowOutput flag.
*/
@Override
public boolean getSwallowOutput() {
return this.swallowOutput;
}
/**
* Set the value of the swallowOutput flag. If set to true, the system.out and system.err will be redirected to the
* logger during a servlet execution.
*
* @param swallowOutput The new value
*/
@Override
public void setSwallowOutput(boolean swallowOutput) {
/**
* @return the value of the unloadDelay flag.
*/
public long getUnloadDelay() {
return this.unloadDelay;
}
/**
* Set the value of the unloadDelay flag, which represents the amount of ms that the container will wait when
* unloading servlets. Setting this to a small value may cause more requests to fail to complete when stopping a web
* application.
*
* @param unloadDelay The new value
*/
public void setUnloadDelay(long unloadDelay) {
long oldUnloadDelay = this.unloadDelay;
this.unloadDelay = unloadDelay;
support.firePropertyChange("unloadDelay", Long.valueOf(oldUnloadDelay), Long.valueOf(this.unloadDelay));
}
/**
* @return unpack WAR flag.
*/
public boolean getUnpackWAR() {
return unpackWAR;
}
/**
* Unpack WAR flag mutator.
*
* @param unpackWAR <code>true</code> to unpack WARs on deployment
*/
public void setUnpackWAR(boolean unpackWAR) {
this.unpackWAR = unpackWAR;
}
/**
* Flag which indicates if bundled context.xml files should be copied to the config folder. The doesn't occur by
* default.
*
* @return <code>true</code> if the <code>META-INF/context.xml</code> file included in a WAR will be copied to the
* host configuration base folder on deployment
*/
public boolean getCopyXML() {
return copyXML;
}
/**
* Allows copying a bundled context.xml file to the host configuration base folder on deployment.
*
* @param copyXML the new flag value
*/
public void setCopyXML(boolean copyXML) {
this.copyXML = copyXML;
}
/**
* @return the Java class name of the Wrapper implementation used for servlets registered in this Context.
*/
@Override
public String getWrapperClass() {
return this.wrapperClassName;
}
/**
* Set the Java class name of the Wrapper implementation used for servlets registered in this Context.
*
* @param wrapperClassName The new wrapper class name
*
* @throws IllegalArgumentException if the specified wrapper class cannot be found or is not a subclass of
* StandardWrapper
*/
@Override
public void setWrapperClass(String wrapperClassName) {
this.wrapperClassName = wrapperClassName;
try {
wrapperClass = Class.forName(wrapperClassName);
if (!StandardWrapper.class.isAssignableFrom(wrapperClass)) {
throw new IllegalArgumentException(
sm.getString("standardContext.invalidWrapperClass", wrapperClassName));
}
} catch (ClassNotFoundException cnfe) {
throw new IllegalArgumentException(cnfe.getMessage());
}
}
@Override
public JspConfigDescriptor getJspConfigDescriptor() {
return jspConfigDescriptor;
}
@Override
public void setJspConfigDescriptor(JspConfigDescriptor descriptor) {
this.jspConfigDescriptor = descriptor;
}
@Override
public ThreadBindingListener getThreadBindingListener() {
return threadBindingListener;
}
@Override
public void setThreadBindingListener(ThreadBindingListener threadBindingListener) {
this.threadBindingListener = threadBindingListener;
}
// ------------------------------------------------------ Public Properties
/**
* @return whether or not an attempt to modify the JNDI context will trigger an exception or if the request will be
* ignored.
*/
public boolean getJndiExceptionOnFailedWrite() {
return jndiExceptionOnFailedWrite;
}
/**
* Controls whether or not an attempt to modify the JNDI context will trigger an exception or if the request will be
* ignored.
*
* @param jndiExceptionOnFailedWrite <code>false</code> to avoid an exception
*/
public void setJndiExceptionOnFailedWrite(boolean jndiExceptionOnFailedWrite) {
this.jndiExceptionOnFailedWrite = jndiExceptionOnFailedWrite;
}
/**
* @return the Locale to character set mapper class for this Context.
*/
public String getCharsetMapperClass() {
return this.charsetMapperClass;
}
/**
* Set the Locale to character set mapper class for this Context.
*
* @param mapper The new mapper class
*/
public void setCharsetMapperClass(String mapper) {
/**
* Get the absolute path to the work dir. To avoid duplication.
*
* @return The work path
*/
public String getWorkPath() {
if (getWorkDir() == null) {
return null;
}
File workDir = new File(getWorkDir());
if (!workDir.isAbsolute()) {
try {
workDir = new File(getCatalinaBase().getCanonicalFile(), getWorkDir());
} catch (IOException e) {
log.warn(sm.getString("standardContext.workPath", getName()), e);
}
}
return workDir.getAbsolutePath();
}
/**
* @return the work directory for this Context.
*/
public String getWorkDir() {
return this.workDir;
}
/**
* Set the work directory for this Context.
*
* @param workDir The new work directory
*/
public void setWorkDir(String workDir) {
this.workDir = workDir;
if (getState().isAvailable()) {
postWorkDirectory();
}
}
public boolean getClearReferencesRmiTargets() {
return this.clearReferencesRmiTargets;
}
/**
* @return the clearReferencesStopThreads flag for this Context.
*/
public boolean getClearReferencesStopThreads() {
return this.clearReferencesStopThreads;
}
/**
* Set the clearReferencesStopThreads feature for this Context.
*
* @param clearReferencesStopThreads The new flag value
*/
public void setClearReferencesStopThreads(boolean clearReferencesStopThreads) {
/**
* @return the clearReferencesStopTimerThreads flag for this Context.
*/
public boolean getClearReferencesStopTimerThreads() {
return this.clearReferencesStopTimerThreads;
}
/**
* Set the clearReferencesStopTimerThreads feature for this Context.
*
* @param clearReferencesStopTimerThreads The new flag value
*/
public void setClearReferencesStopTimerThreads(boolean clearReferencesStopTimerThreads) {
/**
* @return the clearReferencesHttpClientKeepAliveThread flag for this Context.
*/
public boolean getClearReferencesHttpClientKeepAliveThread() {
return this.clearReferencesHttpClientKeepAliveThread;
}
/**
* Set the clearReferencesHttpClientKeepAliveThread feature for this Context.
*
* @param clearReferencesHttpClientKeepAliveThread The new flag value
*/
public void setClearReferencesHttpClientKeepAliveThread(boolean clearReferencesHttpClientKeepAliveThread) {
this.clearReferencesHttpClientKeepAliveThread = clearReferencesHttpClientKeepAliveThread;
}
public boolean getRenewThreadsWhenStoppingContext() {
return this.renewThreadsWhenStoppingContext;
}
/**
* Add a new Listener class name to the set of Listeners configured for this application.
*
* @param listener Java class name of a listener class
*/
@Override
public void addApplicationListener(String listener) {
if (applicationListeners.addIfAbsent(listener)) {
fireContainerEvent("addApplicationListener", listener);
} else {
log.info(sm.getString("standardContext.duplicateListener", listener));
}
}
/**
* Add a new application parameter for this application.
*
* @param parameter The new application parameter
*/
@Override
public void addApplicationParameter(ApplicationParameter parameter) {
/**
* Add a child Container, only if the proposed child is an implementation of Wrapper.
*
* @param child Child container to be added
*
* @exception IllegalArgumentException if the proposed container is not an implementation of Wrapper
*/
@Override
public void addChild(Container child) {
// Global JspServlet
Wrapper oldJspServlet = null;
if (!(child instanceof Wrapper)) {
throw new IllegalArgumentException(sm.getString("standardContext.notWrapper"));
}
// Allow webapp to override JspServlet inherited from global web.xml.
if (isJspServlet) {
oldJspServlet = (Wrapper) findChild("jsp");
if (oldJspServlet != null) {
removeChild(oldJspServlet);
}
}
super.addChild(child);
if (isJspServlet && oldJspServlet != null) {
/*
* The webapp-specific JspServlet inherits all the mappings specified in the global web.xml, and may add
* additional ones.
*/
String[] jspMappings = oldJspServlet.findMappings();
for (int i = 0; jspMappings != null && i < jspMappings.length; i++) {
addServletMappingDecoded(jspMappings[i], child.getName());
}
}
}
/**
* Add a security constraint to the set for this web application.
*
* @param constraint the new security constraint
*/
@Override
public void addConstraint(SecurityConstraint constraint) {
// Validate the proposed constraint
SecurityCollection collections[] = constraint.findCollections();
for (SecurityCollection collection : collections) {
String patterns[] = collection.findPatterns();
for (int j = 0; j < patterns.length; j++) {
patterns[j] = adjustURLPattern(patterns[j]);
if (!validateURLPattern(patterns[j])) {
throw new IllegalArgumentException(
sm.getString("standardContext.securityConstraint.pattern", patterns[j]));
}
}
if (collection.findMethods().length > 0 && collection.findOmittedMethods().length > 0) {
throw new IllegalArgumentException(sm.getString("standardContext.securityConstraint.mixHttpMethod"));
}
}
// Add this constraint to the set for our web application
synchronized (constraintsLock) {
SecurityConstraint[] results = Arrays.copyOf(constraints, constraints.length + 1);
results[constraints.length] = constraint;
constraints = results;
}
}
/**
* Add an error page for the specified error or Java exception.
*
* @param errorPage The error page definition to be added
*/
@Override
public void addErrorPage(ErrorPage errorPage) {
// Validate the input parameters
if (errorPage == null) {
throw new IllegalArgumentException(sm.getString("standardContext.errorPage.required"));
}
String location = errorPage.getLocation();
if ((location != null) && !location.startsWith("/")) {
if (isServlet22()) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("standardContext.errorPage.warning", location));
}
errorPage.setLocation("/" + location);
} else {
throw new IllegalArgumentException(sm.getString("standardContext.errorPage.error", location));
}
}
/**
* Add a filter definition to this Context.
*
* @param filterDef The filter definition to be added
*/
@Override
public void addFilterDef(FilterDef filterDef) {
/**
* Add a filter mapping to this Context at the end of the current set of filter mappings.
*
* @param filterMap The filter mapping to be added
*
* @exception IllegalArgumentException if the specified filter name does not match an existing filter definition, or
* the filter mapping is malformed
*/
@Override
public void addFilterMap(FilterMap filterMap) {
validateFilterMap(filterMap);
// Add this filter mapping to our registered set
filterMaps.add(filterMap);
fireContainerEvent("addFilterMap", filterMap);
}
/**
* Add a filter mapping to this Context before the mappings defined in the deployment descriptor but after any other
* mappings added via this method.
*
* @param filterMap The filter mapping to be added
*
* @exception IllegalArgumentException if the specified filter name does not match an existing filter definition, or
* the filter mapping is malformed
*/
@Override
public void addFilterMapBefore(FilterMap filterMap) {
validateFilterMap(filterMap);
// Add this filter mapping to our registered set
filterMaps.addBefore(filterMap);
fireContainerEvent("addFilterMap", filterMap);
}
/**
* Validate the supplied FilterMap.
*
* @param filterMap the filter mapping
*/
private void validateFilterMap(FilterMap filterMap) {
// Validate the proposed filter mapping
String filterName = filterMap.getFilterName();
String[] servletNames = filterMap.getServletNames();
String[] urlPatterns = filterMap.getURLPatterns();
if (findFilterDef(filterName) == null) {
throw new IllegalArgumentException(sm.getString("standardContext.filterMap.name", filterName));
}
if (!filterMap.getMatchAllServletNames() && !filterMap.getMatchAllUrlPatterns() && (servletNames.length == 0) &&
(urlPatterns.length == 0)) {
throw new IllegalArgumentException(sm.getString("standardContext.filterMap.either"));
}
for (String urlPattern : urlPatterns) {
if (!validateURLPattern(urlPattern)) {
throw new IllegalArgumentException(sm.getString("standardContext.filterMap.pattern", urlPattern));
}
}
}
/**
* Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
*
* @param locale locale to map an encoding for
* @param encoding encoding to be used for a give locale
*/
@Override
public void addLocaleEncodingMappingParameter(String locale, String encoding) {
getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
}
/**
* Add a message destination for this web application.
*
* @param md New message destination
*/
public void addMessageDestination(MessageDestination md) {
/**
* Add a new MIME mapping, replacing any existing mapping for the specified extension.
*
* @param extension Filename extension being mapped
* @param mimeType Corresponding MIME type
*/
@Override
public void addMimeMapping(String extension, String mimeType) {
/**
* Add a new context initialization parameter.
*
* @param name Name of the new parameter
* @param value Value of the new parameter
*
* @exception IllegalArgumentException if the name or value is missing, or if this context initialization parameter
* has already been registered
*/
@Override
public void addParameter(String name, String value) {
// Validate the proposed context initialization parameter
if (name == null || value == null) {
throw new IllegalArgumentException(sm.getString("standardContext.parameter.required"));
}
// Add this parameter to our defined set if not already present
String oldValue = parameters.putIfAbsent(name, value);
if (oldValue != null) {
throw new IllegalArgumentException(sm.getString("standardContext.parameter.duplicate", name));
}
fireContainerEvent("addParameter", name);
}
/**
* Add a security role reference for this web application.
*
* @param role Security role used in the application
* @param link Actual security role to check for
*/
@Override
public void addRoleMapping(String role, String link) {
/**
* Add a new servlet mapping, replacing any existing mapping for the specified pattern.
*
* @param pattern URL pattern to be mapped
* @param name Name of the corresponding servlet to execute
* @param jspWildCard true if name identifies the JspServlet and pattern contains a wildcard; false otherwise
*
* @exception IllegalArgumentException if the specified servlet name is not known to this Context
*/
@Override
public void addServletMappingDecoded(String pattern, String name, boolean jspWildCard) {
// Validate the proposed mapping
if (findChild(name) == null) {
throw new IllegalArgumentException(sm.getString("standardContext.servletMap.name", name));
}
String adjustedPattern = adjustURLPattern(pattern);
if (!validateURLPattern(adjustedPattern)) {
throw new IllegalArgumentException(sm.getString("standardContext.servletMap.pattern", adjustedPattern));
}
// Add this mapping to our registered set
synchronized (servletMappingsLock) {
String name2 = servletMappings.get(adjustedPattern);
if (name2 != null) {
// Don't allow more than one servlet on the same pattern
Wrapper wrapper = (Wrapper) findChild(name2);
wrapper.removeMapping(adjustedPattern);
}
servletMappings.put(adjustedPattern, name);
}
Wrapper wrapper = (Wrapper) findChild(name);
wrapper.addMapping(adjustedPattern);
/**
* Add a new watched resource to the set recognized by this Context.
*
* @param name New watched resource file name
*/
@Override
public void addWatchedResource(String name) {
/**
* Add a new welcome file to the set recognized by this Context.
*
* @param name New welcome file name
*/
@Override
public void addWelcomeFile(String name) {
synchronized (welcomeFilesLock) {
// Welcome files from the application deployment descriptor
// completely replace those from the default conf/web.xml file
if (replaceWelcomeFiles) {
fireContainerEvent(CLEAR_WELCOME_FILES_EVENT, null);
welcomeFiles = new String[0];
setReplaceWelcomeFiles(false);
}
String[] results = Arrays.copyOf(welcomeFiles, welcomeFiles.length + 1);
results[welcomeFiles.length] = name;
welcomeFiles = results;
}
if (this.getState().equals(LifecycleState.STARTED)) {
fireContainerEvent(ADD_WELCOME_FILE_EVENT, name);
}
}
/**
* Add the classname of a LifecycleListener to be added to each Wrapper appended to this Context.
*
* @param listener Java class name of a LifecycleListener class
*/
@Override
public void addWrapperLifecycle(String listener) {
/**
* Add the classname of a ContainerListener to be added to each Wrapper appended to this Context.
*
* @param listener Java class name of a ContainerListener class
*/
@Override
public void addWrapperListener(String listener) {
/**
* Factory method to create and return a new Wrapper instance, of the Java implementation class appropriate for this
* Context implementation. The constructor of the instantiated Wrapper will have been called, but no properties will
* have been set.
*/
@Override
public Wrapper createWrapper() {
/**
* Return the set of application listener class names configured for this application.
*/
@Override
public String[] findApplicationListeners() {
return applicationListeners.toArray(new String[0]);
}
/**
* Return the set of application parameters for this application.
*/
@Override
public ApplicationParameter[] findApplicationParameters() {
/**
* Return the security constraints for this web application. If there are none, a zero-length array is returned.
*/
@Override
public SecurityConstraint[] findConstraints() {
return constraints;
}
/**
* Return the error page entry for the specified HTTP error code, if any; otherwise return <code>null</code>.
*
* @param errorCode Error code to look up
*/
@Override
public ErrorPage findErrorPage(int errorCode) {
return errorPageSupport.find(errorCode);
}
@Override
public ErrorPage findErrorPage(Throwable exceptionType) {
return errorPageSupport.find(exceptionType);
}
/**
* Return the set of defined error pages for all specified error codes and exception types.
*/
@Override
public ErrorPage[] findErrorPages() {
return errorPageSupport.findAll();
}
/**
* Return the filter definition for the specified filter name, if any; otherwise return <code>null</code>.
*
* @param filterName Filter name to look up
*/
@Override
public FilterDef findFilterDef(String filterName) {
synchronized (filterDefs) {
return filterDefs.get(filterName);
}
}
/**
* @return the set of defined filters for this Context.
*/
@Override
public FilterDef[] findFilterDefs() {
synchronized (filterDefs) {
return filterDefs.values().toArray(new FilterDef[0]);
}
}
/**
* @return the set of filter mappings for this Context.
*/
@Override
public FilterMap[] findFilterMaps() {
return filterMaps.asArray();
}
/**
* @return the message destination with the specified name, if any; otherwise, return <code>null</code>.
*
* @param name Name of the desired message destination
*/
public MessageDestination findMessageDestination(String name) {
synchronized (messageDestinations) {
return messageDestinations.get(name);
}
}
/**
* @return the set of defined message destinations for this web application. If none have been defined, a
* zero-length array is returned.
*/
public MessageDestination[] findMessageDestinations() {
synchronized (messageDestinations) {
return messageDestinations.values().toArray(new MessageDestination[0]);
}
}
/**
* @return the MIME type to which the specified extension is mapped, if any; otherwise return <code>null</code>.
*
* @param extension Extension to map to a MIME type
*/
@Override
public String findMimeMapping(String extension) {
return mimeMappings.get(extension.toLowerCase(Locale.ENGLISH));
}
/**
* @return the extensions for which MIME mappings are defined. If there are none, a zero-length array is returned.
*/
@Override
public String[] findMimeMappings() {
synchronized (mimeMappings) {
return mimeMappings.keySet().toArray(new String[0]);
}
}
/**
* @return the value for the specified context initialization parameter name, if any; otherwise return
* <code>null</code>.
*
* @param name Name of the parameter to return
*/
@Override
public String findParameter(String name) {
return parameters.get(name);
}
/**
* @return the names of all defined context initialization parameters for this Context. If no parameters are
* defined, a zero-length array is returned.
*/
@Override
public String[] findParameters() {
return parameters.keySet().toArray(new String[0]);
}
/**
* For the given security role (as used by an application), return the corresponding role name (as defined by the
* underlying Realm) if there is one. Otherwise, return the specified role unchanged.
*
* @param role Security role to map
*
* @return the role name
*/
@Override
public String findRoleMapping(String role) {
String realRole = null;
synchronized (roleMappings) {
realRole = roleMappings.get(role);
}
if (realRole != null) {
return realRole;
} else {
return role;
}
}
/**
* @return <code>true</code> if the specified security role is defined for this application; otherwise return
* <code>false</code>.
*
* @param role Security role to verify
*/
@Override
public boolean findSecurityRole(String role) {
synchronized (securityRolesLock) {
for (String securityRole : securityRoles) {
if (role.equals(securityRole)) {
return true;
}
}
}
return false;
}
/**
* @return the security roles defined for this application. If none have been defined, a zero-length array is
* returned.
*/
@Override
public String[] findSecurityRoles() {
synchronized (securityRolesLock) {
return securityRoles;
}
}
/**
* @return the servlet name mapped by the specified pattern (if any); otherwise return <code>null</code>.
*
* @param pattern Pattern for which a mapping is requested
*/
@Override
public String findServletMapping(String pattern) {
synchronized (servletMappingsLock) {
return servletMappings.get(pattern);
}
}
/**
* @return the patterns of all defined servlet mappings for this Context. If no mappings are defined, a zero-length
* array is returned.
*/
@Override
public String[] findServletMappings() {
synchronized (servletMappingsLock) {
return servletMappings.keySet().toArray(new String[0]);
}
}
/**
* @return <code>true</code> if the specified welcome file is defined for this Context; otherwise return
* <code>false</code>.
*
* @param name Welcome file to verify
*/
@Override
public boolean findWelcomeFile(String name) {
synchronized (welcomeFilesLock) {
for (String welcomeFile : welcomeFiles) {
if (name.equals(welcomeFile)) {
return true;
}
}
}
return false;
}
/**
* @return the set of watched resources for this Context. If none are defined, a zero length array will be returned.
*/
@Override
public String[] findWatchedResources() {
synchronized (watchedResourcesLock) {
return watchedResources;
}
}
/**
* @return the set of welcome files defined for this Context. If none are defined, a zero-length array is returned.
*/
@Override
public String[] findWelcomeFiles() {
synchronized (welcomeFilesLock) {
return welcomeFiles;
}
}
/**
* @return the set of LifecycleListener classes that will be added to newly created Wrappers automatically.
*/
@Override
public String[] findWrapperLifecycles() {
synchronized (wrapperLifecyclesLock) {
return wrapperLifecycles;
}
}
/**
* @return the set of ContainerListener classes that will be added to newly created Wrappers automatically.
*/
@Override
public String[] findWrapperListeners() {
synchronized (wrapperListenersLock) {
return wrapperListeners;
}
}
/**
* Reload this web application, if reloading is supported.
* <p>
* <b>IMPLEMENTATION NOTE</b>: This method is designed to deal with reloads required by changes to classes in the
* underlying repositories of our class loader and changes to the web.xml file. It does not handle changes to any
* context.xml file. If the context.xml has changed, you should stop this Context and create (and start) a new
* Context instance instead. Note that there is additional code in <code>CoyoteAdapter#postParseRequest()</code> to
* handle mapping requests to paused Contexts.
*
* @exception IllegalStateException if the <code>reloadable</code> property is set to <code>false</code>.
*/
@Override
public synchronized void reload() {
// Validate our current component state
if (!getState().isAvailable()) {
throw new IllegalStateException(sm.getString("standardContext.notStarted", getName()));
}
if (log.isInfoEnabled()) {
log.info(sm.getString("standardContext.reloadingStarted", getName()));
}
if (log.isInfoEnabled()) {
log.info(sm.getString("standardContext.reloadingCompleted", getName()));
}
}
/**
* Remove the specified application listener class from the set of listeners for this application.
*
* @param listener Java class name of the listener to be removed
*/
@Override
public void removeApplicationListener(String listener) {
if (applicationListeners.remove(listener)) {
// Inform interested listeners if the specified listener was present and has been removed
fireContainerEvent("removeApplicationListener", listener);
}
}
/**
* Remove the application parameter with the specified name from the set for this application.
*
* @param name Name of the application parameter to remove
*/
@Override
public void removeApplicationParameter(String name) {
synchronized (applicationParametersLock) {
// Make sure this parameter is currently present
int n = -1;
for (int i = 0; i < applicationParameters.length; i++) {
if (name.equals(applicationParameters[i].getName())) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified parameter
int j = 0;
ApplicationParameter results[] = new ApplicationParameter[applicationParameters.length - 1];
for (int i = 0; i < applicationParameters.length; i++) {
if (i != n) {
results[j++] = applicationParameters[i];
}
}
applicationParameters = results;
/**
* Add a child Container, only if the proposed child is an implementation of Wrapper.
*
* @param child Child container to be added
*
* @exception IllegalArgumentException if the proposed container is not an implementation of Wrapper
*/
@Override
public void removeChild(Container child) {
if (!(child instanceof Wrapper)) {
throw new IllegalArgumentException(sm.getString("standardContext.notWrapper"));
}
super.removeChild(child);
}
/**
* Remove the specified security constraint from this web application.
*
* @param constraint Constraint to be removed
*/
@Override
public void removeConstraint(SecurityConstraint constraint) {
synchronized (constraintsLock) {
// Make sure this constraint is currently present
int n = -1;
for (int i = 0; i < constraints.length; i++) {
if (constraints[i].equals(constraint)) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified constraint
int j = 0;
SecurityConstraint results[] = new SecurityConstraint[constraints.length - 1];
for (int i = 0; i < constraints.length; i++) {
if (i != n) {
results[j++] = constraints[i];
}
}
constraints = results;
/**
* Remove the error page for the specified error code or Java language exception, if it exists; otherwise, no action
* is taken.
*
* @param errorPage The error page definition to be removed
*/
@Override
public void removeErrorPage(ErrorPage errorPage) {
errorPageSupport.remove(errorPage);
fireContainerEvent("removeErrorPage", errorPage);
}
/**
* Remove the specified filter definition from this Context, if it exists; otherwise, no action is taken.
*
* @param filterDef Filter definition to be removed
*/
@Override
public void removeFilterDef(FilterDef filterDef) {
/**
* Remove a filter mapping from this Context.
*
* @param filterMap The filter mapping to be removed
*/
@Override
public void removeFilterMap(FilterMap filterMap) {
filterMaps.remove(filterMap);
// Inform interested listeners
fireContainerEvent("removeFilterMap", filterMap);
}
/**
* Remove any message destination with the specified name.
*
* @param name Name of the message destination to remove
*/
public void removeMessageDestination(String name) {
/**
* Remove the MIME mapping for the specified extension, if it exists; otherwise, no action is taken.
*
* @param extension Extension to remove the mapping for
*/
@Override
public void removeMimeMapping(String extension) {
/**
* Remove the context initialization parameter with the specified name, if it exists; otherwise, no action is taken.
*
* @param name Name of the parameter to remove
*/
@Override
public void removeParameter(String name) {
parameters.remove(name);
fireContainerEvent("removeParameter", name);
}
/**
* Remove any security role reference for the specified name
*
* @param role Security role (as used in the application) to remove
*/
@Override
public void removeRoleMapping(String role) {
/**
* Remove any security role with the specified name.
*
* @param role Security role to remove
*/
@Override
public void removeSecurityRole(String role) {
synchronized (securityRolesLock) {
// Make sure this security role is currently present
int n = -1;
for (int i = 0; i < securityRoles.length; i++) {
if (role.equals(securityRoles[i])) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified security role
int j = 0;
String results[] = new String[securityRoles.length - 1];
for (int i = 0; i < securityRoles.length; i++) {
if (i != n) {
results[j++] = securityRoles[i];
}
}
securityRoles = results;
/**
* Remove any servlet mapping for the specified pattern, if it exists; otherwise, no action is taken.
*
* @param pattern URL pattern of the mapping to remove
*/
@Override
public void removeServletMapping(String pattern) {
String name = null;
synchronized (servletMappingsLock) {
name = servletMappings.remove(pattern);
}
Wrapper wrapper = (Wrapper) findChild(name);
if (wrapper != null) {
wrapper.removeMapping(pattern);
}
fireContainerEvent("removeServletMapping", pattern);
}
/**
* Remove the specified watched resource name from the list associated with this Context.
*
* @param name Name of the watched resource to be removed
*/
@Override
public void removeWatchedResource(String name) {
synchronized (watchedResourcesLock) {
// Make sure this watched resource is currently present
int n = -1;
for (int i = 0; i < watchedResources.length; i++) {
if (watchedResources[i].equals(name)) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified watched resource
int j = 0;
String results[] = new String[watchedResources.length - 1];
for (int i = 0; i < watchedResources.length; i++) {
if (i != n) {
results[j++] = watchedResources[i];
}
}
watchedResources = results;
/**
* Remove the specified welcome file name from the list recognized by this Context.
*
* @param name Name of the welcome file to be removed
*/
@Override
public void removeWelcomeFile(String name) {
synchronized (welcomeFilesLock) {
// Make sure this welcome file is currently present
int n = -1;
for (int i = 0; i < welcomeFiles.length; i++) {
if (welcomeFiles[i].equals(name)) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified welcome file
int j = 0;
String results[] = new String[welcomeFiles.length - 1];
for (int i = 0; i < welcomeFiles.length; i++) {
if (i != n) {
results[j++] = welcomeFiles[i];
}
}
welcomeFiles = results;
}
// Inform interested listeners
if (this.getState().equals(LifecycleState.STARTED)) {
fireContainerEvent(REMOVE_WELCOME_FILE_EVENT, name);
}
}
/**
* Remove a class name from the set of LifecycleListener classes that will be added to newly created Wrappers.
*
* @param listener Class name of a LifecycleListener class to be removed
*/
@Override
public void removeWrapperLifecycle(String listener) {
synchronized (wrapperLifecyclesLock) {
// Make sure this lifecycle listener is currently present
int n = -1;
for (int i = 0; i < wrapperLifecycles.length; i++) {
if (wrapperLifecycles[i].equals(listener)) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified lifecycle listener
int j = 0;
String results[] = new String[wrapperLifecycles.length - 1];
for (int i = 0; i < wrapperLifecycles.length; i++) {
if (i != n) {
results[j++] = wrapperLifecycles[i];
}
}
wrapperLifecycles = results;
/**
* Remove a class name from the set of ContainerListener classes that will be added to newly created Wrappers.
*
* @param listener Class name of a ContainerListener class to be removed
*/
@Override
public void removeWrapperListener(String listener) {
synchronized (wrapperListenersLock) {
// Make sure this listener is currently present
int n = -1;
for (int i = 0; i < wrapperListeners.length; i++) {
if (wrapperListeners[i].equals(listener)) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified listener
int j = 0;
String results[] = new String[wrapperListeners.length - 1];
for (int i = 0; i < wrapperListeners.length; i++) {
if (i != n) {
results[j++] = wrapperListeners[i];
}
}
wrapperListeners = results;
/**
* Gets the cumulative processing times of all servlets in this StandardContext.
*
* @return Cumulative processing times of all servlets in this StandardContext
*/
public long getProcessingTime() {
long result = 0;
Container[] children = findChildren();
if (children != null) {
for (Container child : children) {
result += ((StandardWrapper) child).getProcessingTime();
}
}
return result;
}
/**
* Gets the maximum processing time of all servlets in this StandardContext.
*
* @return Maximum processing time of all servlets in this StandardContext
*/
public long getMaxTime() {
long result = 0;
long time;
Container[] children = findChildren();
if (children != null) {
for (Container child : children) {
time = ((StandardWrapper) child).getMaxTime();
if (time > result) {
result = time;
}
}
}
return result;
}
/**
* Gets the minimum processing time of all servlets in this StandardContext.
*
* @return Minimum processing time of all servlets in this StandardContext
*/
public long getMinTime() {
long result = -1;
long time;
Container[] children = findChildren();
if (children != null) {
for (Container child : children) {
time = ((StandardWrapper) child).getMinTime();
if (result < 0 || time < result) {
result = time;
}
}
}
return result;
}
/**
* Gets the cumulative request count of all servlets in this StandardContext.
*
* @return Cumulative request count of all servlets in this StandardContext
*
* @deprecated The return type will change to long in Tomcat 11 onwards. Callers of this method should switch to
* storing the result of calls to this method in a long value rather than an int.
*/
@Deprecated
public int getRequestCount() {
int result = 0;
Container[] children = findChildren();
if (children != null) {
for (Container child : children) {
result += ((StandardWrapper) child).getRequestCount();
}
}
return result;
}
/**
* Gets the cumulative error count of all servlets in this StandardContext.
*
* @return Cumulative error count of all servlets in this StandardContext
*
* @deprecated The return type will change to long in Tomcat 11 onwards. Callers of this method should switch to
* storing the result of calls to this method in a long value rather than an int.
*/
@Deprecated
public int getErrorCount() {
int result = 0;
Container[] children = findChildren();
if (children != null) {
for (Container child : children) {
result += ((StandardWrapper) child).getErrorCount();
}
}
return result;
}
/**
* Return the real path for a given virtual path, if possible; otherwise return <code>null</code>.
*
* @param path The path to the desired resource
*/
@Override
public String getRealPath(String path) {
// The WebResources API expects all paths to start with /. This is a
// special case for consistency with earlier Tomcat versions.
if ("".equals(path)) {
path = "/";
}
if (resources != null) {
try {
WebResource resource = resources.getResource(path);
String canonicalPath = resource.getCanonicalPath();
if (canonicalPath == null) {
return null;
} else if ((resource.isDirectory() && !canonicalPath.endsWith(File.separator) || !resource.exists()) &&
path.endsWith("/")) {
return canonicalPath + File.separatorChar;
} else {
return canonicalPath;
}
} catch (IllegalArgumentException iae) {
// ServletContext.getRealPath() does not allow this to be thrown
}
}
return null;
}
/**
* Hook to track which Servlets were created via {@link ServletContext#createServlet(Class)}.
*
* @param servlet the created Servlet
*/
public void dynamicServletCreated(Servlet servlet) {
createdServlets.add(servlet);
}
public boolean wasCreatedDynamicServlet(Servlet servlet) {
return createdServlets.contains(servlet);
}
/**
* A helper class to manage the filter mappings in a Context.
*/
private static final class ContextFilterMaps {
private final Object lock = new Object();
/**
* The set of filter mappings for this application, in the order they were defined in the deployment descriptor
* with additional mappings added via the {@link ServletContext} possibly both before and after those defined in
* the deployment descriptor.
*/
private FilterMap[] array = new FilterMap[0];
/**
* Filter mappings added via {@link ServletContext} may have to be inserted before the mappings in the
* deployment descriptor but must be inserted in the order the {@link ServletContext} methods are called. This
* isn't an issue for the mappings added after the deployment descriptor - they are just added to the end - but
* correctly the adding mappings before the deployment descriptor mappings requires knowing where the last
* 'before' mapping was added.
*/
private int insertPoint = 0;
/**
* @return The set of filter mappings
*/
public FilterMap[] asArray() {
synchronized (lock) {
return array;
}
}
/**
* Add a filter mapping at the end of the current set of filter mappings.
*
* @param filterMap The filter mapping to be added
*/
public void add(FilterMap filterMap) {
synchronized (lock) {
FilterMap results[] = Arrays.copyOf(array, array.length + 1);
results[array.length] = filterMap;
array = results;
}
}
/**
* Add a filter mapping before the mappings defined in the deployment descriptor but after any other mappings
* added via this method.
*
* @param filterMap The filter mapping to be added
*/
public void addBefore(FilterMap filterMap) {
synchronized (lock) {
FilterMap results[] = new FilterMap[array.length + 1];
System.arraycopy(array, 0, results, 0, insertPoint);
System.arraycopy(array, insertPoint, results, insertPoint + 1, array.length - insertPoint);
results[insertPoint] = filterMap;
array = results;
insertPoint++;
}
}
/**
* Remove a filter mapping.
*
* @param filterMap The filter mapping to be removed
*/
public void remove(FilterMap filterMap) {
synchronized (lock) {
// Make sure this filter mapping is currently present
int n = -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == filterMap) {
n = i;
break;
}
}
if (n < 0) {
return;
}
// Remove the specified filter mapping
FilterMap results[] = new FilterMap[array.length - 1];
System.arraycopy(array, 0, results, 0, n);
System.arraycopy(array, n + 1, results, n, (array.length - 1) - n);
array = results;
if (n < insertPoint) {
insertPoint--;
}
}
}
}
// --------------------------------------------------------- Public Methods
/**
* Configure and initialize the set of filters for this Context.
*
* @return <code>true</code> if all filter initialization completed successfully, or <code>false</code> otherwise.
*/
public boolean filterStart() {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Starting filters");
}
// Instantiate and record a FilterConfig for each defined filter
boolean ok = true;
synchronized (filterDefs) {
filterConfigs.clear();
for (Entry<String,FilterDef> entry : filterDefs.entrySet()) {
String name = entry.getKey();
if (getLogger().isDebugEnabled()) {
getLogger().debug(" Starting filter '" + name + "'");
}
try {
ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, entry.getValue());
filterConfigs.put(name, filterConfig);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error(sm.getString("standardContext.filterStart", name), t);
ok = false;
}
}
}
return ok;
}
/**
* Finalize and release the set of filters for this Context.
*
* @return <code>true</code> if all filter finalization completed successfully, or <code>false</code> otherwise.
*/
public boolean filterStop() {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Stopping filters");
}
// Release all Filter and FilterConfig instances
synchronized (filterDefs) {
for (Entry<String,ApplicationFilterConfig> entry : filterConfigs.entrySet()) {
if (getLogger().isDebugEnabled()) {
getLogger().debug(" Stopping filter '" + entry.getKey() + "'");
}
ApplicationFilterConfig filterConfig = entry.getValue();
filterConfig.release();
}
filterConfigs.clear();
}
return true;
}
/**
* Find and return the initialized <code>FilterConfig</code> for the specified filter name, if any; otherwise return
* <code>null</code>.
*
* @param name Name of the desired filter
*
* @return the filter config object
*/
public FilterConfig findFilterConfig(String name) {
synchronized (filterDefs) {
return filterConfigs.get(name);
}
}
/**
* Configure the set of instantiated application event listeners for this Context.
*
* @return <code>true</code> if all listeners wre initialized successfully, or <code>false</code> otherwise.
*/
public boolean listenerStart() {
if (log.isDebugEnabled()) {
log.debug("Configuring application event listeners");
}
// Instantiate the required listeners
String listeners[] = findApplicationListeners();
Object results[] = new Object[listeners.length];
boolean ok = true;
for (int i = 0; i < results.length; i++) {
if (getLogger().isDebugEnabled()) {
getLogger().debug(" Configuring event listener class '" + listeners[i] + "'");
}
try {
String listener = listeners[i];
results[i] = getInstanceManager().newInstance(listener);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error(sm.getString("standardContext.applicationListener", listeners[i]), t);
ok = false;
}
}
if (!ok) {
getLogger().error(sm.getString("standardContext.applicationSkipped"));
return false;
}
// Sort listeners in two arrays
List<Object> eventListeners = new ArrayList<>();
List<Object> lifecycleListeners = new ArrayList<>();
for (Object result : results) {
if ((result instanceof ServletContextAttributeListener) ||
(result instanceof ServletRequestAttributeListener) || (result instanceof ServletRequestListener) ||
(result instanceof HttpSessionIdListener) || (result instanceof HttpSessionAttributeListener)) {
eventListeners.add(result);
}
if ((result instanceof ServletContextListener) || (result instanceof HttpSessionListener)) {
lifecycleListeners.add(result);
}
}
// Listener instances may have been added directly to this Context by
// ServletContextInitializers and other code via the pluggability APIs. // Put them these listeners after the ones defined in web.xml and/or // annotations then overwrite the list of instances with the new, full // list.
eventListeners.addAll(Arrays.asList(getApplicationEventListeners()));
setApplicationEventListeners(eventListeners.toArray()); for (Object lifecycleListener : getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener); if (lifecycleListener instanceof ServletContextListener) {
noPluggabilityListeners.add(lifecycleListener);
}
}
setApplicationLifecycleListeners(lifecycleListeners.toArray());
// Send application start events
if (getLogger().isDebugEnabled()) {
getLogger().debug("Sending application start events");
}
// Ensure context is not null
getServletContext();
context.setNewServletContextListenerAllowed(false);
// Collect "load on startup" servlets that need to be initialized
TreeMap<Integer,ArrayList<Wrapper>> map = new TreeMap<>(); for (Container child : children) {
Wrapper wrapper = (Wrapper) child; int loadOnStartup = wrapper.getLoadOnStartup(); if (loadOnStartup < 0) { continue;
}
Integer key = Integer.valueOf(loadOnStartup);
map.computeIfAbsent(key, k -> new ArrayList<>()).add(wrapper);
}
// Load the collected "load on startup" servlets for (ArrayList<Wrapper> list : map.values()) { for (Wrapper wrapper : list) { try {
wrapper.load();
} catch (ServletException e) {
getLogger().error(
sm.getString("standardContext.loadOnStartup.loadException", getName(), wrapper.getName()),
StandardWrapper.getRootCause(e)); // NOTE: load errors (including a servlet that throws // UnavailableException from the init() method) are NOT // fatal to application startup // unless failCtxIfServletStartFails="true" is specified if (getComputedFailCtxIfServletStartFails()) { returnfalse;
}
}
}
} returntrue;
if (log.isDebugEnabled()) {
log.debug("Starting " + getBaseName());
}
// Send j2ee.state.starting notification if (this.getObjectName() != null) {
Notification notification = new Notification("j2ee.state.starting", this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
setConfigured(false); boolean ok = true;
// Currently this is effectively a NO-OP but needs to be called to // ensure the NamingResources follows the correct lifecycle if (namingResources != null) {
namingResources.start();
}
// Post work directory
postWorkDirectory();
// Add missing components as necessary if (getResources() == null) { // (1) Required by Loader if (log.isDebugEnabled()) {
log.debug("Configuring default Resources");
}
if (getLoader() == null) {
WebappLoader webappLoader = new WebappLoader();
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader);
}
// An explicit cookie processor hasn't been specified; use the default if (cookieProcessor == null) {
cookieProcessor = new Rfc6265CookieProcessor();
}
// Initialize character set mapper
getCharsetMapper();
try { if (ok) { // Start our subordinate components, if any
Loader loader = getLoader(); if (loader instanceof Lifecycle) {
((Lifecycle) loader).start();
}
// since the loader just started, the webapp classloader is now // created. if (loader.getClassLoader() instanceof WebappClassLoaderBase) {
WebappClassLoaderBase cl = (WebappClassLoaderBase) loader.getClassLoader();
cl.setClearReferencesRmiTargets(getClearReferencesRmiTargets());
cl.setClearReferencesStopThreads(getClearReferencesStopThreads());
cl.setClearReferencesStopTimerThreads(getClearReferencesStopTimerThreads());
cl.setClearReferencesHttpClientKeepAliveThread(getClearReferencesHttpClientKeepAliveThread());
cl.setClearReferencesObjectStreamClassCaches(getClearReferencesObjectStreamClassCaches());
cl.setClearReferencesThreadLocals(getClearReferencesThreadLocals());
cl.setSkipMemoryLeakChecksOnJvmShutdown(getSkipMemoryLeakChecksOnJvmShutdown());
}
// By calling unbindThread and bindThread in a row, we setup the // current Thread CCL to be the webapp classloader
unbindThread(oldCCL);
oldCCL = bindThread();
// Initialize logger again. Other components might have used it // too early, so it should be reset.
logger = null;
getLogger();
Realm realm = getRealmInternal(); if (null != realm) { if (realm instanceof Lifecycle) {
((Lifecycle) realm).start();
}
// Place the CredentialHandler into the ServletContext so // applications can have access to it. Wrap it in a "safe" // handler so application's can't modify it.
CredentialHandler safeHandler = new CredentialHandler() {
@Override publicboolean matches(String inputCredentials, String storedCredentials) { return getRealmInternal().getCredentialHandler().matches(inputCredentials,
storedCredentials);
}
// Start our child containers, if not already started for (Container child : findChildren()) { if (!child.getState().isAvailable()) {
child.start();
}
}
// Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
// Configure default manager if none was specified if (contextManager != null) { if (log.isDebugEnabled()) {
log.debug(sm.getString("standardContext.manager", contextManager.getClass().getName()));
}
setManager(contextManager);
}
if (manager != null && (getCluster() != null) && distributable) { // let the cluster know that there is a context that is distributable // and that it has its own manager
getCluster().registerManager(manager);
}
}
if (!getConfigured()) {
log.error(sm.getString("standardContext.configurationFail"));
ok = false;
}
// We put the resources into the servlet context if (ok) {
getServletContext().setAttribute(Globals.RESOURCES_ATTR, getResources());
// Create context attributes that will be required
getServletContext().setAttribute(JarScanner.class.getName(), getJarScanner());
// Make the version info available
getServletContext().setAttribute(Globals.WEBAPP_VERSION, getWebappVersion());
// Make the utility executor available if (!Globals.IS_SECURITY_ENABLED) {
getServletContext().setAttribute(ScheduledThreadPoolExecutor.class.getName(),
Container.getService(this).getServer().getUtilityExecutor());
}
}
// Set up the context init params
mergeParameters();
// Configure and call application event listeners if (ok) { if (!listenerStart()) {
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
}
// Check constraints for uncovered HTTP methods // Needs to be after SCIs and listeners as they may programmatically // change constraints if (ok) {
checkConstraintsForUncoveredMethods(findConstraints());
}
// Configure and call application filters if (ok) { if (!filterStart()) {
log.error(sm.getString("standardContext.filterFail"));
ok = false;
}
}
// Load and initialize all "load on startup" servlets if (ok) { if (!loadOnStartup(findChildren())) {
log.error(sm.getString("standardContext.servletFail"));
ok = false;
}
}
// Set available status depending upon startup success if (ok) { if (log.isDebugEnabled()) {
log.debug("Starting completed");
}
} else {
log.error(sm.getString("standardContext.startFailed", getName()));
}
startTime = System.currentTimeMillis();
// Send j2ee.state.running notification if (ok && (this.getObjectName() != null)) {
Notification notification = new Notification("j2ee.state.running", this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
// The WebResources implementation caches references to JAR files. On // some platforms these references may lock the JAR files. Since web // application start is likely to have read from lots of JARs, trigger // a clean-up now.
getResources().gc();
// Reinitializing if something went wrong if (!ok) {
setState(LifecycleState.FAILED); // Send j2ee.object.failed notification if (this.getObjectName() != null) {
Notification notification = new Notification("j2ee.object.failed", this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
} else {
setState(LifecycleState.STARTING);
}
}
// Send j2ee.state.stopping notification if (this.getObjectName() != null) {
Notification notification = new Notification("j2ee.state.stopping", this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
// Context has been removed from Mapper at this point (so no new // requests will be mapped) but is still available.
// Give the in progress async requests a chance to complete long limit = System.currentTimeMillis() + unloadDelay; while (inProgressAsyncCount.get() > 0 && System.currentTimeMillis() < limit) { try { Thread.sleep(50);
} catch (InterruptedException e) {
log.info(sm.getString("standardContext.stop.asyncWaitInterrupted"), e); break;
}
}
// Once the state is set to STOPPING, the Context will report itself as // not available and any in progress async requests will timeout
setState(LifecycleState.STOPPING);
// Finalize our character set mapper
setCharsetMapper(null);
// Normal container shutdown processing if (log.isDebugEnabled()) {
log.debug("Processing standard container shutdown");
}
// JNDI resources are unbound in CONFIGURE_STOP_EVENT so stop // naming resources before they are unbound since NamingResources // does a JNDI lookup to retrieve the resource. This needs to be // after the application has finished with the resource if (namingResources != null) {
namingResources.stop();
}
fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);
// Stop the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle && ((Lifecycle) pipeline).getState().isAvailable()) {
((Lifecycle) pipeline).stop();
}
// Clear all application-originated servlet context attributes if (context != null) {
context.clearAttributes();
}
// If in state NEW when destroy is called, the object name will never // have been set so the notification can't be created if (getObjectName() != null) { // Send j2ee.object.deleted notification
Notification notification = new Notification("j2ee.object.deleted", this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
if (namingResources != null) {
namingResources.destroy();
}
privatevoid resetContext() throws Exception { // Restore the original state ( pre reading web.xml in start ) // If you extend this - override this method and make sure to clean up
// Don't reset anything that is read from a <Context.../> element since // <Context .../> elements are read at initialisation will not be read // again for this object for (Container child : findChildren()) {
removeChild(child);
}
startupTime = 0;
startTime = 0;
tldScanTime = 0;
// Bugzilla 32867
distributable = false;
applicationListeners.clear();
applicationEventListenersList.clear();
applicationLifecycleListenersObjects = new Object[0];
jspConfigDescriptor = null;
SecurityConstraint[] securityConstraints = findConstraints(); for (SecurityConstraint securityConstraint : securityConstraints) {
SecurityCollection[] collections = securityConstraint.findCollections(); for (SecurityCollection collection : collections) { if (collection.findPattern(urlPattern)) { // First pattern found will indicate if there is a // conflict since for any given pattern all matching // constraints will be from either the descriptor or // not. It is not permitted to have a mixture if (collection.isFromDescriptor()) { // Skip this pattern
foundConflict = true;
conflicts.add(urlPattern); break;
} else { // Need to overwrite constraint for this pattern
collection.removePattern(urlPattern); // If the collection is now empty, remove it if (collection.findPatterns().length == 0) {
securityConstraint.removeCollection(collection);
}
}
}
}
// If the constraint now has no collections - remove it if (securityConstraint.findCollections().length == 0) {
removeConstraint(securityConstraint);
}
// No need to check other constraints for the current pattern // once a conflict has been found if (foundConflict) { break;
}
}
// Note: For programmatically added Servlets this may not be the // complete set of security constraints since additional // URL patterns can be added after the application has called // setSecurity. For all programmatically added servlets, the // #dynamicServletAdded() method sets a flag that ensures that // the constraints are re-evaluated before the servlet is // first used
// If the pattern did not conflict, add the new constraint(s). if (!foundConflict) {
SecurityConstraint[] newSecurityConstraints =
SecurityConstraint.createConstraints(servletSecurityElement, urlPattern); for (SecurityConstraint securityConstraint : newSecurityConstraints) {
addConstraint(securityConstraint);
}
}
}
if (isUseNaming()) { try {
ContextBindings.bindThread(this, getNamingToken());
} catch (NamingException e) { // Silent catch, as this is a normal case during the early // startup stages
}
}
returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
@java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13 publicvoidunbind(booleanusePrivilegedAction,ClassLoaderoriginalClassLoader){ if(originalClassLoader==null){ return; }
if(threadBindingListener!=null){ *ProcesstheSTARTeventforanassociated. threadBindingListener@java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13 Throwable){ .handleThrowable(t; } }
/**contextXml *@returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*/
Override publicboolean getPausedjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 return?clazz .forNamehost()
}
Object :instances) if (instance/
java.lang.StringIndexOutOfBoundsException: Index 112 out of bounds for length 29
}
(!instanceinstanceofServletRequestListener { continue;
}
ServletRequestListener listener = (ServletRequestListener
@java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
!pp) java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
if ((instances != null) &&java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ServletRequestEvent event = new java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
for (int i int j = (instances.length - .get)
continue;// More complicated than the ideal as the canonical path may or may
} if (!(instances[j] instanceof ServletRequestListener)) { continue; } else {
}
ServletRequestListener listener =(ServletRequestListener) instances[]
log.rror(sm.getString("hostConfig.deployDescriptor.blocked"java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77 voidremovePostConstructMethodStringclazz) {
postConstructMethods.remove(clazz);
fireContainerEvent("removePostConstructMethod", clazz);
}
@Override public String findPreDestroyMethod(String clazz) { return .get(File.(),cn.getBaseName());
}
@Override public Map<String,String> findPostConstructMethods() { return postConstructMethods;
}
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9 public Map<String,String> findPreDestroyMethods() { return preDestroyMethods;
}
/**
*/ protectedvoid postWorkDirectory()if(.isDirectory() java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
// Acquire (or calculate) the work directory path
String workDir}catch Throwablet){ if (workDir == null |throwt
String getBaseName); if (temp.startsWith("/")) {
temp = temp.substring(1);
}
tempLifecycleListenerlistener=(LifecycleListener clazz.getConstructor().newInstance(;
temp = temp.replace('\\', '_'); if (temp.length() <1 java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
=.ROOT_NAME
}
(hostWorkDir=null java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
workDir = hostWorkDir + File.separator + temp;
} else {
workDir = "work" + File.
}
setWorkDir(workDir;
}
// Create this directory if necessary
File dir = new File(workDir); if (!ir.isAbsolute() {
String catalinaHomePath try {
catalinaHomePath = getCatalinaBase().getCanonicalPath();
dir newFilecatalinaHomePath,workDir);
} catch (IOException e) {
log. ( migrationCandidate )java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63
}
} if (!dir.mkdirs() && !dir.isDirectory()) {
log.warn(sm.getString("standardContext. catch ( t
}
// Set the appropriate servlet context attributelogerror(.(".migrateAppthreaded.",e) if
getServletContext();
{
contextsetAttribute(ServletContextTEMPDIR,dir()
/java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
}
if (urlPattern == null)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 returnfalse;
} if (urlPattern.indexOf('\n' redeployResourcesglobalContextXml(java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 returnfalse;
} if(urlPatternequals") returntrue;
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9 if (urlPattern.startsWith("*.")) { if(.indexOf'' < 0
checkUnusualURLPattern(urlPattern); returntrue;
} else { if (.isDebugEnabled) {
}
} if (urlPatternjava.lang.StringIndexOutOfBoundsException: Index 80 out of bounds for length 80
checkUnusualURLPattern(urlPattern); returntrue;
} else { returnfalse;
}
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
/**!ocBaseFileisAbsolute)){ }
*/ privatevoid checkUnusualURLPattern(String urlPattern) { if (log.isInfoEnabled()) { // First group checks for '*' or '/foo*' style patterns // Second group checks for *.foo.bar style patterns if ((urlPattern.endsWith("*") &&
(urlPattern.length() < 2 | (app, null,);
urlPatternstartsWith"*" &urlPatternlength) 2& urlPatternlastIndexOf.)>1)
.(smgetString"." urlPattern ();
}
}
}
StringBuilder keyProperties = new StringBuilder("j2eeType=WebModule,");
keyProperties.append(getObjectKeyPropertiesNameOnly());
keyProperties.append(",=")java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
keyPropertiesappend()java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
keyProperties.append(",J2EEServer=");
update ;
keyPropertiestoString);
}
private String getObjectKeyPropertiesNameOnly() {
StringBuilder result = new StringBuilder("name=//");
String hostname = getParent().getName(); if (hostname == null) {
resultappend("DEFAULT";
} else {
result.append(hostname);
}
String contextName = getName(); if
result.append('/');
}
result.append(contextName);
/** *GetJMXBroadcasterInfo * *@seejavax.management.NotificationBroadcaster#returnfalse;
*/
@Override public MBeanNotificationInfo[] getNotificationInfo() { / FIXME: we not send j2ee.attribute.changed wenotsend .attribute. if (notificationInfo == null) {
notificationInfo = new MBeanNotificationInfo[] { new MBeanNotificationInfo(new String[] { "j2ee.object.created" }, Notification.class.getName(), "web application is created"), new MBeanNotificationInfo( "hostConfigcanonicalizing" host.getAppBaseFile) appname) e; "change web application is starting"), new MBeanNotificationInfo(new Stringjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 "web application is running"), new MBeanNotificationInfo(new String[] { "j2ee.state.stopping" }, Notification.class.getName(), "web application start to stopped"), new MBeanNotificationInfo } catch(IOExceptione){
webapplicationis stopped, new MBeanNotificationInfo(new String[] { "j2ee.object.deleted" }, Notification.class.getName(), "web application is deleted"), new MBeanNotificationInfo(new String[] { "j2ee.object.failed" }, Notification.class.getName(), "web
}
@Override publicgetXmlBlockExternal){ returnxmlBlockExternaljava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 }
@java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13 publicvoidsetTldValidation(booleantldValidation){ this.tldValidation=tldValidation; }
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.