/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.catalina.core;
/** * Standard implementation of the <b>Host</b> interface. Each child container must be a Context implementation to * process the requests directed to a particular web application. * * @author Craig R. McClanahan * @author Remy Maucherat
*/ publicclass StandardHost extends ContainerBase implements Host {
/** * The auto deploy flag for this Host.
*/ privateboolean autoDeploy = true;
/** * The Java class name of the default context configuration class for deployed web applications.
*/ private String configClass = "org.apache.catalina.startup.ContextConfig";
/** * The Java class name of the default Context implementation class for deployed web applications.
*/ private String contextClass = "org.apache.catalina.core.StandardContext";
/** * The deploy on startup flag for this Host.
*/ privateboolean deployOnStartup = true;
/** * Should XML files be copied to $CATALINA_BASE/conf/<engine>/<host> by default when a web application * is deployed?
*/ privateboolean copyXML = false;
/** * The Java class name of the default error reporter implementation class for deployed web applications.
*/ private String errorReportValveClass = "org.apache.catalina.valves.ErrorReportValve";
/** * Work Directory base for applications.
*/ private String workDir = null;
/** * Should we create directories upon startup for appBase and xmlBase
*/ privateboolean createDirs = true;
/** * Track the class loaders for the child web applications so memory leaks can be detected.
*/ privatefinal Map<ClassLoader,String> childClassLoaders = new WeakHashMap<>();
/** * Any file or directory in {@link #appBase} that this pattern matches will be ignored by the automatic deployment * process (both {@link #deployOnStartup} and {@link #autoDeploy}).
*/ private Pattern deployIgnore = null;
/** * @return <code>true</code> if the Host will attempt to create directories for appBase and xmlBase unless they * already exist.
*/
@Override publicboolean getCreateDirs() { return createDirs;
}
/** * Set to <code>true</code> if the Host should attempt to create directories for xmlBase and appBase upon startup * * @param createDirs the new flag value
*/
@Override publicvoid setCreateDirs(boolean createDirs) { this.createDirs = createDirs;
}
/** * @return the value of the auto deploy flag. If true, it indicates that this host's child webapps will be * dynamically deployed.
*/
@Override publicboolean getAutoDeploy() { returnthis.autoDeploy;
}
/** * Set the auto deploy flag value for this host. * * @param autoDeploy The new auto deploy flag
*/
@Override publicvoid setAutoDeploy(boolean autoDeploy) {
/** * @return the Java class name of the context configuration class for new web applications.
*/
@Override public String getConfigClass() { returnthis.configClass;
}
/** * Set the Java class name of the context configuration class for new web applications. * * @param configClass The new context configuration class
*/
@Override publicvoid setConfigClass(String configClass) {
/** * @return the Java class name of the Context implementation class for new web applications.
*/ public String getContextClass() { returnthis.contextClass;
}
/** * Set the Java class name of the Context implementation class for new web applications. * * @param contextClass The new context implementation class
*/ publicvoid setContextClass(String contextClass) {
/** * @return the value of the deploy on startup flag. If <code>true</code>, it indicates that this host's child * webapps should be discovered and automatically deployed at startup time.
*/
@Override publicboolean getDeployOnStartup() { returnthis.deployOnStartup;
}
/** * Set the deploy on startup flag value for this host. * * @param deployOnStartup The new deploy on startup flag
*/
@Override publicvoid setDeployOnStartup(boolean deployOnStartup) {
/** * @return <code>true</code> if XML context descriptors should be deployed.
*/ publicboolean isDeployXML() { return deployXML;
}
/** * Deploy XML Context config files flag mutator. * * @param deployXML <code>true</code> if context descriptors should be deployed
*/ publicvoid setDeployXML(boolean deployXML) { this.deployXML = deployXML;
}
/** * @return the copy XML config file flag for this component.
*/ publicboolean isCopyXML() { returnthis.copyXML;
}
/** * Set the copy XML config file flag for this component. * * @param copyXML The new copy XML flag
*/ publicvoid setCopyXML(boolean copyXML) { this.copyXML = copyXML;
}
/** * @return the Java class name of the error report valve class for new web applications.
*/ public String getErrorReportValveClass() { returnthis.errorReportValveClass;
}
/** * Set the Java class name of the error report valve class for new web applications. * * @param errorReportValveClass The new error report valve class
*/ publicvoid setErrorReportValveClass(String errorReportValveClass) {
/** * @return the canonical, fully qualified, name of the virtual host this Container represents.
*/
@Override public String getName() { return name;
}
/** * Set the canonical, fully qualified, name of the virtual host this Container represents. * * @param name Virtual host name * * @exception IllegalArgumentException if name is null
*/
@Override publicvoid setName(String name) {
if (name == null) { thrownew IllegalArgumentException(sm.getString("standardHost.nullName"));
}
name = name.toLowerCase(Locale.ENGLISH); // Internally all names are lower case
/** * @return <code>true</code> if WARs should be unpacked on deployment.
*/ publicboolean isUnpackWARs() { return unpackWARs;
}
/** * Unpack WARs flag mutator. * * @param unpackWARs <code>true</code> to unpack WARs on deployment
*/ publicvoid setUnpackWARs(boolean unpackWARs) { this.unpackWARs = unpackWARs;
}
/** * @return host work directory base.
*/ public String getWorkDir() { return workDir;
}
/** * Set host work directory base. * * @param workDir the new base work folder for this host
*/ publicvoid setWorkDir(String workDir) { this.workDir = workDir;
}
/** * @return the regular expression that defines the files and directories in the host's {@link #getAppBase} that will * be ignored by the automatic deployment process.
*/
@Override public String getDeployIgnore() { if (deployIgnore == null) { returnnull;
} returnthis.deployIgnore.toString();
}
/** * @return the compiled regular expression that defines the files and directories in the host's {@link #getAppBase} * that will be ignored by the automatic deployment process.
*/
@Override public Pattern getDeployIgnorePattern() { returnthis.deployIgnore;
}
/** * Set the regular expression that defines the files and directories in the host's {@link #getAppBase} that will be * ignored by the automatic deployment process. * * @param deployIgnore the regexp
*/
@Override publicvoid setDeployIgnore(String deployIgnore) {
String oldDeployIgnore; if (this.deployIgnore == null) {
oldDeployIgnore = null;
} else {
oldDeployIgnore = this.deployIgnore.toString();
} if (deployIgnore == null) { this.deployIgnore = null;
} else { this.deployIgnore = Pattern.compile(deployIgnore);
}
support.firePropertyChange("deployIgnore", oldDeployIgnore, deployIgnore);
}
/** * @return <code>true</code> if a webapp start should fail if a Servlet startup fails
*/ publicboolean isFailCtxIfServletStartFails() { return failCtxIfServletStartFails;
}
/** * Change the behavior of Servlet startup errors on web application starts. * * @param failCtxIfServletStartFails <code>false</code> to ignore errors on Servlets which are stated when the web * application starts
*/ publicvoid setFailCtxIfServletStartFails(boolean failCtxIfServletStartFails) { boolean oldFailCtxIfServletStartFails = this.failCtxIfServletStartFails; this.failCtxIfServletStartFails = failCtxIfServletStartFails;
support.firePropertyChange("failCtxIfServletStartFails", oldFailCtxIfServletStartFails,
failCtxIfServletStartFails);
}
// --------------------------------------------------------- Public Methods
/** * Add an alias name that should be mapped to this same Host. * * @param alias The alias to be added
*/
@Override publicvoid addAlias(String alias) {
alias = alias.toLowerCase(Locale.ENGLISH);
synchronized (aliasesLock) { // Skip duplicate aliases for (String s : aliases) { if (s.equals(alias)) { return;
}
} // Add this alias to the list
String newAliases[] = Arrays.copyOf(aliases, aliases.length + 1);
newAliases[aliases.length] = alias;
aliases = newAliases;
} // Inform interested listeners
fireContainerEvent(ADD_ALIAS_EVENT, alias);
}
/** * Add a child Container, only if the proposed child is an implementation of Context. * * @param child Child container to be added
*/
@Override publicvoid addChild(Container child) {
if (!(child instanceof Context)) { thrownew IllegalArgumentException(sm.getString("standardHost.notContext"));
}
// Avoid NPE for case where Context is defined in server.xml with only a // docBase
Context context = (Context) child; if (context.getPath() == null) {
ContextName cn = new ContextName(context.getDocBase(), true);
context.setPath(cn.getPath());
}
super.addChild(child);
}
/** * Used to ensure the regardless of {@link Context} implementation, a record is kept of the class loader used every * time a context starts.
*/ privateclass MemoryLeakTrackingListener implements LifecycleListener {
@Override publicvoid lifecycleEvent(LifecycleEvent event) { if (event.getType().equals(AFTER_START_EVENT)) { if (event.getSource() instanceof Context) {
Context context = ((Context) event.getSource());
childClassLoaders.put(context.getLoader().getClassLoader(),
context.getServletContext().getContextPath());
}
}
}
}
/** * Attempt to identify the contexts that have a class loader memory leak. This is usually triggered on context * reload. Note: This method attempts to force a full garbage collection. This should be used with extreme caution * on a production system. * * @return a list of possibly leaking contexts
*/ public String[] findReloadedContextMemoryLeaks() {
System.gc();
List<String> result = new ArrayList<>();
for (Map.Entry<ClassLoader,String> entry : childClassLoaders.entrySet()) {
ClassLoader cl = entry.getKey(); if (cl instanceof WebappClassLoaderBase) { if (!((WebappClassLoaderBase) cl).getState().isAvailable()) {
result.add(entry.getValue());
}
}
}
return result.toArray(new String[0]);
}
/** * @return the set of alias names for this Host. If none are defined, a zero length array is returned.
*/
@Override public String[] findAliases() { synchronized (aliasesLock) { returnthis.aliases;
}
}
/** * Remove the specified alias name from the aliases for this Host. * * @param alias Alias name to be removed
*/
@Override publicvoid removeAlias(String alias) {
alias = alias.toLowerCase(Locale.ENGLISH);
synchronized (aliasesLock) {
// Make sure this alias is currently present int n = -1; for (int i = 0; i < aliases.length; i++) { if (aliases[i].equals(alias)) {
n = i; break;
}
} if (n < 0) { return;
}
// Remove the specified alias int j = 0;
String results[] = new String[aliases.length - 1]; for (int i = 0; i < aliases.length; i++) { if (i != n) {
results[j++] = aliases[i];
}
}
aliases = results;
/** * Start this component and implement the requirements of * {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error that prevents this component from being * used
*/
@Override protectedsynchronizedvoid startInternal() throws LifecycleException {
// Set error report valve
String errorValve = getErrorReportValveClass(); if ((errorValve != null) && (!errorValve.equals(""))) { try { boolean found = false;
Valve[] valves = getPipeline().getValves(); for (Valve valve : valves) { if (errorValve.equals(valve.getClass().getName())) {
found = true; break;
}
} if (!found) {
Valve valve = ErrorReportValve.class.getName().equals(errorValve) ? new ErrorReportValve() :
(Valve) Class.forName(errorValve).getConstructor().newInstance();
getPipeline().addValve(valve);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("standardHost.invalidErrorReportValveClass", errorValve), t);
}
} super.startInternal();
}
// -------------------- JMX -------------------- /** * @return the MBean Names of the Valves associated with this Host * * @exception Exception if an MBean cannot be created or registered
*/ public String[] getValveNames() throws Exception {
Valve[] valves = this.getPipeline().getValves();
String[] mbeanNames = new String[valves.length]; for (int i = 0; i < valves.length; i++) { if (valves[i] instanceof JmxEnabled) {
ObjectName oname = ((JmxEnabled) valves[i]).getObjectName(); if (oname != null) {
mbeanNames[i] = oname.toString();
}
}
}
StringBuilder keyProperties = new StringBuilder("type=Host");
keyProperties.append(getMBeanKeyProperties());
return keyProperties.toString();
}
}
¤ 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.0.20Bemerkung:
(vorverarbeitet)
¤
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 ist noch experimentell.