/**
*
* Copyright 2003-2005 The Apache Software Foundation
*
* Licensed 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.geronimo.system.main;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.common.GeronimoEnvironment;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.kernel.KernelFactory;
import org.apache.geronimo.kernel.config.ConfigurationManager;
import org.apache.geronimo.kernel.config.ConfigurationUtil;
import org.apache.geronimo.kernel.config.PersistentConfigurationList;
import org.apache.geronimo.kernel.log.GeronimoLogging;
import org.apache.geronimo.kernel.repository.Artifact;
import org.apache.geronimo.system.serverinfo.DirectoryUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* @version $Rev:385659 $ $Date: 2006-05-18 04:10:58 +0200 (Thu, 18 May 2006) $
*/
public class Daemon {
private final static String ARGUMENT_NO_PROGRESS = "--quiet";
private final static String ARGUMENT_LONG_PROGRESS = "--long";
private final static String ARGUMENT_VERBOSE_SHORTFORM = "-v";
private final static String ARGUMENT_VERBOSE = "--verbose";
private final static String ARGUMENT_MORE_VERBOSE_SHORTFORM = "-vv";
private final static String ARGUMENT_MORE_VERBOSE = "--veryverbose";
private final static String ARGUMENT_MODULE_OVERRIDE = "--override";
private static boolean started = false;
private static Log log;
private StartupMonitor monitor;
private List configs = new ArrayList();
private String verboseArg = null;
private String noProgressArg = null;
private String longProgressArg = null;
private Daemon(String[] args) {
// Very first startup tasks
long start = System.currentTimeMillis();
// Command line arguments affect logging configuration, etc.
if(processArguments(args)) {
System.out.println("Booting Geronimo Kernel (in Java " + System.getProperty("java.version") + ")...");
System.out.flush();
// Initialization tasks that must run before anything else
initializeSystem();
monitor.systemStarting(start);
doStartup();
} else {
System.exit(1);
throw new AssertionError();
}
}
private void printHelp(PrintStream out) {
out.println();
out.println("Syntax: java -jar bin/server.jar [options]");
out.println();
out.println("Available options are: ");
out.println(" "+ARGUMENT_NO_PROGRESS);
out.println(" Suppress the normal startup progress bar. This is typically\n" +
" used when redirecting console output to a file, or starting\n" +
" the server from an IDE or other tool.");
out.println(" "+ARGUMENT_LONG_PROGRESS);
out.println(" Write startup progress to the console in a format that is\n" +
" suitable for redirecting console output to a file, or starting\n" +
" the server from an IDE or other tool (doesn't use linefeeds to\n" +
" update the progress information that is used by default if you\n" +
" don't specify " +ARGUMENT_NO_PROGRESS +" or "+ARGUMENT_LONG_PROGRESS+").\n");
out.println(" "+ARGUMENT_VERBOSE_SHORTFORM +" " +ARGUMENT_VERBOSE);
out.println(" Reduces the console log level to DEBUG, resulting in more\n" +
" console output than is normally present.");
out.println(" "+ARGUMENT_MORE_VERBOSE_SHORTFORM +" " +ARGUMENT_MORE_VERBOSE);
out.println(" Reduces the console log level to TRACE, resulting in still\n" +
" more console output.");
out.println();
out.println(" "+ARGUMENT_MODULE_OVERRIDE+" [moduleId] [moduleId] ...");
out.println(" USE WITH CAUTION! Overrides the modules in\n" +
" var/config/config.xml such that only the modules listed on\n" +
" the command line will be started. Note that many J2EE\n" +
" features depend on certain modules being started, so you\n" +
" should be very careful what you omit. Any arguments after\n" +
" this are assumed to be module names.");
out.println();
out.println("In addition you may specify a replacement for var/config/config.xml using by setting the property\n" +
"-Dorg.apache.geronimo.config.file=var/config/<my-config.xml>\n" +
"This is resolved relative to the geronimo base directory.");
out.println();
}
/**
* @return true if the server startup should proceed (all arguments
* make sense and the user didn't ask for help)
*/
private boolean processArguments(String[] args) {
boolean override = false;
boolean help = false;
for (int i = 0; i < args.length; i++) {
if(override) {
configs.add(Artifact.create(args[i]));
} else if (args[i].equals(ARGUMENT_NO_PROGRESS)) {
noProgressArg = ARGUMENT_NO_PROGRESS;
} else if (args[i].equals(ARGUMENT_LONG_PROGRESS)) {
longProgressArg = ARGUMENT_LONG_PROGRESS;
} else if (args[i].equals(ARGUMENT_VERBOSE_SHORTFORM) ||
args[i].equals(ARGUMENT_VERBOSE)) {
if (verboseArg == null) {
verboseArg = ARGUMENT_VERBOSE;
}
} else if (args[i].equals(ARGUMENT_MORE_VERBOSE_SHORTFORM) ||
args[i].equals(ARGUMENT_MORE_VERBOSE)) {
if (verboseArg == null) {
verboseArg = ARGUMENT_MORE_VERBOSE;
}
} else if (args[i].equals(ARGUMENT_MODULE_OVERRIDE)) {
override = true;
} else if(args[i].equalsIgnoreCase("-help") || args[i].equalsIgnoreCase("--help") ||
args[i].equalsIgnoreCase("-h") || args[i].equalsIgnoreCase("/?")) {
help = true;
} else {
System.out.println("Unrecognized argument: "+args[i]);
help = true;
}
}
if(help) {
printHelp(System.out);
}
return !help;
}
private void initializeSystem() {
if (!started) {
started = true;
// Perform initialization tasks common with the various Geronimo environments
GeronimoEnvironment.init();
// This MUST be done before the first log is acquired (WHICH THE STARTUP MONITOR 5 LINES LATER DOES!)
// Generally we want to suppress anything but WARN until the log GBean starts up
GeronimoLogging.initialize(verboseArg == null || verboseArg.equals(ARGUMENT_VERBOSE) ? GeronimoLogging.WARN : GeronimoLogging.DEBUG);
// The following will be used once the log GBean starts up
GeronimoLogging.setConsoleLogLevel(verboseArg == null ? GeronimoLogging.INFO : verboseArg.equals(ARGUMENT_VERBOSE) ? GeronimoLogging.DEBUG : GeronimoLogging.TRACE);
log = LogFactory.getLog(Daemon.class.getName());
}
if (verboseArg != null || noProgressArg != null) {
monitor = new SilentStartupMonitor();
} else {
if (longProgressArg != null)
monitor = new LongStartupMonitor();
else
monitor = new ProgressBarStartupMonitor();
}
// JVMCheck(); // Removed for 1.1
}
private void JVMCheck() {
String jvmVersion = System.getProperty("java.specification.version");
if (! jvmVersion.equals("1.4"))
log.warn("\n====================================== Warning =======================================\n" +
" Geronimo is currently only certified on version 1.4 of the Java Virtual Machine.\n" +
" Use of version " + jvmVersion + " is not currently supported. Use at your own risk.\n" +
" Check http://geronimo.apache.org for current information on JDK certification level.\n" +
"====================================== Warning =======================================");
}
private void doStartup() {
try {
// Check that the tmpdir exists - if not give friendly msg and exit
// since we allow it to be configured in geronimo.bat and geronimo.sh
// (since 1.0 release) the same way Tomcat allows it to be configured.
String tmpDir = System.getProperty("java.io.tmpdir");
if (tmpDir == null || (!(new File(tmpDir)).exists()) ||
(!(new File(tmpDir)).isDirectory())) {
System.err.println("The java.io.tmpdir system property specifies the "+
"non-existent directory " +tmpDir);
System.exit(1);
throw new AssertionError();
}
// Determine the geronimo installation directory
File geronimoInstallDirectory = DirectoryUtils.getGeronimoInstallDirectory();
if (geronimoInstallDirectory == null) {
System.err.println("Could not determine geronimo installation directory");
System.exit(1);
throw new AssertionError();
}
// setup the endorsed dir entry
CommandLineManifest manifestEntries = CommandLineManifest.getManifestEntries();
String endorsedDirs = "java.endorsed.dirs";
List endorsedDirsFromManifest = manifestEntries.getEndorsedDirs();
AddToSystemProperty(endorsedDirs, endorsedDirsFromManifest, geronimoInstallDirectory);
String extensionDirs = "java.ext.dirs";
List extensionDirsFromManifest = manifestEntries.getExtensionDirs();
AddToSystemProperty(extensionDirs, extensionDirsFromManifest, geronimoInstallDirectory);
ClassLoader classLoader = Daemon.class.getClassLoader();
// create the kernel
final Kernel kernel = KernelFactory.newInstance().createKernel("geronimo");
// boot the kernel
try {
kernel.boot();
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
throw new AssertionError();
}
// add our shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread("Geronimo shutdown thread") {
public void run() {
System.out.println("\rServer shutdown begun ");
kernel.shutdown();
System.out.println("Server shutdown completed");
}
});
// load this configuration
InputStream in = classLoader.getResourceAsStream("META-INF/config.ser");
try {
ConfigurationUtil.loadBootstrapConfiguration(kernel, in, classLoader);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {
// ignored
}
}
}
monitor.systemStarted(kernel);
AbstractNameQuery query = new AbstractNameQuery(PersistentConfigurationList.class.getName());
if (configs.isEmpty()) {
// --override wasn't used (nothing explicit), see what was running before
Set configLists = kernel.listGBeans(query);
for (Iterator i = configLists.iterator(); i.hasNext();) {
AbstractName configListName = (AbstractName) i.next();
try {
configs.addAll((List) kernel.invoke(configListName, "restore"));
} catch (IOException e) {
System.err.println("Unable to restore last known configurations");
e.printStackTrace();
kernel.shutdown();
System.exit(1);
throw new AssertionError();
}
}
}
monitor.foundModules((Artifact[]) configs.toArray(new Artifact[configs.size()]));
// load the rest of the configurations
try {
ConfigurationManager configurationManager = ConfigurationUtil.getConfigurationManager(kernel);
try {
for (Iterator i = configs.iterator(); i.hasNext();) {
Artifact configID = (Artifact) i.next();
monitor.moduleLoading(configID);
configurationManager.loadConfiguration(configID);
monitor.moduleLoaded(configID);
monitor.moduleStarting(configID);
configurationManager.startConfiguration(configID);
monitor.moduleStarted(configID);
}
} finally {
ConfigurationUtil.releaseConfigurationManager(kernel, configurationManager);
}
} catch (Exception e) {
//Exception caught when starting configurations, starting kernel shutdown
monitor.serverStartFailed(e);
try {
kernel.shutdown();
} catch (Exception e1) {
System.err.println("Exception caught during kernel shutdown");
e1.printStackTrace();
}
System.exit(1);
throw new AssertionError();
}
// Tell every persistent configuration list that the kernel is now fully started
Set configLists = kernel.listGBeans(query);
for (Iterator i = configLists.iterator(); i.hasNext();) {
AbstractName configListName = (AbstractName) i.next();
kernel.setAttribute(configListName, "kernelFullyStarted", Boolean.TRUE);
}
// Startup sequence is finished
monitor.startupFinished();
monitor = null;
// capture this thread until the kernel is ready to exit
while (kernel.isRunning()) {
try {
synchronized (kernel) {
kernel.wait();
}
} catch (InterruptedException e) {
// continue
}
}
} catch (Exception e) {
if (monitor != null) {
monitor.serverStartFailed(e);
}
e.printStackTrace();
System.exit(1);
throw new AssertionError();
}
}
private void AddToSystemProperty(String propertyName, List dirsFromManifest, File geronimoInstallDirectory) {
String dirs = System.getProperty(propertyName, "");
for (Iterator iterator = dirsFromManifest.iterator(); iterator.hasNext();) {
String directoryName = (String) iterator.next();
File directory = new File(directoryName);
if (!directory.isAbsolute()) {
directory = new File(geronimoInstallDirectory, directoryName);
}
if (dirs.length() > 0) {
dirs += File.pathSeparatorChar;
}
dirs += directory.getAbsolutePath();
}
if (dirs.length() > 0) {
System.setProperty(propertyName, dirs);
}
log.debug(propertyName + "=" + System.getProperty(propertyName));
}
/**
* Static entry point allowing a Kernel to be run from the command line.
*
* Once the Kernel is booted and the configuration is loaded, the process
* will remain running until the shutdown() method on the kernel is
* invoked or until the JVM exits.
*
* @param args the command line arguments
*/
public static void main(String[] args) {
new Daemon(args);
}
}