init
This commit is contained in:
916
java/org/apache/catalina/startup/Catalina.java
Normal file
916
java/org/apache/catalina/startup/Catalina.java
Normal file
@@ -0,0 +1,916 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.LogManager;
|
||||
|
||||
import org.apache.catalina.Container;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.LifecycleState;
|
||||
import org.apache.catalina.Server;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.security.SecurityConfig;
|
||||
import org.apache.juli.ClassLoaderLogManager;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.ExceptionUtils;
|
||||
import org.apache.tomcat.util.digester.Digester;
|
||||
import org.apache.tomcat.util.digester.Rule;
|
||||
import org.apache.tomcat.util.digester.RuleSet;
|
||||
import org.apache.tomcat.util.log.SystemLogHandler;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public class Catalina {
|
||||
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
protected static final StringManager sm =
|
||||
StringManager.getManager(Constants.Package);
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* Use await.
|
||||
*/
|
||||
protected boolean await = false;
|
||||
|
||||
/**
|
||||
* Pathname to the server configuration file.
|
||||
*/
|
||||
protected String configFile = "conf/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;
|
||||
|
||||
|
||||
/**
|
||||
* Use shutdown hook flag.
|
||||
*/
|
||||
protected boolean useShutdownHook = true;
|
||||
|
||||
|
||||
/**
|
||||
* Shutdown hook.
|
||||
*/
|
||||
protected Thread shutdownHook = null;
|
||||
|
||||
|
||||
/**
|
||||
* Is naming enabled ?
|
||||
*/
|
||||
protected boolean useNaming = true;
|
||||
|
||||
|
||||
/**
|
||||
* Prevent duplicate loads.
|
||||
*/
|
||||
protected boolean loaded = false;
|
||||
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
public Catalina() {
|
||||
setSecurityProtection();
|
||||
ExceptionUtils.preload();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------- Properties
|
||||
|
||||
public void setConfigFile(String file) {
|
||||
configFile = file;
|
||||
}
|
||||
|
||||
|
||||
public String getConfigFile() {
|
||||
return configFile;
|
||||
}
|
||||
|
||||
|
||||
public void setUseShutdownHook(boolean useShutdownHook) {
|
||||
this.useShutdownHook = useShutdownHook;
|
||||
}
|
||||
|
||||
|
||||
public boolean getUseShutdownHook() {
|
||||
return useShutdownHook;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the shared extensions class loader.
|
||||
*
|
||||
* @param parentClassLoader The shared extensions class loader.
|
||||
*/
|
||||
public void setParentClassLoader(ClassLoader parentClassLoader) {
|
||||
this.parentClassLoader = parentClassLoader;
|
||||
}
|
||||
|
||||
public ClassLoader getParentClassLoader() {
|
||||
if (parentClassLoader != null) {
|
||||
return parentClassLoader;
|
||||
}
|
||||
return ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
|
||||
public void setServer(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
|
||||
public Server getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if naming is enabled.
|
||||
*/
|
||||
public boolean isUseNaming() {
|
||||
return this.useNaming;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enables or disables naming support.
|
||||
*
|
||||
* @param useNaming The new use naming value
|
||||
*/
|
||||
public void setUseNaming(boolean useNaming) {
|
||||
this.useNaming = useNaming;
|
||||
}
|
||||
|
||||
public void setAwait(boolean b) {
|
||||
await = b;
|
||||
}
|
||||
|
||||
public boolean isAwait() {
|
||||
return await;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
|
||||
/**
|
||||
* Process the specified command line arguments.
|
||||
*
|
||||
* @param args Command line arguments to process
|
||||
* @return <code>true</code> if we should continue processing
|
||||
*/
|
||||
protected boolean arguments(String args[]) {
|
||||
|
||||
boolean isConfig = false;
|
||||
|
||||
if (args.length < 1) {
|
||||
usage();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (isConfig) {
|
||||
configFile = args[i];
|
||||
isConfig = false;
|
||||
} else if (args[i].equals("-config")) {
|
||||
isConfig = true;
|
||||
} else if (args[i].equals("-nonaming")) {
|
||||
setUseNaming(false);
|
||||
} else if (args[i].equals("-help")) {
|
||||
usage();
|
||||
return false;
|
||||
} else if (args[i].equals("start")) {
|
||||
// NOOP
|
||||
} else if (args[i].equals("configtest")) {
|
||||
// NOOP
|
||||
} else if (args[i].equals("stop")) {
|
||||
// NOOP
|
||||
} else {
|
||||
usage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
long t1=System.currentTimeMillis();
|
||||
// Initialize the digester
|
||||
Digester digester = new Digester();
|
||||
digester.setValidating(false);
|
||||
digester.setRulesValidation(true);
|
||||
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
|
||||
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);
|
||||
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/GlobalNamingResources",
|
||||
"org.apache.catalina.deploy.NamingResourcesImpl");
|
||||
digester.addSetProperties("Server/GlobalNamingResources");
|
||||
digester.addSetNext("Server/GlobalNamingResources",
|
||||
"setGlobalNamingResources",
|
||||
"org.apache.catalina.deploy.NamingResourcesImpl");
|
||||
|
||||
digester.addObjectCreate("Server/Listener",
|
||||
null, // MUST be specified in the element
|
||||
"className");
|
||||
digester.addSetProperties("Server/Listener");
|
||||
digester.addSetNext("Server/Listener",
|
||||
"addLifecycleListener",
|
||||
"org.apache.catalina.LifecycleListener");
|
||||
|
||||
digester.addObjectCreate("Server/Service",
|
||||
"org.apache.catalina.core.StandardService",
|
||||
"className");
|
||||
digester.addSetProperties("Server/Service");
|
||||
digester.addSetNext("Server/Service",
|
||||
"addService",
|
||||
"org.apache.catalina.Service");
|
||||
|
||||
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");
|
||||
|
||||
//Executor
|
||||
digester.addObjectCreate("Server/Service/Executor",
|
||||
"org.apache.catalina.core.StandardThreadExecutor",
|
||||
"className");
|
||||
digester.addSetProperties("Server/Service/Executor");
|
||||
|
||||
digester.addSetNext("Server/Service/Executor",
|
||||
"addExecutor",
|
||||
"org.apache.catalina.Executor");
|
||||
|
||||
|
||||
digester.addRule("Server/Service/Connector",
|
||||
new ConnectorCreateRule());
|
||||
digester.addRule("Server/Service/Connector",
|
||||
new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName"}));
|
||||
digester.addSetNext("Server/Service/Connector",
|
||||
"addConnector",
|
||||
"org.apache.catalina.connector.Connector");
|
||||
|
||||
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
|
||||
"org.apache.tomcat.util.net.SSLHostConfig");
|
||||
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
|
||||
digester.addSetNext("Server/Service/Connector/SSLHostConfig",
|
||||
"addSslHostConfig",
|
||||
"org.apache.tomcat.util.net.SSLHostConfig");
|
||||
|
||||
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
|
||||
new CertificateCreateRule());
|
||||
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
|
||||
new SetAllPropertiesRule(new String[]{"type"}));
|
||||
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
|
||||
"addCertificate",
|
||||
"org.apache.tomcat.util.net.SSLHostConfigCertificate");
|
||||
|
||||
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
|
||||
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
|
||||
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
|
||||
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
|
||||
"setOpenSslConf",
|
||||
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
|
||||
|
||||
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
|
||||
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
|
||||
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
|
||||
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
|
||||
"addCmd",
|
||||
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
|
||||
|
||||
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/");
|
||||
|
||||
long t2=System.currentTimeMillis();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Digester for server.xml created " + ( t2-t1 ));
|
||||
}
|
||||
return digester;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cluster support is optional. The JARs may have been removed.
|
||||
*/
|
||||
private void addClusterRuleSet(Digester digester, String prefix) {
|
||||
Class<?> clazz = null;
|
||||
Constructor<?> constructor = null;
|
||||
try {
|
||||
clazz = Class.forName("org.apache.catalina.ha.ClusterRuleSet");
|
||||
constructor = clazz.getConstructor(String.class);
|
||||
RuleSet ruleSet = (RuleSet) constructor.newInstance(prefix);
|
||||
digester.addRuleSet(ruleSet);
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("catalina.noCluster",
|
||||
e.getClass().getName() + ": " + e.getMessage()), e);
|
||||
} else if (log.isInfoEnabled()) {
|
||||
log.info(sm.getString("catalina.noCluster",
|
||||
e.getClass().getName() + ": " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
||||
return digester;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void stopServer() {
|
||||
stopServer(null);
|
||||
}
|
||||
|
||||
public void stopServer(String[] arguments) {
|
||||
|
||||
if (arguments != null) {
|
||||
arguments(arguments);
|
||||
}
|
||||
|
||||
Server s = getServer();
|
||||
if (s == null) {
|
||||
// Create and execute our Digester
|
||||
Digester digester = createStopDigester();
|
||||
File file = configFile();
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
InputSource is =
|
||||
new InputSource(file.toURI().toURL().toString());
|
||||
is.setByteStream(fis);
|
||||
digester.push(this);
|
||||
digester.parse(is);
|
||||
} catch (Exception e) {
|
||||
log.error("Catalina.stop: ", e);
|
||||
System.exit(1);
|
||||
}
|
||||
} else {
|
||||
// Server object already present. Must be running as a service
|
||||
try {
|
||||
s.stop();
|
||||
s.destroy();
|
||||
} catch (LifecycleException e) {
|
||||
log.error("Catalina.stop: ", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop the existing server
|
||||
s = getServer();
|
||||
if (s.getPort()>0) {
|
||||
try (Socket socket = new Socket(s.getAddress(), s.getPort());
|
||||
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.getPort())));
|
||||
log.error("Catalina.stop: ", ce);
|
||||
System.exit(1);
|
||||
} catch (IOException e) {
|
||||
log.error("Catalina.stop: ", e);
|
||||
System.exit(1);
|
||||
}
|
||||
} else {
|
||||
log.error(sm.getString("catalina.stopServer"));
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start a new server instance.
|
||||
*/
|
||||
public void load() {
|
||||
|
||||
if (loaded) {
|
||||
return;
|
||||
}
|
||||
loaded = true;
|
||||
|
||||
long t1 = System.nanoTime();
|
||||
|
||||
initDirs();
|
||||
|
||||
// Before digester - it may be needed
|
||||
initNaming();
|
||||
|
||||
// Create and execute our Digester
|
||||
Digester digester = createStartDigester();
|
||||
|
||||
InputSource inputSource = null;
|
||||
InputStream inputStream = null;
|
||||
File file = null;
|
||||
try {
|
||||
try {
|
||||
file = configFile();
|
||||
inputStream = new FileInputStream(file);
|
||||
inputSource = new InputSource(file.toURI().toURL().toString());
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("catalina.configFail", file), e);
|
||||
}
|
||||
}
|
||||
if (inputStream == null) {
|
||||
try {
|
||||
inputStream = getClass().getClassLoader()
|
||||
.getResourceAsStream(getConfigFile());
|
||||
inputSource = new InputSource
|
||||
(getClass().getClassLoader()
|
||||
.getResource(getConfigFile()).toString());
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("catalina.configFail",
|
||||
getConfigFile()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This should be included in catalina.jar
|
||||
// Alternative: don't bother with xml, just create it manually.
|
||||
if (inputStream == null) {
|
||||
try {
|
||||
inputStream = getClass().getClassLoader()
|
||||
.getResourceAsStream("server-embed.xml");
|
||||
inputSource = new InputSource
|
||||
(getClass().getClassLoader()
|
||||
.getResource("server-embed.xml").toString());
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("catalina.configFail",
|
||||
"server-embed.xml"), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (inputStream == null || inputSource == null) {
|
||||
if (file == null) {
|
||||
log.warn(sm.getString("catalina.configFail",
|
||||
getConfigFile() + "] or [server-embed.xml]"));
|
||||
} else {
|
||||
log.warn(sm.getString("catalina.configFail",
|
||||
file.getAbsolutePath()));
|
||||
if (file.exists() && !file.canRead()) {
|
||||
log.warn("Permissions incorrect, read permission is not allowed on the file.");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
inputSource.setByteStream(inputStream);
|
||||
digester.push(this);
|
||||
digester.parse(inputSource);
|
||||
} catch (SAXParseException spe) {
|
||||
log.warn("Catalina.start using " + getConfigFile() + ": " +
|
||||
spe.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
log.warn("Catalina.start using " + getConfigFile() + ": " , e);
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getServer().setCatalina(this);
|
||||
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
|
||||
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
|
||||
|
||||
// Stream redirection
|
||||
initStreams();
|
||||
|
||||
// Start the new server
|
||||
try {
|
||||
getServer().init();
|
||||
} catch (LifecycleException e) {
|
||||
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
|
||||
throw new java.lang.Error(e);
|
||||
} else {
|
||||
log.error("Catalina.start", e);
|
||||
}
|
||||
}
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
if(log.isInfoEnabled()) {
|
||||
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load using arguments
|
||||
*/
|
||||
public void load(String args[]) {
|
||||
|
||||
try {
|
||||
if (arguments(args)) {
|
||||
load();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start a new server instance.
|
||||
*/
|
||||
public void start() {
|
||||
|
||||
if (getServer() == null) {
|
||||
load();
|
||||
}
|
||||
|
||||
if (getServer() == null) {
|
||||
log.fatal("Cannot start server. Server instance is not configured.");
|
||||
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;
|
||||
}
|
||||
|
||||
long t2 = System.nanoTime();
|
||||
if(log.isInfoEnabled()) {
|
||||
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
|
||||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
public void 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("Catalina.stop", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Await and shutdown.
|
||||
*/
|
||||
public void await() {
|
||||
|
||||
getServer().await();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print usage information for this application.
|
||||
*/
|
||||
protected void usage() {
|
||||
|
||||
System.out.println
|
||||
("usage: java org.apache.catalina.startup.Catalina"
|
||||
+ " [ -config {pathname} ]"
|
||||
+ " [ -nonaming ] "
|
||||
+ " { -help | start | stop }");
|
||||
|
||||
}
|
||||
|
||||
|
||||
protected void initDirs() {
|
||||
String temp = System.getProperty("java.io.tmpdir");
|
||||
if (temp == null || (!(new File(temp)).isDirectory())) {
|
||||
log.error(sm.getString("embedded.notmp", temp));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void initStreams() {
|
||||
// Replace System.out and System.err with a custom PrintStream
|
||||
System.setOut(new SystemLogHandler(System.out));
|
||||
System.setErr(new SystemLogHandler(System.err));
|
||||
}
|
||||
|
||||
|
||||
protected void initNaming() {
|
||||
// Setting additional variables
|
||||
if (!useNaming) {
|
||||
log.info( "Catalina naming disabled");
|
||||
System.setProperty("catalina.useNaming", "false");
|
||||
} else {
|
||||
System.setProperty("catalina.useNaming", "true");
|
||||
String value = "org.apache.naming";
|
||||
String oldValue =
|
||||
System.getProperty(javax.naming.Context.URL_PKG_PREFIXES);
|
||||
if (oldValue != null) {
|
||||
value = value + ":" + oldValue;
|
||||
}
|
||||
System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, value);
|
||||
if( log.isDebugEnabled() ) {
|
||||
log.debug("Setting naming prefix=" + value);
|
||||
}
|
||||
value = System.getProperty
|
||||
(javax.naming.Context.INITIAL_CONTEXT_FACTORY);
|
||||
if (value == null) {
|
||||
System.setProperty
|
||||
(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
|
||||
"org.apache.naming.java.javaURLContextFactory");
|
||||
} else {
|
||||
log.debug( "INITIAL_CONTEXT_FACTORY already set " + value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the security package access/protection.
|
||||
*/
|
||||
protected void setSecurityProtection(){
|
||||
SecurityConfig securityConfig = SecurityConfig.newInstance();
|
||||
securityConfig.setPackageDefinition();
|
||||
securityConfig.setPackageAccess();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------- CatalinaShutdownHook Inner Class
|
||||
|
||||
// XXX Should be moved to embedded !
|
||||
/**
|
||||
* Shutdown hook which will perform a clean shutdown of Catalina if needed.
|
||||
*/
|
||||
protected class CatalinaShutdownHook extends Thread {
|
||||
|
||||
@Override
|
||||
public void 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final Log log = LogFactory.getLog(Catalina.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Private Classes
|
||||
|
||||
|
||||
/**
|
||||
* Rule that sets the parent class loader for the top object on the stack,
|
||||
* which must be a <code>Container</code>.
|
||||
*/
|
||||
|
||||
final class SetParentClassLoaderRule extends Rule {
|
||||
|
||||
public SetParentClassLoaderRule(ClassLoader parentClassLoader) {
|
||||
|
||||
this.parentClassLoader = parentClassLoader;
|
||||
|
||||
}
|
||||
|
||||
ClassLoader parentClassLoader = null;
|
||||
|
||||
@Override
|
||||
public void begin(String namespace, String name, Attributes attributes)
|
||||
throws Exception {
|
||||
|
||||
if (digester.getLogger().isDebugEnabled()) {
|
||||
digester.getLogger().debug("Setting parent class loader");
|
||||
}
|
||||
|
||||
Container top = (Container) digester.peek();
|
||||
top.setParentClassLoader(parentClassLoader);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user