org.b5chat.crossfire.plugin.admin.AdminConsolePlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.b5chat.crossfire.plugin.admin.AdminConsolePlugin.java

Source

/**
 * $Revision: 3034 $
 * $Date: 2005-11-04 21:02:33 -0300 (Fri, 04 Nov 2005) $
 *
 * Copyright (C) 2004-2008 B5Chat Community. All rights reserved.
 *
 * Licensed 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.b5chat.crossfire.plugin.admin;

import java.io.File;

import org.b5chat.crossfire.core.plugin.IPlugin;
import org.b5chat.crossfire.core.plugin.PluginManager;
import org.b5chat.crossfire.core.property.Globals;
import org.b5chat.crossfire.core.util.LocaleUtils;
import org.b5chat.crossfire.core.util.StringUtils;
import org.b5chat.crossfire.xmpp.server.XmppServer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The admin console plugin. It starts a Jetty instance on the configured
 * port and loads the admin console web application.
 *
 * @author Matt Tucker
 */
public class AdminConsolePlugin implements IPlugin {

    private static final Logger Log = LoggerFactory.getLogger(AdminConsolePlugin.class);

    /**
     * Random secret used by JVM to allow SSO. Only other cluster nodes can use this secret
     * as a way to integrate the admin consoles of each cluster node.
     */
    public final static String secret = StringUtils.randomString(64);

    private int adminPort;
    private Server adminServer;
    private ContextHandlerCollection contexts;
    private boolean restartNeeded = false;

    private File pluginDir;

    /**
     * Create a Jetty module.
     */
    public AdminConsolePlugin() {
        contexts = new ContextHandlerCollection();

        // JSP 2.0 uses commons-logging, so also override that implementation.
        System.setProperty("org.apache.commons.logging.LogFactory",
                "org.b5chat.crossfire.core.util.log.util.CommonsLogFactory");
    }

    public void setRestartNeeded(boolean value) {
        restartNeeded = value;
    }

    /**
     * Starts the Jetty instance.
     */
    public void startup() {
        restartNeeded = false;

        adminPort = Globals.getXMLProperty("adminConsole.port", 9090);
        adminServer = new Server();
        final QueuedThreadPool tp = new QueuedThreadPool(254);
        tp.setName("Jetty-QTP-AdminConsole");
        adminServer.setThreadPool(tp);

        // Do not send Jetty info in HTTP headers
        adminServer.setSendServerVersion(false);

        // Create connector for http traffic if it's enabled.
        if (adminPort > 0) {
            Connector httpConnector = new SelectChannelConnector();
            // Listen on a specific network interface if it has been set.
            String bindInterface = getBindInterface();
            httpConnector.setHost(bindInterface);
            httpConnector.setPort(adminPort);
            adminServer.addConnector(httpConnector);
        }

        // Make sure that at least one connector was registered.
        if (adminServer.getConnectors() == null || adminServer.getConnectors().length == 0) {
            adminServer = null;
            // Log warning.
            log(LocaleUtils.getLocalizedString("admin.console.warning"));
            return;
        }

        HandlerCollection collection = new HandlerCollection();
        adminServer.setHandler(collection);
        collection.setHandlers(new Handler[] { contexts, new DefaultHandler() });

        try {
            adminServer.start();
        } catch (Exception e) {
            Log.error("Could not start admin conosle server", e);
        }

        // Log the ports that the admin server is listening on.
        logAdminConsolePorts();
    }

    /**
     * Shuts down the Jetty server.
     * */
    public void shutdown() {
        //noinspection ConstantConditions
        try {
            if (adminServer != null && adminServer.isRunning()) {
                adminServer.stop();
            }
        } catch (Exception e) {
            Log.error("Error stopping admin console server", e);
        }
        adminServer = null;
    }

    public void initializePlugin(PluginManager manager, File pluginDir) {
        this.pluginDir = pluginDir;

        createWebAppContext();

        startup();
    }

    public void destroyPlugin() {
        shutdown();
    }

    /**
     * Returns true if the Jetty server needs to be restarted. This is usually required when
     * certificates are added, deleted or modified or when server ports were modified.
     *
     * @return true if the Jetty server needs to be restarted.
     */
    public boolean isRestartNeeded() {
        return restartNeeded;
    }

    /**
     * Returns <tt>null</tt> if the admin console will be available in all network interfaces of this machine
     * or a String representing the only interface where the admin console will be available.
     *
     * @return String representing the only interface where the admin console will be available or null if it
     * will be available in all interfaces.
     */
    public String getBindInterface() {
        String adminInterfaceName = Globals.getXMLProperty("adminConsole.interface");
        String globalInterfaceName = Globals.getXMLProperty("network.interface");
        String bindInterface = null;
        if (adminInterfaceName != null && adminInterfaceName.trim().length() > 0) {
            bindInterface = adminInterfaceName;
        } else if (globalInterfaceName != null && globalInterfaceName.trim().length() > 0) {
            bindInterface = globalInterfaceName;
        }
        return bindInterface;
    }

    /**
     * Returns the non-SSL port on which the admin console is currently operating.
     *
     * @return the non-SSL port on which the admin console is currently operating.
     */
    public int getAdminUnsecurePort() {
        return adminPort;
    }

    /**
     * Returns the collection of Jetty contexts used in the admin console. A root context "/"
     * is where the admin console lives. Additional contexts can be added dynamically for
     * other web applications that should be run as part of the admin console server
     * process. The following pseudo code demonstrates how to do this:
     *
     * <pre>
     *   ContextHandlerCollection contexts = ((AdminConsolePlugin)pluginManager.getPlugin("admin")).getContexts();
     *   context = new WebAppContext(SOME_DIRECTORY, "/CONTEXT_NAME");
     *   contexts.addHandler(context);
     *   context.setWelcomeFiles(new String[]{"index.jsp"});
     *   context.start();
     * </pre>
     *
     * @return the Jetty handlers.
     */
    public ContextHandlerCollection getContexts() {
        return contexts;
    }

    public void restart() {
        try {
            adminServer.stop();
            adminServer.start();
        } catch (Exception e) {
            Log.error(e.getMessage(), e);
        }
    }

    private void createWebAppContext() {
        ServletContextHandler context;
        // Add web-app. Check to see if we're in development mode. If so, we don't
        // add the normal web-app location, but the web-app in the project directory.
        if (Boolean.getBoolean("developmentMode")) {
            System.out.println(LocaleUtils.getLocalizedString("admin.console.devmode"));
            context = new WebAppContext(contexts,
                    pluginDir.getParentFile().getParentFile().getParentFile().getParent() + File.separator + "src"
                            + File.separator + "web",
                    "/");
        } else {
            context = new WebAppContext(contexts, pluginDir.getAbsoluteFile() + File.separator + "webapp", "/");
        }
        context.setWelcomeFiles(new String[] { "index.jsp" });
    }

    private void log(String string) {
        Log.info(string);
        System.out.println(string);
    }

    private void logAdminConsolePorts() {
        // Log what ports the admin console is running on.
        String listening = LocaleUtils.getLocalizedString("admin.console.listening");
        String hostname = getBindInterface() == null ? XmppServer.getInstance().getServerInfo().getXMPPDomain()
                : getBindInterface();

        log(listening + " http://" + hostname + ":" + adminPort);
    }
}