Package com.tinkerpop.rexster

Source Code of com.tinkerpop.rexster.Application

package com.tinkerpop.rexster;

import com.tinkerpop.rexster.protocol.EngineConfiguration;
import com.tinkerpop.rexster.protocol.EngineController;
import com.tinkerpop.rexster.server.HttpRexsterServer;
import com.tinkerpop.rexster.server.RexProRexsterServer;
import com.tinkerpop.rexster.server.RexsterApplication;
import com.tinkerpop.rexster.server.RexsterCommandLine;
import com.tinkerpop.rexster.server.RexsterProperties;
import com.tinkerpop.rexster.server.RexsterServer;
import com.tinkerpop.rexster.server.RexsterSettings;
import com.tinkerpop.rexster.server.ShutdownManager;
import com.tinkerpop.rexster.server.XmlRexsterApplication;
import com.tinkerpop.rexster.server.metrics.ReporterConfig;
import com.tinkerpop.rexster.util.JuliToLog4jHandler;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.BindException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;

/**
* Main class for initializing, starting and stopping Rexster.
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public class Application {

    private static final Logger logger = Logger.getLogger(Application.class);

    static {
        // try to load a log4j properties file in the root of REXSTER_HOME
        final File logConfigFile = new File("log4j.properties");
        URL logConfigFileUrl;
        try {
            if (logConfigFile.exists()) {
                // this one exists in the root of REXSTER_HOME
                logConfigFileUrl = logConfigFile.toURI().toURL();
            } else {
                // a custom one from a user doesn't exist so use the default one in the jar
                logConfigFileUrl = Application.class.getResource("log4j.properties");
            }
        } catch (MalformedURLException mue) {
            // revert to the properties file in the jar
            logConfigFileUrl = Application.class.getResource("log4j.properties");
        }

        PropertyConfigurator.configure(logConfigFileUrl);
    }

    private final RexsterServer httpServer;
    private final RexsterServer rexproServer;
    private final RexsterApplication rexsterApplication;
    private final RexsterProperties properties;
    private final ReporterConfig reporterConfig;

    /**
     * Check for configuration file changes.
     */
    private final FileAlterationMonitor configurationMonitor;

    public Application(final RexsterProperties properties,
                       final FileAlterationObserver rexsterConfigurationObserver) throws Exception {

        // watch rexster.xml for changes
        rexsterConfigurationObserver.addListener(properties);
        this.configurationMonitor = new FileAlterationMonitor(properties.getConfigCheckInterval());
        configurationMonitor.addObserver(rexsterConfigurationObserver);

        // get the graph configurations from the XML config file
        this.properties = properties;
        this.rexsterApplication = new XmlRexsterApplication(this.properties);

        this.reporterConfig = new ReporterConfig(properties, this.rexsterApplication.getMetricRegistry());
        this.httpServer = new HttpRexsterServer(properties);
        this.rexproServer = new RexProRexsterServer(properties, true);
    }

    public void start() throws Exception {
        configureScriptEngine();
        properties.addListener(new RexsterProperties.RexsterPropertiesListener() {
            @Override
            public void propertiesChanged(final XMLConfiguration configuration) {
                configureScriptEngine();
            }
        });

        this.httpServer.start(this.rexsterApplication);
        this.rexproServer.start(this.rexsterApplication);
        this.configurationMonitor.start();

        startShutdownManager(this.properties);
    }

    private void configureScriptEngine() {
        // the EngineController needs to be configured statically before requests start serving so that it can
        // properly construct ScriptEngine objects with the correct reset policy. allow scriptengines to be
        // configured so that folks can drop in different gremlin flavors.
        final List<EngineConfiguration> configuredScriptEngines = new ArrayList<EngineConfiguration>();
        final List<HierarchicalConfiguration> configs = this.properties.getScriptEngines();
        for(HierarchicalConfiguration config : configs) {
            configuredScriptEngines.add(new EngineConfiguration(config));
        }

        EngineController.configure(configuredScriptEngines);
    }

    public void stop() {

        try {
            this.configurationMonitor.stop();
        } catch (Exception ex) {
            logger.debug("Error shutting down the configuration monitor");
        }

        try {
            this.httpServer.stop();
        } catch (Exception ex) {
            logger.debug("Error shutting down Rexster Server ignored.", ex);
        }

        try {
            this.rexproServer.stop();
        } catch (Exception ex) {
            logger.debug("Error shutting down RexPro Server ignored.", ex);
        }

        try {
            this.rexsterApplication.stop();
        } catch (Exception ex) {
            logger.warn("Error while shutting down graphs.  All graphs may not have been shutdown cleanly.");
        }
    }

    private void startShutdownManager(final RexsterProperties properties) throws Exception {
        final ShutdownManager shutdownManager = new ShutdownManager(properties);

        //Register a shutdown hook
        shutdownManager.registerShutdownListener(new ShutdownManager.ShutdownListener() {
            public void shutdown() {
            // shutdown grizzly/graphs
            stop();
            }
        });

        //Start the shutdown listener
        shutdownManager.start();

        //Wait for a shutdown request and all shutdown listeners to complete
        shutdownManager.waitForShutdown();
    }

    public static void main(final String[] args)  {

        logger.info(".:Welcome to Rexster:.");

        // properties from XML can be overriden by entries issued from the command line
        final RexsterSettings settings = new RexsterSettings(args);
        initializeDebugLogging(settings);
        final RexsterCommandLine line = settings.getCommand();

        if (settings.getPrimeCommand().equals(RexsterSettings.COMMAND_START)) {
            try {
                new Application(settings.getProperties(), createRexsterConfigurationObserver(settings)).start();
            } catch (BindException be) {
                logger.fatal("Could not start Rexster Server.  A port that Rexster needs is in use.");
            } catch (Exception ex) {
                logger.fatal("The Rexster Server could not be started", ex);
            }
        } else if (settings.getPrimeCommand().equals(RexsterSettings.COMMAND_VERSION)) {
            logger.info(String.format("Rexster version [%s]", Tokens.REXSTER_VERSION));
        } else if (settings.getPrimeCommand().equals(RexsterSettings.COMMAND_STOP)) {
            if (line.hasCommandParameters() && line.getCommandParameters().hasOption("wait")) {
                issueControlCommand(line, ShutdownManager.COMMAND_SHUTDOWN_WAIT);
            } else {
                issueControlCommand(line, ShutdownManager.COMMAND_SHUTDOWN_NO_WAIT);
            }
        } else if (settings.getPrimeCommand().equals(RexsterSettings.COMMAND_STATUS)) {
            issueControlCommand(line, ShutdownManager.COMMAND_STATUS);
        } else {
            settings.printHelp();
        }
    }

    /**
     * Initialize debug level logging for rexster if the setting is turned on from the command line.
     */
    private static void initializeDebugLogging(final RexsterSettings settings) {
        if (settings.isDebug()) {
            // turn on all logging for jersey -- this is debug mode
            for (String l : Collections.list(LogManager.getLogManager().getLoggerNames())) {
                java.util.logging.Logger logger = java.util.logging.Logger.getLogger(l);
                logger.setLevel(Level.ALL);

                // remove old handlers
                for (Handler handler : logger.getHandlers()) {
                    logger.removeHandler(handler);
                }

                // route all logging from java.util.Logging to log4net
                final Handler handler = new JuliToLog4jHandler();
                handler.setLevel(Level.ALL);
                java.util.logging.Logger.getLogger(l).addHandler(handler);
            }
        } else {
            // turn off all logging for jersey
            for (String l : Collections.list(LogManager.getLogManager().getLoggerNames())) {
                java.util.logging.Logger.getLogger(l).setLevel(Level.OFF);
            }
        }
    }

    /**
     * Construct an observer for watching the rexster configuration file.
     */
    private static FileAlterationObserver createRexsterConfigurationObserver(final RexsterSettings settings) {
        final File rexsterConfigurationFile = settings.getRexsterXmlFile();
        final File absolute = new File(rexsterConfigurationFile.getAbsolutePath());
        final File rexsterConfigurationDirectory = absolute.getParentFile();

        logger.info(String.format("Rexster is watching [%s] for change.", rexsterConfigurationFile.getAbsolutePath()));

        // follow the rexster configuration file directory and only the rexster.xml equivalent within that directory.
        return new FileAlterationObserver(rexsterConfigurationDirectory,
                FileFilterUtils.and(FileFileFilter.FILE, FileFilterUtils.nameFileFilter(rexsterConfigurationFile.getName())));
    }

    private static int parseInt(final String intString, final int intDefault) {
        try {
            return Integer.parseInt(intString);
        } catch (NumberFormatException nfe) {
            return intDefault;
        }
    }

    private static void issueControlCommand(final RexsterCommandLine line, final String command) {

        final String host = line.getCommandOption("rexsterhost", RexsterSettings.DEFAULT_HOST);
        final String portString = line.getCommandOption("rexsterport", null);

        final int port = parseInt(portString, RexsterSettings.DEFAULT_SHUTDOWN_PORT);
        if (line.hasCommandOption("rexsterport") && !Integer.toString(port).equals(portString)) {
            logger.warn("The value of the <port> parameter was not a valid value.  Utilizing the default port of " + port + ".");
        }

        Socket shutdownConnection = null;
        try {
            final InetAddress hostAddress = InetAddress.getByName(host);
            shutdownConnection = new Socket(hostAddress, port);

            shutdownConnection.setSoTimeout(30000);
            final BufferedReader reader = new BufferedReader(new InputStreamReader(shutdownConnection.getInputStream()));
            final PrintStream writer = new PrintStream(shutdownConnection.getOutputStream());
            try {
                writer.println(command);
                writer.flush();

                while (true) {
                    final String theLine = reader.readLine();
                    if (theLine == null) {
                        break;
                    }

                    System.out.println(theLine);
                }

            } finally {
                IOUtils.closeQuietly(reader);
                IOUtils.closeQuietly(writer);
            }
        } catch (SocketTimeoutException ste) {
            // perhaps the -wait option should take an argument for how long to wait for...for now 30 seconds seems
            // long enough.
            logger.warn("Taking longer than 30 seconds to shutdown Rexster.  Check shutdown status with --status");
        } catch (IOException ioe) {
            // SocketException or ConnectionException would be more exacting here, but don't think much can be done
            // with an IOException ... will keep it generic for now.
            logger.warn("Cannot connect to Rexster Server to issue command.  It may not be running.");
        } finally {
            try {
                if (shutdownConnection != null) {
                    shutdownConnection.close();
                }
            } catch (IOException ioe) {
            }
        }
    }
}
TOP

Related Classes of com.tinkerpop.rexster.Application

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.