Package com.enioka.jqm.tools

Source Code of com.enioka.jqm.tools.JettyServer

package com.enioka.jqm.tools;

import java.io.File;
import java.net.BindException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.TagLibConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;

import com.enioka.jqm.jpamodel.Node;

/**
* Every engine has an embedded Jetty engine that serves the servlet API ({@link ServletFile}, {@link ServletStatus}, {@link ServletEnqueue}
* ). It may also serve the REST API.
*/
class JettyServer
{
    private static Logger jqmlogger = Logger.getLogger(JettyServer.class);

    private Server server = null;
    private HandlerCollection h = new HandlerCollection();

    void start(Node node)
    {
        server = new Server();

        // Connectors.
        List<Connector> ls = new ArrayList<Connector>();
        try
        {
            InetAddress[] adresses = InetAddress.getAllByName(node.getDns());
            for (InetAddress s : adresses)
            {
                if (s instanceof Inet4Address)
                {
                    Connector connector = new SelectChannelConnector();
                    connector.setHost(s.getHostAddress());
                    connector.setPort(node.getPort());
                    ls.add(connector);
                    jqmlogger.debug("Jetty will bind on " + s.getHostAddress() + ":" + node.getPort());
                }
            }
        }
        catch (UnknownHostException e1)
        {
            jqmlogger.warn("Could not resolve name " + node.getDns() + ". Will bind on all interfaces.");
            Connector connector = new SelectChannelConnector();
            connector.setHost(null);
            connector.setPort(node.getPort());
            ls.add(connector);
        }
        server.setConnectors(ls.toArray(new Connector[ls.size()]));

        // Collection handler
        server.setHandler(h);

        // Servlets (basic script API + files)
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");

        context.addServlet(new ServletHolder(new ServletFile()), "/getfile");
        context.addServlet(new ServletHolder(new ServletEnqueue()), "/enqueue");
        context.addServlet(new ServletHolder(new ServletStatus()), "/status");
        context.addServlet(new ServletHolder(new ServletLog()), "/log");

        h.addHandler(context);

        // Potentially add a webapp context
        loadWar();

        // Start the server
        jqmlogger.trace("Starting Jetty (port " + node.getPort() + ")");
        try
        {
            server.start();
        }
        catch (BindException e)
        {
            // JETTY-839: threadpool not daemon nor close on exception. Explicit closing required as workaround.
            this.stop();
            throw new JqmInitError("Could not start web server - check there is no other process binding on this port & interface", e);
        }
        catch (Exception e)
        {
            throw new JqmInitError("Could not start web server - not a port issue, but a generic one", e);
        }
        jqmlogger.info("Jetty has started on port " + getActualPort());
    }

    int getActualPort()
    {
        return server.getConnectors()[0].getLocalPort();
    }

    void stop()
    {
        jqmlogger.trace("Jetty will now stop");
        try
        {
            this.server.stop();
            this.server.join();
            jqmlogger.info("Jetty has stopped");
        }
        catch (Exception e)
        {
            // Who cares, we are dying.
        }
    }

    private void loadWar()
    {
        File war = new File("./webapp/jqm-ws.war");
        if (!war.exists() || !war.isFile())
        {
            return;
        }
        jqmlogger.info("Jetty will now load the web service application war");

        // Load web application.
        WebAppContext webAppContext = new WebAppContext(war.getPath(), "/api");
        webAppContext.setDisplayName("JqmWebServices");

        // Hide server classes from the web app
        final int nbEx = 4;
        String[] defExcl = webAppContext.getDefaultServerClasses();
        String[] exclusions = new String[defExcl.length + nbEx];
        for (int i = nbEx; i <= defExcl.length; i++)
        {
            exclusions[i] = defExcl[i - nbEx];
        }
        exclusions[0] = "com.enioka.";
        exclusions[1] = "org.slf4j.";
        exclusions[2] = "org.apache.log4j.";
        exclusions[3] = "org.glassfish."; // Jersey
        webAppContext.setServerClasses(exclusions);

        // JQM configuration should be on the class path
        webAppContext.setExtraClasspath("conf/jqm.properties");

        // Set configurations (order is important: need to unpack war before reading web.xml)
        webAppContext.setConfigurations(new Configuration[] { new WebInfConfiguration(), new WebXmlConfiguration(),
                new MetaInfConfiguration(), new FragmentConfiguration(), new AnnotationConfiguration(), new TagLibConfiguration() });

        h.addHandler(webAppContext);
    }
}
TOP

Related Classes of com.enioka.jqm.tools.JettyServer

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.