Bootstrap.java
- /*
- * Bootstrap
- */
- package gov.usgs.earthquake.distribution;
- import gov.usgs.util.Config;
- import gov.usgs.util.Configurable;
- import gov.usgs.util.StreamUtils;
- import gov.usgs.util.logging.LoggingOutputStream;
- import gov.usgs.util.logging.SimpleLogFileHandler;
- import gov.usgs.util.logging.SimpleLogFormatter;
- import gov.usgs.util.logging.StdOutErrLevel;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.PrintStream;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.logging.ConsoleHandler;
- import java.util.logging.Formatter;
- import java.util.logging.Handler;
- import java.util.logging.Level;
- import java.util.logging.LogManager;
- import java.util.logging.Logger;
- import java.util.logging.SimpleFormatter;
- import java.util.logging.XMLFormatter;
- /**
- * Bootstrap is a class used to start an application.
- *
- * It loads a configuration file, sets up initial logging, and starts a
- * configurable main method.
- *
- * @author jmfee
- *
- */
- public class Bootstrap {
- // public static
- static {
- gov.usgs.util.protocolhandlers.data.Handler.register();
- }
- /** Default JAR config path. */
- public static final String JAR_CONFIGFILE = "etc/config/config.ini";
- /** Argument for config file. */
- public static final String CONFIGFILE_ARGUMENT = "--configFile=";
- /** Default config file. */
- public static final String DEFAULT_CONFIGFILE = "config.ini";
- /** Whether to test config only. */
- public static final String CONFIG_TEST_ARGUMENT = "--configTest";
- /** Property for log format. */
- public static final String LOGFORMAT_PROPERTY_NAME = "logformat";
- /** log format value for "pdl" format */
- public static final String LOGFORMAT_PDL = "pdl";
- /** log format value for java "simple" format */
- public static final String LOGFORMAT_SIMPLE = "simple";
- /** log format value for java "xml" format */
- public static final String LOGFORMAT_XML = "xml";
- /** Default log format is "simple". */
- public static final String DEFAULT_LOGFORMAT = LOGFORMAT_PDL;
- /** Property for log level. */
- public static final String LOGLEVEL_PROPERTY_NAME = "loglevel";
- /** Default log level is "INFO". */
- public static final String DEFAULT_LOGLEVEL = "INFO";
- /** Property for log directory. */
- public static final String LOGDIRECTORY_PROPERTY_NAME = "logdirectory";
- /** Default log directory is "log". */
- public static final String DEFAULT_LOGDIRECTORY = "log";
- /** Property for log file pattern. */
- public static final String LOGFILE_PROPERTY_NAME = "logfile";
- /** Default log file pattern is "yyyyMMdd'.log'". */
- public static final String DEFAULT_LOGFILE = "yyyyMMdd'.log'";
- /** Property for console redirect. */
- public static final String CONSOLEREDIRECT_PROPERTY_NAME = "redirectconsole";
- /** Default console redirect value is "false" (don't redirect). */
- public static final String DEFAULT_CONSOLEREDIRECT = "false";
- /** Property used to disable tracker updates. */
- public static final String ENABLE_TRACKER_PROPERTY_NAME = "enableTracker";
- /** Argument for mainclass. */
- public static final String MAINCLASS_ARGUMENT = "--mainclass=";
- /** Property for mainclass. */
- public static final String MAINCLASS_PROPERTY_NAME = "mainclass";
- /** Default mainclass is "gov.usgs.earthquake.distribution.ProductClient. */
- public static final String DEFAULT_MAINCLASS = "gov.usgs.earthquake.distribution.ProductClient";
- /** Argument for version */
- public static final String VERSION_ARGUMENT = "--version";
- // private static
- /** Private logging object. */
- private static final Logger LOGGER = Logger.getLogger(Bootstrap.class
- .getName());
- /** List of logger objects that have level overrides configured. */
- private final ArrayList<Logger> loggers = new ArrayList<Logger>();
- /** Constructor */
- public Bootstrap() {
- }
- // members
- /**
- * Read configuration from inside jar file, and configFile.
- *
- * @param configFile
- * config file to load.
- * @return
- * config
- * @throws IOException
- * if IO error occurs
- */
- public Config loadConfig(final File configFile) throws IOException {
- Config config = new Config();
- // load defaults from jar file
- InputStream in = Bootstrap.class.getClassLoader().getResourceAsStream(
- JAR_CONFIGFILE);
- if (in != null) {
- try {
- config.load(in);
- } finally {
- StreamUtils.closeStream(in);
- }
- } else {
- LOGGER.config("Jar configuration not found");
- }
- // override settings with a config file
- if (configFile.exists()) {
- LOGGER.config("Loading configuration file "
- + configFile.getCanonicalPath());
- config = new Config(config);
- in = StreamUtils.getInputStream(configFile);
- try {
- config.load(in);
- } finally {
- StreamUtils.closeStream(in);
- }
- }
- return config;
- }
- /**
- * Sets up LogManager
- * @param config Config file
- */
- public void setupLogging(final Config config) {
- final LogManager logManager = LogManager.getLogManager();
- logManager.reset();
- loggers.clear();
- // logging is noisy without this
- for (final String name : new String[]{
- "com.sun.activation",
- "com.sun.xml.bind",
- "javax.xml.bind",
- "org.glassfish.grizzly",
- "org.glassfish.tyrus",
- "sun.awt.X11.timeoutTask.XToolkit"
- }) {
- final Logger logger = Logger.getLogger(name);
- logger.setLevel(Level.INFO);
- // save reference to logger since LogManager uses weakref
- loggers.add(logger);
- };
- final Level level = Level.parse(config.getProperty(LOGLEVEL_PROPERTY_NAME,
- DEFAULT_LOGLEVEL));
- final String logDirectory = config.getProperty(LOGDIRECTORY_PROPERTY_NAME,
- DEFAULT_LOGDIRECTORY);
- LOGGER.config("Logging Level '" + level + "'");
- LOGGER.config("Log directory '" + logDirectory + "'");
- Logger rootLogger = Logger.getLogger("");
- rootLogger.setLevel(level);
- try {
- File logDirectoryFile = new File(logDirectory);
- if (!logDirectoryFile.exists()) {
- LOGGER.fine("Creating log directory");
- if (!logDirectoryFile.mkdirs()) {
- LOGGER.warning("Unable to create log directory");
- }
- }
- // filepattern, maxBytesPerFile, maxFiles, append
- // FileHandler handler = new FileHandler(logFile, 100000, 10, true);
- Handler handler = new SimpleLogFileHandler(logDirectoryFile,
- new SimpleDateFormat(DEFAULT_LOGFILE));
- handler.setLevel(level);
- rootLogger.addHandler(handler);
- } catch (Exception e) {
- LOGGER.log(Level.WARNING, "Unable to create log file handler", e);
- }
- String redirectConsole = config.getProperty(
- CONSOLEREDIRECT_PROPERTY_NAME, DEFAULT_CONSOLEREDIRECT);
- if (!redirectConsole.equals(DEFAULT_CONSOLEREDIRECT)) {
- // default is off, so enable
- System.err.println("Redirecting STDOUT and STDERR to log file");
- System.setOut(new PrintStream(new LoggingOutputStream(Logger
- .getLogger("stdout"), StdOutErrLevel.STDOUT)));
- System.setErr(new PrintStream(new LoggingOutputStream(Logger
- .getLogger("stderr"), StdOutErrLevel.STDERR)));
- } else {
- ConsoleHandler handler = new ConsoleHandler();
- handler.setLevel(level);
- rootLogger.addHandler(handler);
- }
- Formatter formatter;
- String logFormat = config.getProperty(
- LOGFORMAT_PROPERTY_NAME, DEFAULT_LOGFORMAT);
- if (logFormat.equals(LOGFORMAT_SIMPLE)) {
- // built in simple formatter
- formatter = new SimpleFormatter();
- } else if (logFormat.equals(LOGFORMAT_XML)) {
- // built in xml formatter
- formatter = new XMLFormatter();
- } else {
- // pdl style simple formatter
- formatter = new SimpleLogFormatter();
- }
- for (Handler handler : rootLogger.getHandlers()) {
- handler.setFormatter(formatter);
- }
- }
- public static void main(final String[] args) throws Exception {
- StringBuffer argumentList = new StringBuffer();
- boolean configTest = false;
- String className = null;
- // use default config file
- File configFile = new File(DEFAULT_CONFIGFILE);
- for (String arg : args) {
- argumentList.append(arg).append(" ");
- if (arg.startsWith(CONFIGFILE_ARGUMENT)) {
- // unless config file argument provided
- configFile = new File(arg.replace(CONFIGFILE_ARGUMENT, ""));
- } else if (arg.equals(CONFIG_TEST_ARGUMENT)) {
- configTest = true;
- } else if (arg.startsWith(MAINCLASS_ARGUMENT)) {
- className = arg.replace(MAINCLASS_ARGUMENT, "");
- } else if (arg.equals(VERSION_ARGUMENT)) {
- System.err.println("Product Distribution Client");
- System.err.println(ProductClient.RELEASE_VERSION);
- System.exit(0);
- }
- }
- Bootstrap bootstrap = new Bootstrap();
- // load configuration file
- Config config = bootstrap.loadConfig(configFile);
- // set global config object
- Config.setConfig(config);
- // setup logging based on configuration
- bootstrap.setupLogging(config);
- // java and os information
- LOGGER.config("java.vendor = " + System.getProperty("java.vendor"));
- LOGGER.config("java.version = " + System.getProperty("java.version"));
- LOGGER.config("java.home = " + System.getProperty("java.home"));
- LOGGER.config("os.arch = " + System.getProperty("os.arch"));
- LOGGER.config("os.name = " + System.getProperty("os.name"));
- LOGGER.config("os.version = " + System.getProperty("os.version"));
- LOGGER.config("user.dir = " + System.getProperty("user.dir"));
- LOGGER.config("user.name = " + System.getProperty("user.name"));
- // log command line arguments
- LOGGER.fine("Command line arguments: " + argumentList.toString().trim());
- // configure whether tracker updates are sent.
- String enableTrackerProperty = config
- .getProperty(ENABLE_TRACKER_PROPERTY_NAME);
- if (Boolean.valueOf(enableTrackerProperty)) {
- LOGGER.warning("Enabled tracker updates,"
- + " this is usually not a good idea.");
- ProductTracker.setTrackerEnabled(true);
- }
- // lookup main class
- if (className == null) {
- // no argument specified, check configuration
- className = config.getProperty(MAINCLASS_PROPERTY_NAME,
- DEFAULT_MAINCLASS);
- }
- // invoke main class main(String[] args) method
- LOGGER.config("Loading main class " + className);
- Bootstrappable main = null;
- try {
- main = (Bootstrappable) Class.forName(className)
- .getConstructor().newInstance();
- } catch (ClassCastException cce) {
- LOGGER.log(Level.SEVERE,
- "Main class must implement the Bootstrappable interface",
- cce);
- System.exit(1);
- }
- // use the configurable interface when available
- if (main instanceof Configurable) {
- Configurable configurable = ((Configurable) main);
- configurable.setName("main");
- try {
- configurable.configure(config);
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Exception loading configuration ", e);
- System.exit(1);
- }
- }
- // configuration loaded okay
- LOGGER.config("Configuration loaded");
- if (configTest) {
- // exit successfully
- System.exit(0);
- }
- // run main instance
- LOGGER.config("Bootstrap complete, running main class\n");
- try {
- main.run(args);
- } catch (Exception e) {
- LOGGER.log(Level.SEVERE, "Main class threw exception, exiting", e);
- System.exit(Bootstrappable.RUN_EXCEPTION_EXIT_CODE);
- }
- }
- }