Java tutorial
/* * * 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.qpid.server; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.qpid.configuration.CommonProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.logback.LogbackLoggingSystemLauncherListener; import org.apache.qpid.server.model.AbstractSystemConfig; import org.apache.qpid.server.model.JsonSystemConfigImpl; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.SystemConfig; import org.apache.qpid.server.plugin.ProtocolEngineCreator; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.util.StringUtil; import org.apache.qpid.util.FileUtils; /** * Main entry point for AMQPD. * */ public class Main { public static final String PROPERTY_QPID_HOME = "QPID_HOME"; /** * Configuration property name for the absolute path to use for the broker home directory. * * If not otherwise set, the value for this configuration property defaults to the location * set in the "QPID_HOME" system property if that was set, or remains unset if it was not. */ private static final String QPID_HOME_DIR = "qpid.home_dir"; private static final int MANAGEMENT_MODE_PASSWORD_LENGTH = 10; private static final Option OPTION_HELP = new Option("h", "help", false, "print this message"); private static final Option OPTION_VERSION = new Option("v", "version", false, "print the version information and exit"); private static final Option OPTION_CONFIGURATION_STORE_PATH = OptionBuilder.withArgName("path").hasArg() .withDescription("use given configuration store location").withLongOpt("store-path").create("sp"); private static final Option OPTION_CONFIGURATION_STORE_TYPE = OptionBuilder.withArgName("type").hasArg() .withDescription("use given broker configuration store type").withLongOpt("store-type").create("st"); private static final Option OPTION_INITIAL_CONFIGURATION_PATH = OptionBuilder.withArgName("path").hasArg() .withDescription( "set the location of initial JSON config to use when creating/overwriting a broker configuration store") .withLongOpt("initial-config-path").create("icp"); private static final Option OPTION_CREATE_INITIAL_CONFIG = OptionBuilder.withArgName("path").hasOptionalArg() .withDescription("create a copy of the initial config file, either to an" + " optionally specified file path, or as " + SystemConfig.DEFAULT_INITIAL_CONFIG_NAME + " in the current directory") .withLongOpt("create-initial-config").create("cic"); private static final Option OPTION_CONFIGURATION_PROPERTY = OptionBuilder.withArgName("name=value").hasArg() .withDescription( "set a configuration property to use when resolving variables in the broker configuration store, with format \"name=value\"") .withLongOpt("config-property").create("prop"); private static final Option OPTION_MANAGEMENT_MODE = OptionBuilder .withDescription("start broker in management mode, disabling the AMQP ports") .withLongOpt("management-mode").create("mm"); private static final Option OPTION_MM_QUIESCE_VHOST = OptionBuilder .withDescription("make virtualhosts stay in the quiesced state during management mode.") .withLongOpt("management-mode-quiesce-virtualhosts").create("mmqv"); private static final Option OPTION_MM_HTTP_PORT = OptionBuilder.withArgName("port").hasArg() .withDescription("override http management port in management mode") .withLongOpt("management-mode-http-port").create("mmhttp"); private static final Option OPTION_MM_PASSWORD = OptionBuilder.withArgName("password").hasArg() .withDescription( "Set the password for the management mode user " + SystemConfig.MANAGEMENT_MODE_USER_NAME) .withLongOpt("management-mode-password").create("mmpass"); private static final Option OPTION_INITIAL_SYSTEM_PROPERTIES = OptionBuilder.withArgName("path").hasArg() .withDescription("set the location of initial properties file to set otherwise unset system properties") .withLongOpt("system-properties-file").create("props"); private static final Options OPTIONS = new Options(); static { OPTIONS.addOption(OPTION_HELP); OPTIONS.addOption(OPTION_VERSION); OPTIONS.addOption(OPTION_CONFIGURATION_STORE_PATH); OPTIONS.addOption(OPTION_CONFIGURATION_STORE_TYPE); OPTIONS.addOption(OPTION_CREATE_INITIAL_CONFIG); OPTIONS.addOption(OPTION_INITIAL_CONFIGURATION_PATH); OPTIONS.addOption(OPTION_MANAGEMENT_MODE); OPTIONS.addOption(OPTION_MM_QUIESCE_VHOST); OPTIONS.addOption(OPTION_MM_HTTP_PORT); OPTIONS.addOption(OPTION_MM_PASSWORD); OPTIONS.addOption(OPTION_CONFIGURATION_PROPERTY); OPTIONS.addOption(OPTION_INITIAL_SYSTEM_PROPERTIES); CommonProperties.ensureIsLoaded(); } protected CommandLine _commandLine; public static void main(String[] args) { new Main(args); } public Main(final String[] args) { if (parseCommandline(args)) { try { execute(); } catch (Exception e) { System.err.println("Exception during startup: " + e); e.printStackTrace(); shutdown(1); } } } protected boolean parseCommandline(final String[] args) { try { _commandLine = new PosixParser().parse(OPTIONS, args); return true; } catch (ParseException e) { System.err.println("Error: " + e.getMessage()); HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("Qpid", OPTIONS, true); return false; } } protected void execute() throws Exception { Map<String, Object> attributes = new HashMap<>(); String initialProperties = _commandLine.getOptionValue(OPTION_INITIAL_SYSTEM_PROPERTIES.getOpt()); SystemLauncher.populateSystemPropertiesFromDefaults(initialProperties); String initialConfigLocation = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_PATH.getOpt()); if (initialConfigLocation != null) { attributes.put(SystemConfig.INITIAL_CONFIGURATION_LOCATION, initialConfigLocation); } //process the remaining options if (_commandLine.hasOption(OPTION_HELP.getOpt())) { final HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("Qpid", OPTIONS, true); } else if (_commandLine.hasOption(OPTION_CREATE_INITIAL_CONFIG.getOpt())) { createInitialConfigCopy(initialConfigLocation); } else if (_commandLine.hasOption(OPTION_VERSION.getOpt())) { printVersion(); } else { String[] configPropPairs = _commandLine.getOptionValues(OPTION_CONFIGURATION_PROPERTY.getOpt()); Map<String, String> context = calculateConfigContext(configPropPairs); if (!context.isEmpty()) { attributes.put(SystemConfig.CONTEXT, context); } String configurationStore = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_PATH.getOpt()); if (configurationStore != null) { attributes.put("storePath", configurationStore); } String configurationStoreType = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_TYPE.getOpt()); attributes.put(SystemConfig.TYPE, configurationStoreType == null ? JsonSystemConfigImpl.SYSTEM_CONFIG_TYPE : configurationStoreType); boolean managementMode = _commandLine.hasOption(OPTION_MANAGEMENT_MODE.getOpt()); if (managementMode) { attributes.put(SystemConfig.MANAGEMENT_MODE, true); String httpPort = _commandLine.getOptionValue(OPTION_MM_HTTP_PORT.getOpt()); if (httpPort != null) { attributes.put(SystemConfig.MANAGEMENT_MODE_HTTP_PORT_OVERRIDE, httpPort); } boolean quiesceVhosts = _commandLine.hasOption(OPTION_MM_QUIESCE_VHOST.getOpt()); attributes.put(SystemConfig.MANAGEMENT_MODE_QUIESCE_VIRTUAL_HOSTS, quiesceVhosts); String password = _commandLine.getOptionValue(OPTION_MM_PASSWORD.getOpt()); if (password == null) { password = new StringUtil().randomAlphaNumericString(MANAGEMENT_MODE_PASSWORD_LENGTH); } attributes.put(SystemConfig.MANAGEMENT_MODE_PASSWORD, password); } setExceptionHandler(); startBroker(attributes); } } private Map<String, String> calculateConfigContext(final String[] configPropPairs) { Map<String, String> context = new HashMap<>(); if (configPropPairs != null && configPropPairs.length > 0) { for (String s : configPropPairs) { int firstEquals = s.indexOf("="); if (firstEquals == -1) { throw new IllegalArgumentException( "Configuration property argument is not of the format name=value: " + s); } String name = s.substring(0, firstEquals); String value = s.substring(firstEquals + 1); if (name.equals("")) { throw new IllegalArgumentException( "Configuration property argument is not of the format name=value: " + s); } context.put(name, value); } } if (!context.containsKey(QPID_HOME_DIR)) { Properties systemProperties = System.getProperties(); final Map<String, String> environment = System.getenv(); if (systemProperties.containsKey(QPID_HOME_DIR)) { context.put(QPID_HOME_DIR, systemProperties.getProperty(QPID_HOME_DIR)); } else if (environment.containsKey(QPID_HOME_DIR)) { context.put(QPID_HOME_DIR, environment.get(QPID_HOME_DIR)); } else if (context.containsKey(PROPERTY_QPID_HOME)) { context.put(QPID_HOME_DIR, context.get(PROPERTY_QPID_HOME)); } else if (systemProperties.containsKey(PROPERTY_QPID_HOME)) { context.put(QPID_HOME_DIR, systemProperties.getProperty(PROPERTY_QPID_HOME)); } else if (environment.containsKey(PROPERTY_QPID_HOME)) { context.put(QPID_HOME_DIR, environment.get(PROPERTY_QPID_HOME)); } } return context; } private void printVersion() { final StringBuilder protocol = new StringBuilder("AMQP version(s) [major.minor]: "); boolean first = true; Set<Protocol> protocols = new TreeSet<>(); for (ProtocolEngineCreator installedEngine : (new QpidServiceLoader()) .instancesOf(ProtocolEngineCreator.class)) { protocols.add(installedEngine.getVersion()); } for (Protocol supportedProtocol : protocols) { if (first) { first = false; } else { protocol.append(", "); } protocol.append(supportedProtocol.getProtocolVersion()); } System.out.println(CommonProperties.getVersionString() + " (" + protocol + ")"); } private void createInitialConfigCopy(String initialConfigLocation) { File destinationFile = null; String destinationOption = _commandLine.getOptionValue(OPTION_CREATE_INITIAL_CONFIG.getOpt()); if (destinationOption != null) { destinationFile = new File(destinationOption); } else { destinationFile = new File(System.getProperty("user.dir"), SystemConfig.DEFAULT_INITIAL_CONFIG_NAME); } if (initialConfigLocation == null) { initialConfigLocation = AbstractSystemConfig .getDefaultValue(SystemConfig.INITIAL_CONFIGURATION_LOCATION); } copyInitialConfigFile(initialConfigLocation, destinationFile); System.out.println("Initial config written to: " + destinationFile.getAbsolutePath()); } private void copyInitialConfigFile(final String initialConfigLocation, final File destinationFile) { URL url = null; try { url = new URL(initialConfigLocation); } catch (MalformedURLException e) { File locationFile = new File(initialConfigLocation); try { url = locationFile.toURI().toURL(); } catch (MalformedURLException e1) { throw new IllegalConfigurationException("Cannot create URL for file " + locationFile, e1); } } InputStream in = null; try { in = url.openStream(); FileUtils.copy(in, destinationFile); } catch (IOException e) { throw new IllegalConfigurationException("Cannot create file " + destinationFile + " by copying initial config from " + initialConfigLocation, e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { throw new IllegalConfigurationException( "Cannot close initial config input stream: " + initialConfigLocation, e); } } } } protected void setExceptionHandler() { Thread.UncaughtExceptionHandler handler = null; String handlerClass = System.getProperty("qpid.broker.exceptionHandler"); if (handlerClass != null) { try { handler = (Thread.UncaughtExceptionHandler) Class.forName(handlerClass).newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | ClassCastException e) { } } if (handler == null) { handler = new Thread.UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { boolean continueOnError = Boolean.getBoolean("qpid.broker.exceptionHandler.continue"); try { System.err.println( "########################################################################"); System.err.println("#"); System.err.print("# Unhandled Exception "); System.err.print(e.toString()); System.err.print(" in Thread "); System.err.println(t.getName()); System.err.println("#"); System.err.println(continueOnError ? "# Forced to continue by JVM setting 'qpid.broker.exceptionHandler.continue'" : "# Exiting"); System.err.println("#"); System.err.println( "########################################################################"); e.printStackTrace(System.err); Logger logger = LoggerFactory.getLogger("org.apache.qpid.server.Main"); logger.error("Uncaught exception, " + (continueOnError ? "continuing." : "shutting down."), e); } finally { if (!continueOnError) { Runtime.getRuntime().halt(1); } } } }; Thread.setDefaultUncaughtExceptionHandler(handler); } } protected void startBroker(Map<String, Object> attributes) throws Exception { SystemLauncher systemLauncher = new SystemLauncher(new LogbackLoggingSystemLauncherListener(), new SystemLauncherListener.DefaultSystemLauncherListener() { @Override public void onShutdown(final int exitCode) { if (exitCode != 0) { shutdown(exitCode); } } }); systemLauncher.startup(attributes); } protected void shutdown(final int status) { System.exit(status); } }