org.apache.qpid.server.Main.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.qpid.server.Main.java

Source

/*
 *
 * 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);
    }

}