/* * 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.startup;
/** * Startup/Shutdown shell program for Catalina. The following command line * options are recognized: * <ul> * <li><b>-config {pathname}</b> - Set the pathname of the configuration file * to be processed. If a relative path is specified, it will be * interpreted as relative to the directory pathname specified by the * "catalina.base" system property. [conf/server.xml]</li> * <li><b>-help</b> - Display usage information.</li> * <li><b>-nonaming</b> - Disable naming support.</li> * <li><b>configtest</b> - Try to test the config</li> * <li><b>start</b> - Start an instance of Catalina.</li> * <li><b>stop</b> - Stop the currently running instance of Catalina.</li> * </ul> * * @author Craig R. McClanahan * @author Remy Maucherat
*/ publicclass Catalina {
/** * The string manager for this package.
*/ protectedstaticfinal StringManager sm =
StringManager.getManager(Constants.Package);
/** * Use await.
*/ protectedboolean await = false;
/** * Pathname to the server configuration file.
*/ protected String configFile = SERVER_XML;
// XXX Should be moved to embedded /** * The shared extensions class loader for this server.
*/ protected ClassLoader parentClassLoader =
Catalina.class.getClassLoader();
/** * The server component we are starting or stopping.
*/ protected Server server = null;
/** * @return <code>true</code> if an exception should be thrown if an error * occurs during server init
*/ publicboolean getThrowOnInitFailure() { return throwOnInitFailure;
}
/** * Set the behavior regarding errors that could occur during server init. * @param throwOnInitFailure the new flag value
*/ publicvoid setThrowOnInitFailure(boolean throwOnInitFailure) { this.throwOnInitFailure = throwOnInitFailure;
}
/** * Set the shared extensions class loader. * * @param parentClassLoader The shared extensions class loader.
*/ publicvoid setParentClassLoader(ClassLoader parentClassLoader) { this.parentClassLoader = parentClassLoader;
}
public ClassLoader getParentClassLoader() { if (parentClassLoader != null) { return parentClassLoader;
} return ClassLoader.getSystemClassLoader();
}
/** * @return <code>true</code> if naming is enabled.
*/ publicboolean isUseNaming() { returnthis.useNaming;
}
/** * Enables or disables naming support. * * @param useNaming The new use naming value
*/ publicvoid setUseNaming(boolean useNaming) { this.useNaming = useNaming;
}
/** * Process the specified command line arguments. * * @param args Command line arguments to process * @return <code>true</code> if we should continue processing
*/ protectedboolean arguments(String args[]) {
/** * Return a File object representing our configuration file. * @return the main configuration file
*/ protected File configFile() {
File file = new File(configFile); if (!file.isAbsolute()) {
file = new File(Bootstrap.getCatalinaBase(), configFile);
} return file;
}
/** * Create and configure the Digester we will be using for startup. * @return the main digester to parse server.xml
*/ protected Digester createStartDigester() { // Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>(); // Ignore className on all elements
List<String> objectAttrs = new ArrayList<>();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs); // Ignore attribute added by Eclipse for its internal tracking
List<String> contextAttrs = new ArrayList<>();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs); // Ignore Connector attribute used internally but set on Server
List<String> connectorAttrs = new ArrayList<>();
connectorAttrs.add("portOffset");
fakeAttributes.put(Connector.class, connectorAttrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
// Configure the actions we will be using
digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");
digester.addSetProperties("Server");
digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");
digester.addObjectCreate("Server/Service/Listener", null, // MUST be specified in the element "className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate", new CertificateCreateRule());
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/Certificate", new String[]{"type"});
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate", "addCertificate", "org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/Listener", null, // MUST be specified in the element "className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol", null, // MUST be specified in the element "className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol", "addUpgradeProtocol", "org.apache.coyote.UpgradeProtocol");
// Add RuleSets for nested elements
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
/** * Create and configure the Digester we will be using for shutdown. * @return the digester to process the stop operation
*/ protected Digester createStopDigester() {
// Initialize the digester
Digester digester = new Digester();
digester.setUseContextClassLoader(true);
// Configure the rules we need for shutting down
digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");
digester.addSetProperties("Server");
digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");
Server s = getServer(); if (s == null) {
parseServerXml(false); if (getServer() == null) {
log.error(sm.getString("catalina.stopError"));
System.exit(1);
}
} else { // Server object already present. Must be running as a service try {
s.stop();
s.destroy();
} catch (LifecycleException e) {
log.error(sm.getString("catalina.stopError"), e);
} return;
}
// Stop the existing server
s = getServer(); if (s.getPortWithOffset() > 0) { try (Socket socket = new Socket(s.getAddress(), s.getPortWithOffset());
OutputStream stream = socket.getOutputStream()) {
String shutdown = s.getShutdown(); for (int i = 0; i < shutdown.length(); i++) {
stream.write(shutdown.charAt(i));
}
stream.flush();
} catch (ConnectException ce) {
log.error(sm.getString("catalina.stopServer.connectException", s.getAddress(),
String.valueOf(s.getPortWithOffset()), String.valueOf(s.getPort()),
String.valueOf(s.getPortOffset())));
log.error(sm.getString("catalina.stopError"), ce);
System.exit(1);
} catch (IOException e) {
log.error(sm.getString("catalina.stopError"), e);
System.exit(1);
}
} else {
log.error(sm.getString("catalina.stopServer"));
System.exit(1);
}
}
/** * Start a new server instance.
*/ publicvoid load() {
if (loaded) { return;
}
loaded = true;
long t1 = System.nanoTime();
// Before digester - it may be needed
initNaming();
// Parse main server.xml
parseServerXml(true);
Server s = getServer(); if (s == null) { return;
}
/** * Start a new server instance.
*/ publicvoid start() {
if (getServer() == null) {
load();
}
if (getServer() == null) {
log.fatal(sm.getString("catalina.noServer")); return;
}
long t1 = System.nanoTime();
// Start the new server try {
getServer().start();
} catch (LifecycleException e) {
log.fatal(sm.getString("catalina.serverStartFail"), e); try {
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
} return;
}
if (log.isInfoEnabled()) {
log.info(sm.getString("catalina.startup", Long.toString(TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - t1))));
}
if (generateCode) { // Generate loader which will load all generated classes
generateLoader();
}
// Register shutdown hook if (useShutdownHook) { if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
// If JULI is being used, disable JULI's shutdown hook since // shutdown hooks run in parallel and log messages may be lost // if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager.getLogManager(); if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook( false);
}
}
if (await) {
await();
stop();
}
}
/** * Stop an existing server instance.
*/ publicvoid stop() {
try { // Remove the ShutdownHook first so that server.stop() // doesn't get invoked twice if (useShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
// If JULI is being used, re-enable JULI's shutdown to ensure // log messages are not lost
LogManager logManager = LogManager.getLogManager(); if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook( true);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t); // This will fail on JDK 1.2. Ignoring, as Tomcat can run // fine without the shutdown hook.
}
// Shut down the server try {
Server s = getServer();
LifecycleState state = s.getState(); if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) { // Nothing to do. stop() was already called
} else {
s.stop();
s.destroy();
}
} catch (LifecycleException e) {
log.error(sm.getString("catalina.stopError"), e);
}
}
/** * Await and shutdown.
*/ publicvoid await() {
getServer().await();
}
/** * Print usage information for this application.
*/ protectedvoid usage() {
// --------------------------------------- CatalinaShutdownHook Inner Class
// XXX Should be moved to embedded ! /** * Shutdown hook which will perform a clean shutdown of Catalina if needed.
*/ protectedclass CatalinaShutdownHook extendsThread {
@Override publicvoid run() { try { if (getServer() != null) {
Catalina.this.stop();
}
} catch (Throwable ex) {
ExceptionUtils.handleThrowable(ex);
log.error(sm.getString("catalina.shutdownHookFail"), ex);
} finally { // If JULI is used, shut JULI down *after* the server shuts down // so log messages aren't lost
LogManager logManager = LogManager.getLogManager(); if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).shutdown();
}
}
}
}
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.