首页 > 代码库 > (三)Bootstrap.jar
(三)Bootstrap.jar
catalina.bat 在最后启动了bootstrap.jar, 传递了start作为参数(如果多个参数的话,start在尾部)。 然后org.apache.catalina.startup.Bootstrap的main方法初始化了一个bootstrap守护进程,通过调用了catalina.java对应方法。
1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.catalina.startup; 18 19 import java.io.File; 20 import java.lang.reflect.InvocationTargetException; 21 import java.lang.reflect.Method; 22 import java.net.MalformedURLException; 23 import java.net.URL; 24 import java.util.ArrayList; 25 import java.util.List; 26 import java.util.StringTokenizer; 27 28 import org.apache.catalina.Globals; 29 import org.apache.catalina.security.SecurityClassLoad; 30 import org.apache.catalina.startup.ClassLoaderFactory.Repository; 31 import org.apache.catalina.startup.ClassLoaderFactory.RepositoryType; 32 import org.apache.juli.logging.Log; 33 import org.apache.juli.logging.LogFactory; 34 35 /** 36 * Bootstrap loader for Catalina. This application constructs a class loader 37 * for use in loading the Catalina internal classes (by accumulating all of the 38 * JAR files found in the "server" directory under "catalina.home"), and 39 * starts the regular execution of the container. The purpose of this 40 * roundabout approach is to keep the Catalina internal classes (and any 41 * other classes they depend on, such as an XML parser) out of the system 42 * class path and therefore not visible to application level classes. 43 * 44 * @author Craig R. McClanahan 45 * @author Remy Maucherat 46 */ 47 public final class Bootstrap { 48 49 private static final Log log = LogFactory.getLog(Bootstrap.class); 50 51 52 // ------------------------------------------------------- Static Variables 53 54 55 /** 56 * Daemon object used by main. 57 */ 58 private static Bootstrap daemon = null; 59 60 61 // -------------------------------------------------------------- Variables 62 63 64 /** 65 * Daemon reference. 66 */ 67 private Object catalinaDaemon = null; 68 69 70 ClassLoader commonLoader = null; 71 ClassLoader catalinaLoader = null; 72 ClassLoader sharedLoader = null; 73 74 75 // -------------------------------------------------------- Private Methods 76 77 78 private void initClassLoaders() { 79 try { 80 commonLoader = createClassLoader("common", null); 81 if( commonLoader == null ) { 82 // no config file, default to this loader - we might be in a ‘single‘ env. 83 commonLoader=this.getClass().getClassLoader(); 84 } 85 catalinaLoader = createClassLoader("server", commonLoader); 86 sharedLoader = createClassLoader("shared", commonLoader); 87 } catch (Throwable t) { 88 handleThrowable(t); 89 log.error("Class loader creation threw exception", t); 90 System.exit(1); 91 } 92 } 93 94 95 private ClassLoader createClassLoader(String name, ClassLoader parent) 96 throws Exception { 97 98 String value = http://www.mamicode.com/CatalinaProperties.getProperty(name + ".loader"); 99 if ((value =http://www.mamicode.com/= null) || (value.equals(""))) 100 return parent; 101 102 value =http://www.mamicode.com/ replace(value); 103 104 List<Repository> repositories = new ArrayList<Repository>(); 105 106 StringTokenizer tokenizer = new StringTokenizer(value, ","); 107 while (tokenizer.hasMoreElements()) { 108 String repository = tokenizer.nextToken().trim(); 109 if (repository.length() == 0) { 110 continue; 111 } 112 113 // Check for a JAR URL repository 114 try { 115 @SuppressWarnings("unused") 116 URL url = new URL(repository); 117 repositories.add( 118 new Repository(repository, RepositoryType.URL)); 119 continue; 120 } catch (MalformedURLException e) { 121 // Ignore 122 } 123 124 // Local repository 125 if (repository.endsWith("*.jar")) { 126 repository = repository.substring 127 (0, repository.length() - "*.jar".length()); 128 repositories.add( 129 new Repository(repository, RepositoryType.GLOB)); 130 } else if (repository.endsWith(".jar")) { 131 repositories.add( 132 new Repository(repository, RepositoryType.JAR)); 133 } else { 134 repositories.add( 135 new Repository(repository, RepositoryType.DIR)); 136 } 137 } 138 139 return ClassLoaderFactory.createClassLoader(repositories, parent); 140 } 141 142 /** 143 * System property replacement in the given string. 144 * 145 * @param str The original string 146 * @return the modified string 147 */ 148 protected String replace(String str) { 149 // Implementation is copied from ClassLoaderLogManager.replace(), 150 // but added special processing for catalina.home and catalina.base. 151 String result = str; 152 int pos_start = str.indexOf("${"); 153 if (pos_start >= 0) { 154 StringBuilder builder = new StringBuilder(); 155 int pos_end = -1; 156 while (pos_start >= 0) { 157 builder.append(str, pos_end + 1, pos_start); 158 pos_end = str.indexOf(‘}‘, pos_start + 2); 159 if (pos_end < 0) { 160 pos_end = pos_start - 1; 161 break; 162 } 163 String propName = str.substring(pos_start + 2, pos_end); 164 String replacement; 165 if (propName.length() == 0) { 166 replacement = null; 167 } else if (Globals.CATALINA_HOME_PROP.equals(propName)) { 168 replacement = getCatalinaHome(); 169 } else if (Globals.CATALINA_BASE_PROP.equals(propName)) { 170 replacement = getCatalinaBase(); 171 } else { 172 replacement = System.getProperty(propName); 173 } 174 if (replacement != null) { 175 builder.append(replacement); 176 } else { 177 builder.append(str, pos_start, pos_end + 1); 178 } 179 pos_start = str.indexOf("${", pos_end + 1); 180 } 181 builder.append(str, pos_end + 1, str.length()); 182 result = builder.toString(); 183 } 184 return result; 185 } 186 187 188 /** 189 * Initialize daemon. 190 */ 191 public void init() 192 throws Exception 193 { 194 195 // Set Catalina path 196 setCatalinaHome(); 197 setCatalinaBase(); 198 199 initClassLoaders(); 200 201 Thread.currentThread().setContextClassLoader(catalinaLoader); 202 203 SecurityClassLoad.securityClassLoad(catalinaLoader); 204 205 // Load our startup class and call its process() method 206 if (log.isDebugEnabled()) 207 log.debug("Loading startup class"); 208 Class<?> startupClass = 209 catalinaLoader.loadClass 210 ("org.apache.catalina.startup.Catalina"); 211 Object startupInstance = startupClass.newInstance(); 212 213 // Set the shared extensions class loader 214 if (log.isDebugEnabled()) 215 log.debug("Setting startup class properties"); 216 String methodName = "setParentClassLoader"; 217 Class<?> paramTypes[] = new Class[1]; 218 paramTypes[0] = Class.forName("java.lang.ClassLoader"); 219 Object paramValues[] = new Object[1]; 220 paramValues[0] = sharedLoader; 221 Method method = 222 startupInstance.getClass().getMethod(methodName, paramTypes); 223 method.invoke(startupInstance, paramValues); 224 225 catalinaDaemon = startupInstance; 226 227 } 228 229 230 /** 231 * Load daemon. 232 */ 233 private void load(String[] arguments) 234 throws Exception { 235 236 // Call the load() method 237 String methodName = "load"; 238 Object param[]; 239 Class<?> paramTypes[]; 240 if (arguments==null || arguments.length==0) { 241 paramTypes = null; 242 param = null; 243 } else { 244 paramTypes = new Class[1]; 245 paramTypes[0] = arguments.getClass(); 246 param = new Object[1]; 247 param[0] = arguments; 248 } 249 Method method = 250 catalinaDaemon.getClass().getMethod(methodName, paramTypes); 251 if (log.isDebugEnabled()) 252 log.debug("Calling startup class " + method); 253 method.invoke(catalinaDaemon, param); 254 255 } 256 257 258 /** 259 * getServer() for configtest 260 */ 261 private Object getServer() throws Exception { 262 263 String methodName = "getServer"; 264 Method method = 265 catalinaDaemon.getClass().getMethod(methodName); 266 return method.invoke(catalinaDaemon); 267 268 } 269 270 271 // ----------------------------------------------------------- Main Program 272 273 274 /** 275 * Load the Catalina daemon. 276 */ 277 public void init(String[] arguments) 278 throws Exception { 279 280 init(); 281 load(arguments); 282 283 } 284 285 286 /** 287 * Start the Catalina daemon. 288 */ 289 public void start() 290 throws Exception { 291 if( catalinaDaemon==null ) init(); 292 293 Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null); 294 method.invoke(catalinaDaemon, (Object [])null); 295 296 } 297 298 299 /** 300 * Stop the Catalina Daemon. 301 */ 302 public void stop() 303 throws Exception { 304 305 Method method = catalinaDaemon.getClass().getMethod("stop", (Class [] ) null); 306 method.invoke(catalinaDaemon, (Object [] ) null); 307 308 } 309 310 311 /** 312 * Stop the standalone server. 313 */ 314 public void stopServer() 315 throws Exception { 316 317 Method method = 318 catalinaDaemon.getClass().getMethod("stopServer", (Class []) null); 319 method.invoke(catalinaDaemon, (Object []) null); 320 321 } 322 323 324 /** 325 * Stop the standalone server. 326 */ 327 public void stopServer(String[] arguments) 328 throws Exception { 329 330 Object param[]; 331 Class<?> paramTypes[]; 332 if (arguments==null || arguments.length==0) { 333 paramTypes = null; 334 param = null; 335 } else { 336 paramTypes = new Class[1]; 337 paramTypes[0] = arguments.getClass(); 338 param = new Object[1]; 339 param[0] = arguments; 340 } 341 Method method = 342 catalinaDaemon.getClass().getMethod("stopServer", paramTypes); 343 method.invoke(catalinaDaemon, param); 344 345 } 346 347 348 /** 349 * Set flag. 350 */ 351 public void setAwait(boolean await) 352 throws Exception { 353 354 Class<?> paramTypes[] = new Class[1]; 355 paramTypes[0] = Boolean.TYPE; 356 Object paramValues[] = new Object[1]; 357 paramValues[0] = Boolean.valueOf(await); 358 Method method = 359 catalinaDaemon.getClass().getMethod("setAwait", paramTypes); 360 method.invoke(catalinaDaemon, paramValues); 361 362 } 363 364 public boolean getAwait() 365 throws Exception 366 { 367 Class<?> paramTypes[] = new Class[0]; 368 Object paramValues[] = new Object[0]; 369 Method method = 370 catalinaDaemon.getClass().getMethod("getAwait", paramTypes); 371 Boolean b=(Boolean)method.invoke(catalinaDaemon, paramValues); 372 return b.booleanValue(); 373 } 374 375 376 /** 377 * Destroy the Catalina Daemon. 378 */ 379 public void destroy() { 380 381 // FIXME 382 383 } 384 385 386 /** 387 * Main method and entry point when starting Tomcat via the provided 388 * scripts. 389 * 390 * @param args Command line arguments to be processed 391 */ 392 public static void main(String args[]) { 393 394 if (daemon == null) { 395 // Don‘t set daemon until init() has completed 396 Bootstrap bootstrap = new Bootstrap(); 397 try { 398 bootstrap.init(); 399 } catch (Throwable t) { 400 handleThrowable(t); 401 t.printStackTrace(); 402 return; 403 } 404 daemon = bootstrap; 405 } else { 406 // When running as a service the call to stop will be on a new 407 // thread so make sure the correct class loader is used to prevent 408 // a range of class not found exceptions. 409 Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); 410 } 411 412 try { 413 String command = "start"; 414 if (args.length > 0) { 415 command = args[args.length - 1]; 416 } 417 418 if (command.equals("startd")) { 419 args[args.length - 1] = "start"; 420 daemon.load(args); 421 daemon.start(); 422 } else if (command.equals("stopd")) { 423 args[args.length - 1] = "stop"; 424 daemon.stop(); 425 } else if (command.equals("start")) { 426 daemon.setAwait(true); 427 daemon.load(args); 428 daemon.start(); 429 } else if (command.equals("stop")) { 430 daemon.stopServer(args); 431 } else if (command.equals("configtest")) { 432 daemon.load(args); 433 if (null==daemon.getServer()) { 434 System.exit(1); 435 } 436 System.exit(0); 437 } else { 438 log.warn("Bootstrap: command \"" + command + "\" does not exist."); 439 } 440 } catch (Throwable t) { 441 // Unwrap the Exception for clearer error reporting 442 if (t instanceof InvocationTargetException && 443 t.getCause() != null) { 444 t = t.getCause(); 445 } 446 handleThrowable(t); 447 t.printStackTrace(); 448 System.exit(1); 449 } 450 451 } 452 453 public void setCatalinaHome(String s) { 454 System.setProperty(Globals.CATALINA_HOME_PROP, s); 455 } 456 457 public void setCatalinaBase(String s) { 458 System.setProperty(Globals.CATALINA_BASE_PROP, s); 459 } 460 461 462 /** 463 * Set the <code>catalina.base</code> System property to the current 464 * working directory if it has not been set. 465 */ 466 private void setCatalinaBase() { 467 468 if (System.getProperty(Globals.CATALINA_BASE_PROP) != null) 469 return; 470 if (System.getProperty(Globals.CATALINA_HOME_PROP) != null) 471 System.setProperty(Globals.CATALINA_BASE_PROP, 472 System.getProperty(Globals.CATALINA_HOME_PROP)); 473 else 474 System.setProperty(Globals.CATALINA_BASE_PROP, 475 System.getProperty("user.dir")); 476 477 } 478 479 480 /** 481 * Set the <code>catalina.home</code> System property to the current 482 * working directory if it has not been set. 483 */ 484 private void setCatalinaHome() { 485 486 if (System.getProperty(Globals.CATALINA_HOME_PROP) != null) 487 return; 488 File bootstrapJar = 489 new File(System.getProperty("user.dir"), "bootstrap.jar"); 490 if (bootstrapJar.exists()) { 491 try { 492 System.setProperty 493 (Globals.CATALINA_HOME_PROP, 494 (new File(System.getProperty("user.dir"), "..")) 495 .getCanonicalPath()); 496 } catch (Exception e) { 497 // Ignore 498 System.setProperty(Globals.CATALINA_HOME_PROP, 499 System.getProperty("user.dir")); 500 } 501 } else { 502 System.setProperty(Globals.CATALINA_HOME_PROP, 503 System.getProperty("user.dir")); 504 } 505 506 } 507 508 509 /** 510 * Get the value of the catalina.home environment variable. 511 */ 512 public static String getCatalinaHome() { 513 return System.getProperty(Globals.CATALINA_HOME_PROP, 514 System.getProperty("user.dir")); 515 } 516 517 518 /** 519 * Get the value of the catalina.base environment variable. 520 */ 521 public static String getCatalinaBase() { 522 return System.getProperty(Globals.CATALINA_BASE_PROP, getCatalinaHome()); 523 } 524 525 526 // Copied from ExceptionUtils since that class is not visible during start 527 private static void handleThrowable(Throwable t) { 528 if (t instanceof ThreadDeath) { 529 throw (ThreadDeath) t; 530 } 531 if (t instanceof VirtualMachineError) { 532 throw (VirtualMachineError) t; 533 } 534 // All other instances of Throwable will be silently swallowed 535 } 536 }
/*
* 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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.catalina.Globals;
import org.apache.catalina.security.SecurityClassLoad;
import org.apache.catalina.startup.ClassLoaderFactory.Repository;
import org.apache.catalina.startup.ClassLoaderFactory.RepositoryType;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* Bootstrap loader for Catalina. This application constructs a class loader
* for use in loading the Catalina internal classes (by accumulating all of the
* JAR files found in the "server" directory under "catalina.home"), and
* starts the regular execution of the container. The purpose of this
* roundabout approach is to keep the Catalina internal classes (and any
* other classes they depend on, such as an XML parser) out of the system
* class path and therefore not visible to application level classes.
*
* @author Craig R. McClanahan
* @author Remy Maucherat
*/
// Catalina的Bootstrap加载器。这个应用为加载Catalina的内部类(通过累加“catalina.home”下的jar文件)构造了一个类加载器,并启动了容器。
// 这种间接做法的目的是使catalina的内部类(和它依赖的其他类,必须Xml转化器)与系统的class path分离,与应用级别的类互相不能访问。
public final class Bootstrap {
private static final Log log = LogFactory.getLog(Bootstrap.class);
// ------------------------------------------------------- Static Variables
/**
* Daemon object used by main.
*/
private static Bootstrap daemon = null;
// -------------------------------------------------------------- Variables
/**
* Daemon reference.
*/
private Object catalinaDaemon = null;
ClassLoader commonLoader = null;
ClassLoader catalinaLoader = null;
ClassLoader sharedLoader = null;
// -------------------------------------------------------- Private Methods
private void initClassLoaders() {
try {
commonLoader = createClassLoader("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a ‘single‘ env.
commonLoader=this.getClass().getClassLoader();
}
catalinaLoader = createClassLoader("server", commonLoader); // 在tomcat 7x的catalina.properties中server.loader为空
sharedLoader = createClassLoader("shared", commonLoader); // 在tomcat 7x的catalina.properties中shared.loader为空
} catch (Throwable t) {
handleThrowable(t);
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}
// 如果配置文件中没有name+".loader"属性, 返回parent
private ClassLoader createClassLoader(String name, ClassLoader parent)
throws Exception {
String value = http://www.mamicode.com/CatalinaProperties.getProperty(name +".loader");
if ((value =http://www.mamicode.com/= null) || (value.equals("")))
return parent;
value = http://www.mamicode.com/replace(value); // 替换catalina.home和catalina.base
List<Repository> repositories = new ArrayList<Repository>();
StringTokenizer tokenizer = new StringTokenizer(value, ","); // 处理value把结尾不同的值放进不同的Repository
while (tokenizer.hasMoreElements()) {
String repository = tokenizer.nextToken().trim();
if (repository.length() == 0) {
continue;
}
// Check for a JAR URL repository
try {
@SuppressWarnings("unused")
URL url = new URL(repository);
repositories.add(
new Repository(repository, RepositoryType.URL));
continue;
} catch (MalformedURLException e) {
// Ignore
}
// Local repository
if (repository.endsWith("*.jar")) {
repository = repository.substring
(0, repository.length() - "*.jar".length());
repositories.add(
new Repository(repository, RepositoryType.GLOB));
} else if (repository.endsWith(".jar")) {
repositories.add(
new Repository(repository, RepositoryType.JAR));
} else {
repositories.add(
new Repository(repository, RepositoryType.DIR));
}
}
return ClassLoaderFactory.createClassLoader(repositories, parent); // 特权化
}
/**
* System property replacement in the given string.
*
* @param str The original string
* @return the modified string
*/
protected String replace(String str) {
// Implementation is copied from ClassLoaderLogManager.replace(),
// but added special processing for catalina.home and catalina.base.
String result = str;
int pos_start = str.indexOf("${");
if (pos_start >= 0) {
StringBuilder builder = new StringBuilder();
int pos_end = -1;
while (pos_start >= 0) {
builder.append(str, pos_end + 1, pos_start);
pos_end = str.indexOf(‘}‘, pos_start + 2);
if (pos_end < 0) {
pos_end = pos_start - 1;
break;
}
String propName = str.substring(pos_start + 2, pos_end);
String replacement;
if (propName.length() == 0) {
replacement = null;
} else if (Globals.CATALINA_HOME_PROP.equals(propName)) {
replacement = getCatalinaHome();
} else if (Globals.CATALINA_BASE_PROP.equals(propName)) {
replacement = getCatalinaBase();
} else {
replacement = System.getProperty(propName);
}
if (replacement != null) {
builder.append(replacement);
} else {
builder.append(str, pos_start, pos_end + 1);
}
pos_start = str.indexOf("${", pos_end + 1);
}
builder.append(str, pos_end + 1, str.length());
result = builder.toString();
}
return result;
}
/**
* Initialize daemon.
*/
public void init()
throws Exception
{
// Set Catalina path
setCatalinaHome(); // 设置catalina.home, 在catalina.bat启动Bootstarp.java时通过-Dcatalina.home传入; 没有就重新设置
setCatalinaBase(); // 设置catalina.base, 在catalina.bat启动Bootstarp.java时通过-Dcatalina.base传入; 没有就重新设置
initClassLoaders(); // 使用catalina.properties初始化了3个ClassLoader, 在tomcat7x中catalina.loader和server.loader为空;
// 所以catalinaLoader = commonLoader; sharedLoader = commonLoader;
// commonLoader没有parent classLoader, catalinaLoader和sharedLoader的parent classLoader是commonLoader
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
// Load our startup class and call its process() method
if (log.isDebugEnabled())
log.debug("Loading startup class");
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
// Set the shared extensions class loader
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues); // 调用Catalina.setParentClassLoader(), sharedLoader作为参数, 参数类型是ClassLoader
catalinaDaemon = startupInstance; // catalina守护进程
}
/**
* Load daemon.
*/
private void load(String[] arguments)
throws Exception {
// Call the load() method
String methodName = "load";
Object param[];
Class<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
param = new Object[1];
param[0] = arguments;
}
Method method =
catalinaDaemon.getClass().getMethod(methodName, paramTypes);
if (log.isDebugEnabled())
log.debug("Calling startup class " + method);
method.invoke(catalinaDaemon, param); // catalina.java 下有俩个load方法, 一个有参一个无参
}
/**
* getServer() for configtest
*/
private Object getServer() throws Exception {
String methodName = "getServer";
Method method =
catalinaDaemon.getClass().getMethod(methodName);
return method.invoke(catalinaDaemon);
}
// ----------------------------------------------------------- Main Program
/**
* Load the Catalina daemon.
*/
public void init(String[] arguments)
throws Exception {
init();
load(arguments);
}
/**
* Start the Catalina daemon.
*/
public void start()
throws Exception {
if( catalinaDaemon==null ) init();
Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
}
/**
* Stop the Catalina Daemon.
*/
public void stop()
throws Exception {
Method method = catalinaDaemon.getClass().getMethod("stop", (Class [] ) null);
method.invoke(catalinaDaemon, (Object [] ) null);
}
/**
* Stop the standalone server.
*/
public void stopServer()
throws Exception {
Method method =
catalinaDaemon.getClass().getMethod("stopServer", (Class []) null);
method.invoke(catalinaDaemon, (Object []) null);
}
/**
* Stop the standalone server.
*/
public void stopServer(String[] arguments)
throws Exception {
Object param[];
Class<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
param = new Object[1];
param[0] = arguments;
}
Method method =
catalinaDaemon.getClass().getMethod("stopServer", paramTypes);
method.invoke(catalinaDaemon, param);
}
/**
* Set flag.
*/
public void setAwait(boolean await)
throws Exception {
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Boolean.TYPE;
Object paramValues[] = new Object[1];
paramValues[0] = Boolean.valueOf(await);
Method method =
catalinaDaemon.getClass().getMethod("setAwait", paramTypes);
method.invoke(catalinaDaemon, paramValues);
}
public boolean getAwait()
throws Exception
{
Class<?> paramTypes[] = new Class[0];
Object paramValues[] = new Object[0];
Method method =
catalinaDaemon.getClass().getMethod("getAwait", paramTypes);
Boolean b=(Boolean)method.invoke(catalinaDaemon, paramValues);
return b.booleanValue();
}
/**
* Destroy the Catalina Daemon.
*/
public void destroy() {
// FIXME
}
/**
* Main method and entry point when starting Tomcat via the provided
* scripts.
*
* @param args Command line arguments to be processed
*/
public static void main(String args[]) {
if (daemon == null) { // stop时不为空
// Don‘t set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init(); // 执行init()
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap; // 守护进程
} else {
// When running as a service the call to stop will be on a new
// thread so make sure the correct class loader is used to prevent
// a range of class not found exceptions.
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
try { // catalina.bat把start作为最后一个参数启动
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
// 根据不同参数, 调用catalina.java中的同名方法; command = startd或start或onfigtest时, 先通过反射调用catalina.load方法
if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null==daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}
public void setCatalinaHome(String s) {
System.setProperty(Globals.CATALINA_HOME_PROP, s);
}
public void setCatalinaBase(String s) {
System.setProperty(Globals.CATALINA_BASE_PROP, s);
}
/**
* Set the <code>catalina.base</code> System property to the current
* working directory if it has not been set.
*/
private void setCatalinaBase() {
if (System.getProperty(Globals.CATALINA_BASE_PROP) != null)
return;
if (System.getProperty(Globals.CATALINA_HOME_PROP) != null)
System.setProperty(Globals.CATALINA_BASE_PROP,
System.getProperty(Globals.CATALINA_HOME_PROP));
else
System.setProperty(Globals.CATALINA_BASE_PROP,
System.getProperty("user.dir"));
}
/**
* Set the <code>catalina.home</code> System property to the current
* working directory if it has not been set.
*/
private void setCatalinaHome() {
if (System.getProperty(Globals.CATALINA_HOME_PROP) != null)
return;
File bootstrapJar =
new File(System.getProperty("user.dir"), "bootstrap.jar");
if (bootstrapJar.exists()) {
try {
System.setProperty // 设置catalina.home为user.dir的父目录
(Globals.CATALINA_HOME_PROP,
(new File(System.getProperty("user.dir"), ".."))
.getCanonicalPath());
} catch (Exception e) {
// Ignore
System.setProperty(Globals.CATALINA_HOME_PROP,
System.getProperty("user.dir"));
}
} else {
System.setProperty(Globals.CATALINA_HOME_PROP,
System.getProperty("user.dir"));
}
}
/**
* Get the value of the catalina.home environment variable.
*/
public static String getCatalinaHome() {
return System.getProperty(Globals.CATALINA_HOME_PROP,
System.getProperty("user.dir"));
}
/**
* Get the value of the catalina.base environment variable.
*/
public static String getCatalinaBase() {
return System.getProperty(Globals.CATALINA_BASE_PROP, getCatalinaHome());
}
// Copied from ExceptionUtils since that class is not visible during start
private static void handleThrowable(Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
}
if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
}
// All other instances of Throwable will be silently swallowed
}
}
(三)Bootstrap.jar