com.phonytive.astive.server.AstiveServer.java Source code

Java tutorial

Introduction

Here is the source code for com.phonytive.astive.server.AstiveServer.java

Source

/* 
 * Copyright (C) 2010-2013 PhonyTive LLC
 * http://astive.phonytive.com
 *
 * This file is part of Astive Toolkit
 *
 * Astive is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Astive is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Astive.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.phonytive.astive.server;

import com.phonytive.astive.server.admin.AdminCommand;
import com.phonytive.astive.server.admin.AdminDaemon;
import com.phonytive.astive.server.admin.AdminDaemonClient;
import com.phonytive.astive.server.appmanager.DeployerManager;
import com.phonytive.astive.server.monitor.ConnectionMonitor;
import com.phonytive.astive.server.monitor.FastAgiConnectionMonitor;
import com.phonytive.astive.server.utils.InitOutput;
import com.phonytive.astive.server.utils.ServiceProperties;
import com.phonytive.astive.server.utils.ServicePropertiesImpl;
import com.phonytive.astive.telnet.TelnetServer;
import com.phonytive.astive.util.AppLocale;
import com.phonytive.astive.util.NetUtil;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import static java.lang.System.out;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.cli.*;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

/**
 *
 * @since 1.0.0
 * @see AbstractAstiveServer
 */
public class AstiveServer extends AbstractAstiveServer {
    // A usual logging class

    private static final Logger logger = Logger.getLogger(AstiveServer.class);
    private static ServiceProperties adminDaemonSP;
    private static ServiceProperties astivedSP;
    private static ServiceProperties telnedSP;
    private static String ASTIVED_PROPERTIES = AbstractAstiveServer.ASTIVE_HOME + "/conf/astived.properties";
    private static String ADMIN_DAEMON_PROPERTIES = AbstractAstiveServer.ASTIVE_HOME + "/conf/admin.properties";
    private static String TELNED_PROPERTIES = AbstractAstiveServer.ASTIVE_HOME + "/conf/telned.properties";
    private ExecutorService executorService;
    {
        DOMConfigurator.configure(AbstractAstiveServer.ASTIVE_HOME + "/conf/log4j.xml");
    }

    /**
     * Creates a new AstiveServer object.
     *
     * @param port DOCUMENT ME!
     * @param backlog DOCUMENT ME!
     * @param bindAddr DOCUMENT ME!
     *
     * @throws SystemException DOCUMENT ME!
     * @throws IOException DOCUMENT ME!
     */
    public AstiveServer(int port, int backlog, InetAddress bindAddr) throws SystemException, IOException {
        super(port, backlog, bindAddr);
    }

    private static ServiceProperties getServiceProperties(String propPath, String serviceName)
            throws SystemException, IOException {
        Properties prop = new Properties();

        try {
            prop.load(new FileInputStream(propPath));

            return new ServicePropertiesImpl(prop, serviceName);
        } catch (FileNotFoundException ex) {
            throw new SystemException(
                    AppLocale.getI18n("unableToReadFile", new Object[] { propPath, ex.getMessage() }));
        }
    }

    private static boolean isCommand(String cmd) {
        AdminCommand ac = AdminCommand.get(cmd);
        if (ac == null) {
            return false;
        }
        return true;
    }

    private static boolean isFileJar(String file) {
        if (file.endsWith(".jar")) {
            return true;
        }

        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void launchConnectionMonitor() {
        ConnectionMonitor monitor = new FastAgiConnectionMonitor(this, astivedSP.getBacklog());
        executorService.execute(monitor);
    }

    public static void main(String[] args) throws Exception {
        astivedSP = getServiceProperties(ASTIVED_PROPERTIES, "astived");
        adminDaemonSP = getServiceProperties(ADMIN_DAEMON_PROPERTIES, "admin thread");
        telnedSP = getServiceProperties(TELNED_PROPERTIES, "telned");

        ArrayList<ServiceProperties> serviceProperties = new ArrayList();
        serviceProperties.add(astivedSP);

        if (!adminDaemonSP.isDisabled()) {
            serviceProperties.add(adminDaemonSP);
        }

        if (!telnedSP.isDisabled()) {
            serviceProperties.add(telnedSP);
        }

        if ((args.length == 0) || args[0].equals("-h") || args[0].equals("--help")) {
            printUsage();
            System.exit(1);
        }

        // Create a Parser
        CommandLineParser parser = new BasicParser();

        Options start = new Options();
        start.addOption("h", "help", false, AppLocale.getI18n("cli.option.printUsage"));
        start.addOption("v", "version", false, "Prints the Astive Server version and exits.");
        start.addOption("d", "debug", false, AppLocale.getI18n("cli.option.debug"));
        start.addOption("q", "quiet", false, AppLocale.getI18n("cli.option.daemonMode"));
        start.addOption(OptionBuilder.hasArg(true).withArgName("host").withLongOpt("admin-bind")
                .withDescription("" + AppLocale.getI18n("cli.option.bind", new Object[] { "admin" })).create());
        start.addOption(OptionBuilder.hasArg(true).withArgName("port").withLongOpt("admin-port")
                .withDescription("" + AppLocale.getI18n("cli.option.port", new Object[] { "admin" })).create());
        start.addOption(OptionBuilder.hasArg(true).withArgName("port").withLongOpt("astived-port")
                .withDescription("" + AppLocale.getI18n("cli.option.port", new Object[] { "astived" })).create());

        start.addOption(OptionBuilder.hasArg(true).withArgName("host").withLongOpt("astived-host")
                .withDescription("" + AppLocale.getI18n("cli.option.bind", new Object[] { "astived" })).create());
        start.addOption(OptionBuilder.hasArg(true).withArgName("port").withLongOpt("telned-port")
                .withDescription("" + AppLocale.getI18n("cli.option.port", new Object[] { "telned" })).create());

        start.addOption(OptionBuilder.hasArg(true).withArgName("host").withLongOpt("telned-host")
                .withDescription("" + AppLocale.getI18n("cli.option.host", new Object[] { "telned" })).create());

        Options stop = new Options();
        stop.addOption(OptionBuilder.withLongOpt("--help")
                .withDescription("" + AppLocale.getI18n("cli.option.printUsage")).create());

        stop.addOption("h", "host", false,
                AppLocale.getI18n("cli.option.stop.host", new Object[] { DEFAULT_AGI_SERVER_BIND_ADDR }));

        stop.addOption("p", "port", false,
                AppLocale.getI18n("cli.option.stop.port", new Object[] { DEFAULT_AGI_SERVER_PORT }));

        Options deploy = new Options();
        deploy.addOption("h", "help", false, AppLocale.getI18n("cli.option.printUsage"));

        Options undeploy = new Options();
        undeploy.addOption("h", "help", false, AppLocale.getI18n("cli.option.printUsage"));

        if (args.length == 0) {
            printUsage();
            System.exit(1);
        } else if (!isCommand(args[0])) {
            printUnavailableCmd(args[0]);
            System.exit(1);
        }

        AdminCommand cmd = AdminCommand.get(args[0]);

        if (cmd.equals(AdminCommand.DEPLOY) && ((args.length < 2) || !isFileJar(args[1]))) {
            logger.error(AppLocale.getI18n("cli.invalid.app"));
            printUsage(AdminCommand.DEPLOY, deploy);
            System.exit(1);
        }

        if (cmd.equals(AdminCommand.UNDEPLOY) && ((args.length < 2) || !isFileJar(args[1]))) {
            printUsage(AdminCommand.UNDEPLOY, undeploy);
            System.exit(1);
        }

        // Parse the program arguments
        try {
            if (cmd.equals(AdminCommand.START)) {
                CommandLine commandLine = parser.parse(start, args);

                if (commandLine.hasOption('h')) {
                    printUsage(cmd, start);
                    System.exit(0);
                }

                if (commandLine.hasOption('v')) {
                    // Them start the server without noise
                }

                if (commandLine.hasOption("astived-bind")) {
                    astivedSP.setBindAddr(InetAddress.getByName(commandLine.getOptionValue("astived-port")));
                }

                if (commandLine.hasOption("astived-port")) {
                    astivedSP.setPort(Integer.parseInt(commandLine.getOptionValue("astived-port")));
                }

                if (commandLine.hasOption("admin-bind")) {
                    adminDaemonSP.setBindAddr(InetAddress.getByName(commandLine.getOptionValue("admin-bind")));
                }

                if (commandLine.hasOption("admin-port")) {
                    adminDaemonSP.setPort(Integer.parseInt(commandLine.getOptionValue("admin-port")));
                }

                if (commandLine.hasOption("telned-bind")) {
                    telnedSP.setBindAddr(InetAddress.getByName(commandLine.getOptionValue("telned-bind")));
                }

                if (commandLine.hasOption("telned-port")) {
                    adminDaemonSP.setPort(Integer.parseInt(commandLine.getOptionValue("telned-port")));
                }

                if (!NetUtil.available(astivedSP.getPort())) {
                    out.println(AppLocale.getI18n("cantStartFastAgiServerSocket",
                            new Object[] { astivedSP.getBindAddr().getHostAddress(), astivedSP.getPort() }));
                    System.exit(-1);
                }

                if (!NetUtil.available(adminDaemonSP.getPort())) {
                    adminDaemonSP.setUnableToOpen(true);
                }

                if (!NetUtil.available(telnedSP.getPort())) {
                    telnedSP.setUnableToOpen(true);
                }

                InitOutput.printInit(serviceProperties);

                AstiveServer server = new AstiveServer(astivedSP.getPort(), astivedSP.getBacklog(),
                        astivedSP.getBindAddr());
                server.start();
            }

            if (!cmd.equals(AdminCommand.START) && adminDaemonSP.isDisabled()) {
                logger.info("unableToAccessAdminDaemon");
            }

            if (cmd.equals(AdminCommand.STOP)) {
                CommandLine commandLine = parser.parse(stop, args);

                if (commandLine.hasOption("--help")) {
                    printUsage(cmd, stop);
                    System.exit(0);
                }

                if (commandLine.hasOption('h')) {
                    if (commandLine.getOptionValue('h') == null) {
                        printUsage(cmd, stop);
                        System.exit(0);
                    }

                    astivedSP.setBindAddr(InetAddress.getByName(commandLine.getOptionValue('h')));
                }

                if (commandLine.hasOption('p')) {
                    if (commandLine.getOptionValue('p') == null) {
                        printUsage(cmd, stop);
                        System.exit(0);
                    }

                    astivedSP.setPort(Integer.parseInt(commandLine.getOptionValue('p')));
                }

                AdminDaemonClient adClient = new AdminDaemonClient(adminDaemonSP.getBindAddr(),
                        adminDaemonSP.getPort());
                adClient.stop();
            }

            // TODO: This needs to be researched before a full implementation.
            // for now is only possible to do deployments into the local server.
            if (cmd.equals(AdminCommand.DEPLOY)) {
                AdminDaemonClient adClient = new AdminDaemonClient(adminDaemonSP.getBindAddr(),
                        adminDaemonSP.getPort());
                adClient.deploy(args[1]);
            }

            if (cmd.equals(AdminCommand.UNDEPLOY)) {
                AdminDaemonClient adClient = new AdminDaemonClient(adminDaemonSP.getBindAddr(),
                        adminDaemonSP.getPort());
                adClient.undeploy(args[1]);
            }
        } catch (java.net.ConnectException ex) {
            logger.info("serverNotRunning");
        } catch (Exception ex) {
            logger.error(AppLocale.getI18n("unexpectedError", new Object[] { ex.getMessage() }));
        }
    }

    // <editor-fold defaultstate="collapsed" desc="Support methods">
    private static void printUnavailableCmd(String cmd) {
        out.println(AppLocale.getI18n("cli.unavailableCommand", new Object[] { cmd }));
        out.println(AppLocale.getI18n("cli.availableCommands"));
    }

    private static void printUsage() {
        out.println(AppLocale.getI18n("cli.usage"));
        out.println(AppLocale.getI18n("cli.availableCommands"));
        out.println(AppLocale.getI18n("cli.help"));
        out.println(AppLocale.getI18n("cli.footer"));
    }

    private static void printUsage(AdminCommand ac, Options options) {
        String command = ac.getCommand();
        HelpFormatter helpFormatter = new HelpFormatter();
        helpFormatter.setWidth(80);
        helpFormatter.printHelp(AppLocale.getI18n("cli." + command + ".usage"), AppLocale.getI18n("cli.header"),
                options, AppLocale.getI18n("cli.footer"));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void start() throws SystemException {
        super.start();

        // Load properties for admin daemon
        InetAddress adminBindAddr = adminDaemonSP.getBindAddr();
        int adminPort = adminDaemonSP.getPort();
        int adminBacklog = adminDaemonSP.getBacklog();

        // Load properties for telnet
        InetAddress telnedBindAddr = telnedSP.getBindAddr();
        int telnedPort = telnedSP.getPort();
        int telnedBacklog = telnedSP.getBacklog();

        // Load apps already in "apps"
        DeployerManager.getInstance();

        executorService = Executors.newFixedThreadPool(3);
        launchConnectionMonitor();

        try {
            if (!adminDaemonSP.isDisabled()) {
                AdminDaemon admin = new AdminDaemon(adminPort, adminBacklog, adminBindAddr, this);
                executorService.execute(admin);
            }

            if (!telnedSP.isDisabled()) {

                final AstiveServer server = this;

                TelnetServer ts = new TelnetServer(telnedPort, telnedBacklog, telnedBindAddr) {

                    @Override
                    public void stop() {
                        try {
                            server.stop();
                        } catch (SystemException ex) {
                            logger.error(AppLocale.getI18n("unexpectedError", new String[] { ex.getMessage() }));
                        }
                    }

                    @Override
                    public List<String> lookup() {
                        List<String> apps = new ArrayList();
                        AstDB astDB = MyAstDB.getInstance();

                        try {
                            for (AstObj astObj : astDB.getApps()) {
                                StringBuilder sb = new StringBuilder("@App(name=");
                                sb.append(astObj.getInfo().getName());
                                sb.append(" ");
                                sb.append("deploymentId=");
                                sb.append(astObj.getDeploymentId());
                                apps.add(sb.toString());
                            }
                        } catch (AstiveException ex) {
                            logger.error(AppLocale.getI18n("unexpectedError", new String[] { ex.getMessage() }));
                        }

                        return apps;
                    }

                    @Override
                    public String version() {
                        return server.getVersion();
                    }

                    @Override
                    public String system() {
                        throw new UnsupportedOperationException("Not supported yet.");
                    }
                };
                executorService.execute(ts);
            }
        } catch (IOException ex) {
            logger.warn(AppLocale.getI18n("unexpectedError", new Object[] { ex.getMessage() }));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stop() throws SystemException {
        executorService.shutdown();
        super.stop();
    }
    // </editor-fold>
}