org.echocat.jconscius.cluster.impl.relay.station.RelayStationLauncher.java Source code

Java tutorial

Introduction

Here is the source code for org.echocat.jconscius.cluster.impl.relay.station.RelayStationLauncher.java

Source

/*****************************************************************************************
 * *** BEGIN LICENSE BLOCK *****
 *
 * Version: MPL 2.0
 *
 * echocat jConscius, Copyright (c) 2010-2012 echocat
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * *** END LICENSE BLOCK *****
 ****************************************************************************************/

package org.echocat.jconscius.cluster.impl.relay.station;

import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Collection;
import java.util.HashSet;

@SuppressWarnings({ "CallToSystemExit", "UseOfSystemOutOrSystemErr" })
public class RelayStationLauncher {

    private static final Logger LOG = LoggerFactory.getLogger(RelayStationLauncher.class);

    private static final int DEFAULT_PORT = 11256;
    private static final String DEFAULT_NAME = "default";
    private static final int DEFAULT_RECONNECT_TIMEOUT = 1000;

    private static final Options OPTIONS = new Options();
    private static final Option HELP_OPTION = new Option("h", "help", false, "Print this help.");
    private static final Option LISTEN_OPTION = new Option("l", "listen", true,
            "Port and address to listen on. Default: 0.0.0.0:" + DEFAULT_PORT);
    private static final Option NAME_OPTION = new Option("n", "name", true,
            "Name of this station. This name is unique in the cluster. Default: " + DEFAULT_NAME);
    private static final Option RECONNECTION_TIMEOUT_OPTION = new Option("t", "reconnect-timeout", true,
            "The timeout for reconnect in milli seconds if the server socket is broken and have to be reconnected. Default: "
                    + DEFAULT_RECONNECT_TIMEOUT);

    private RelayStationLauncher() {
    }

    static {
        OPTIONS.addOption(HELP_OPTION);

        LISTEN_OPTION.setRequired(false);
        LISTEN_OPTION.setArgName("[address:]port");
        LISTEN_OPTION.setValueSeparator(';');
        OPTIONS.addOption(LISTEN_OPTION);

        NAME_OPTION.setRequired(false);
        NAME_OPTION.setArgName("name");
        OPTIONS.addOption(NAME_OPTION);

        RECONNECTION_TIMEOUT_OPTION.setRequired(false);
        RECONNECTION_TIMEOUT_OPTION.setArgName("milliseconds");
        OPTIONS.addOption(RECONNECTION_TIMEOUT_OPTION);
    }

    public static void main(String[] arguments) throws Exception {
        final RelayStation station = createStation(arguments);
        if (station != null) {
            final Object lock = new Object();
            final Thread shutdownThread = new Thread("ShutdownHook") {
                @Override
                public void run() {
                    LOG.info("Station is going down now...");
                    station.close();
                    LOG.info("Station is down! Bye.");
                    synchronized (lock) {
                        lock.notifyAll();
                    }
                }
            };
            Runtime.getRuntime().addShutdownHook(shutdownThread);
            LOG.info("Station is starting...");
            station.init();
            LOG.info("Station is ready!");

            //noinspection SynchronizationOnLocalVariableOrMethodParameter
            synchronized (lock) {
                lock.wait();
            }
        }
    }

    private static RelayStation createStation(String[] arguments) {
        final CommandLineParser parser = new GnuParser();
        RelayStation station = null;
        try {
            final CommandLine line = parser.parse(OPTIONS, arguments);
            if (line.hasOption(HELP_OPTION.getOpt())) {
                printHelper(null);
            } else {
                station = new RelayStation();
                final String[] listenValues = line.getOptionValues(LISTEN_OPTION.getOpt());
                final Collection<SocketAddress> listen = new HashSet<SocketAddress>();
                if (listenValues != null) {
                    for (String listenValue : listenValues) {
                        if (listenValue != null) {
                            final String hostName;
                            final String portString;
                            final int lastDouble = listenValue.lastIndexOf(':');
                            if (lastDouble >= 0) {
                                hostName = listenValue.substring(0, lastDouble);
                                portString = listenValue.substring(lastDouble + 1);
                            } else {
                                hostName = null;
                                portString = listenValue;
                            }
                            final int port = parsePositiveInteger(portString, "port number");
                            if (hostName != null) {
                                listen.add(new InetSocketAddress(hostName, port));
                            } else {
                                listen.add(new InetSocketAddress((InetAddress) null, port));
                            }
                        }
                    }
                }
                if (listen.isEmpty()) {
                    listen.add(new InetSocketAddress((InetAddress) null, DEFAULT_PORT));
                }
                station.setAddresses(listen);

                final String name = line.getOptionValue(NAME_OPTION.getOpt());
                station.setName(name != null && !name.isEmpty() ? name : DEFAULT_NAME);

                final String reconnectTimeoutString = line.getOptionValue(RECONNECTION_TIMEOUT_OPTION.getOpt());
                station.setReconnectTimeout(reconnectTimeoutString != null
                        ? parsePositiveInteger(reconnectTimeoutString, "milliseconds")
                        : DEFAULT_RECONNECT_TIMEOUT);
            }
        } catch (ParseException e) {
            printHelper(e);
            System.exit(1);
        }
        return station;
    }

    private static int parsePositiveInteger(String string, String messageName) throws ParseException {
        final int result;
        try {
            result = Integer.parseInt(string.trim());
        } catch (NumberFormatException ignored) {
            //noinspection ThrowInsideCatchBlockWhichIgnoresCaughtException
            throw new ParseException("'" + string + "' is not a valid " + messageName + ".");
        }
        if (result <= 0) {
            throw new ParseException("'" + string + "' is not a valid " + messageName + ".");
        }
        return result;
    }

    private static void printHelper(ParseException e) {
        final HelpFormatter formatter = new HelpFormatter();
        final PrintWriter writer = new PrintWriter(e != null ? System.err : System.out);
        writer.println("RelayStation 1.0");
        if (e != null) {
            writer.println("error: " + e.getMessage());
        }
        formatter.printHelp(writer, HelpFormatter.DEFAULT_WIDTH, "station [arguments]", "arguments:", OPTIONS,
                HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD, null);
        writer.flush();
    }

}