//
//  ========================================================================
//  Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.runner;

import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ConnectorStatistics;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.ShutdownMonitor;
import org.eclipse.jetty.server.handler.ContextHandler;
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.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.StatisticsServlet;
import org.eclipse.jetty.util.RolloverFileOutputStream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;

/**
 * Runner
 * <p>
 * Combine jetty classes into a single executable jar and run webapps based on the args to it.
 */
public class Runner
{
    private static final Logger LOG = Log.getLogger(Runner.class);

    public static final String[] __plusConfigurationClasses = new String[] {
            org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.annotations.AnnotationConfiguration.class.getCanonicalName(),
            org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName()
            };
    public static final String __containerIncludeJarPattern =  ".*/jetty-runner-[^/]*\\.jar$";
    public static final String __defaultContextPath = "/";
    public static final int __defaultPort = 8080;

    protected Server _server;
    protected URLClassLoader _classLoader;
    protected Classpath _classpath = new Classpath();
    protected ContextHandlerCollection _contexts;
    protected RequestLogHandler _logHandler;
    protected String _logFile;
    protected ArrayList<String> _configFiles;
    protected boolean _enableStats=false;
    protected String _statsPropFile;



    /**
     * Classpath
     */
    public class Classpath
    {
        private  List<URL> _classpath = new ArrayList<>();

        public void addJars (Resource lib) throws IOException
        {
            if (lib == null || !lib.exists())
                throw new IllegalStateException ("No such lib: "+lib);

            String[] list = lib.list();
            if (list==null)
                return;

            for (String path : list)
            {
                if (".".equals(path) || "..".equals(path))
                    continue;

                try(Resource item = lib.addPath(path))
                {
                    if (item.isDirectory())
                        addJars(item);
                    else
                    {
                        if (path.toLowerCase().endsWith(".jar") ||
                            path.toLowerCase().endsWith(".zip"))
                        {
                            URL url = item.getURL();
                            _classpath.add(url);
                        }
                    }
                }
            }
        }


        public void addPath (Resource path)
        {
            if (path == null || !path.exists())
                throw new IllegalStateException ("No such path: "+path);
            _classpath.add(path.getURL());
        }


        public URL[] asArray ()
        {
            return _classpath.toArray(new URL[_classpath.size()]);
        }
    }

    public Runner()
    {
    }


    /**
     * Generate helpful usage message and exit
     *
     * @param error the error header
     */
    public void usage(String error)
    {
        if (error!=null)
            System.err.println("ERROR: "+error);
        System.err.println("Usage: java [-Djetty.home=dir] -jar jetty-runner.jar [--help|--version] [ server opts] [[ context opts] context ...] ");
        System.err.println("Server opts:");
        System.err.println(" --version                           - display version and exit");
        System.err.println(" --log file                          - request log filename (with optional 'yyyy_mm_dd' wildcard");
        System.err.println(" --out file                          - info/warn/debug log filename (with optional 'yyyy_mm_dd' wildcard");
        System.err.println(" --host name|ip                      - interface to listen on (default is all interfaces)");
        System.err.println(" --port n                            - port to listen on (default 8080)");
        System.err.println(" --stop-port n                       - port to listen for stop command");
        System.err.println(" --stop-key n                        - security string for stop command (required if --stop-port is present)");
        System.err.println(" [--jar file]*n                      - each tuple specifies an extra jar to be added to the classloader");
        System.err.println(" [--lib dir]*n                       - each tuple specifies an extra directory of jars to be added to the classloader");
        System.err.println(" [--classes dir]*n                   - each tuple specifies an extra directory of classes to be added to the classloader");
        System.err.println(" --stats [unsecure|realm.properties] - enable stats gathering servlet context");
        System.err.println(" [--config file]*n                   - each tuple specifies the name of a jetty xml config file to apply (in the order defined)");
        System.err.println("Context opts:");
        System.err.println(" [[--path /path] context]*n          - WAR file, web app dir or context xml file, optionally with a context path");
        System.exit(1);
    }


    /**
     * Generate version message and exit
     */
    public void version ()
    {
        System.err.println("org.eclipse.jetty.runner.Runner: "+Server.getVersion());
        System.exit(1);
    }



    /**
     * Configure a jetty instance and deploy the webapps presented as args
     *
     * @param args the command line arguments
     * @throws Exception if unable to configure
     */
    public void configure(String[] args) throws Exception
    {
        // handle classpath bits first so we can initialize the log mechanism.
        for (int i=0;i<args.length;i++)
        {
            if ("--lib".equals(args[i]))
            {
                try(Resource lib = Resource.newResource(args[++i]))
                {
                    if (!lib.exists() || !lib.isDirectory())
                        usage("No such lib directory "+lib);
                    _classpath.addJars(lib);
                }
            }
            else if ("--jar".equals(args[i]))
            {
                try(Resource jar = Resource.newResource(args[++i]))
                {
                    if (!jar.exists() || jar.isDirectory())
                        usage("No such jar "+jar);
                    _classpath.addPath(jar);
                }
            }
            else if ("--classes".equals(args[i]))
            {
                try(Resource classes = Resource.newResource(args[++i]))
                {
                    if (!classes.exists() || !classes.isDirectory())
                        usage("No such classes directory "+classes);
                    _classpath.addPath(classes);
                }
            }
            else if (args[i].startsWith("--"))
                i++;
        }

        initClassLoader();

        LOG.info("Runner");
        LOG.debug("Runner classpath {}",_classpath);

        String contextPath = __defaultContextPath;
        boolean contextPathSet = false;
        int port = __defaultPort;
        String host = null;
        int stopPort = 0;
        String stopKey = null;

        boolean runnerServerInitialized = false;

        for (int i=0;i<args.length;i++)
        {
            switch (args[i]) 
            {
                case "--port":
                    port = Integer.parseInt(args[++i]);
                    break;
                case "--host":
                    host = args[++i];
                    break;
                case "--stop-port":
                    stopPort = Integer.parseInt(args[++i]);
                    break;
                case "--stop-key":
                    stopKey = args[++i];
                    break;
                case "--log":
                    _logFile = args[++i];
                    break;
                case "--out":
                    String outFile = args[++i];
                    PrintStream out = new PrintStream(new RolloverFileOutputStream(outFile, true, -1));
                    LOG.info("Redirecting stderr/stdout to " + outFile);
                    System.setErr(out);
                    System.setOut(out);
                    break;
                case "--path":
                    contextPath = args[++i];
                    contextPathSet = true;
                    break;
                case "--config":
                    if (_configFiles == null)
                        _configFiles = new ArrayList<>();
                    _configFiles.add(args[++i]);
                    break;
                case "--lib":
                    ++i;//skip

                    break;
                case "--jar":
                    ++i; //skip

                    break;
                case "--classes":
                    ++i;//skip

                    break;
                case "--stats":
                    _enableStats = true;
                    _statsPropFile = args[++i];
                    _statsPropFile = ("unsecure".equalsIgnoreCase(_statsPropFile) ? null : _statsPropFile);
                    break;
                default:
// process contexts

                    if (!runnerServerInitialized) // log handlers not registered, server maybe not created, etc
                    {
                        if (_server == null) // server not initialized yet
                        {
                            // build the server
                            _server = new Server();
                        }

                        //apply jetty config files if there are any
                        if (_configFiles != null) 
                        {
                            for (String cfg : _configFiles) 
                            {
                                try (Resource resource = Resource.newResource(cfg)) {
                                    XmlConfiguration xmlConfiguration = new XmlConfiguration(resource.getURL());
                                    xmlConfiguration.configure(_server);
                                }
                            }
                        }

                        //check that everything got configured, and if not, make the handlers
                        HandlerCollection handlers = (HandlerCollection) _server.getChildHandlerByClass(HandlerCollection.class);
                        if (handlers == null) 
                        {
                            handlers = new HandlerCollection();
                            _server.setHandler(handlers);
                        }

                        //check if contexts already configured
                        _contexts = (ContextHandlerCollection) handlers.getChildHandlerByClass(ContextHandlerCollection.class);
                        if (_contexts == null) 
                        {
                            _contexts = new ContextHandlerCollection();
                            prependHandler(_contexts, handlers);
                        }


                        if (_enableStats) 
                        {
                            //if no stats handler already configured
                            if (handlers.getChildHandlerByClass(StatisticsHandler.class) == null) {
                                StatisticsHandler statsHandler = new StatisticsHandler();


                                Handler oldHandler = _server.getHandler();
                                statsHandler.setHandler(oldHandler);
                                _server.setHandler(statsHandler);


                                ServletContextHandler statsContext = new ServletContextHandler(_contexts, "/stats");
                                statsContext.addServlet(new ServletHolder(new StatisticsServlet()), "/");
                                statsContext.setSessionHandler(new SessionHandler());
                                if (_statsPropFile != null) 
                                {
                                    HashLoginService loginService = new HashLoginService("StatsRealm", _statsPropFile);
                                    Constraint constraint = new Constraint();
                                    constraint.setName("Admin Only");
                                    constraint.setRoles(new String[]{"admin"});
                                    constraint.setAuthenticate(true);

                                    ConstraintMapping cm = new ConstraintMapping();
                                    cm.setConstraint(constraint);
                                    cm.setPathSpec("/*");

                                    ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
                                    securityHandler.setLoginService(loginService);
                                    securityHandler.setConstraintMappings(Collections.singletonList(cm));
                                    securityHandler.setAuthenticator(new BasicAuthenticator());
                                    statsContext.setSecurityHandler(securityHandler);
                                }
                            }
                        }

                        //ensure a DefaultHandler is present
                        if (handlers.getChildHandlerByClass(DefaultHandler.class) == null) 
                        {
                            handlers.addHandler(new DefaultHandler());
                        }

                        //ensure a log handler is present
                        _logHandler = (RequestLogHandler) handlers.getChildHandlerByClass(RequestLogHandler.class);
                        if (_logHandler == null) 
                        {
                            _logHandler = new RequestLogHandler();
                            handlers.addHandler(_logHandler);
                        }


                        //check a connector is configured to listen on
                        Connector[] connectors = _server.getConnectors();
                        if (connectors == null || connectors.length == 0) 
                        {
                            ServerConnector connector = new ServerConnector(_server);
                            connector.setPort(port);
                            if (host != null)
                                connector.setHost(host);
                            _server.addConnector(connector);
                            if (_enableStats)
                                connector.addBean(new ConnectorStatistics());
                        } 
                        else 
                        {
                            if (_enableStats) 
                            {
                                for (Connector connector : connectors) 
                                {
                                    ((AbstractConnector) connector).addBean(new ConnectorStatistics());
                                }
                            }
                        }

                        runnerServerInitialized = true;
                    }

                    // Create a context
                    try (Resource ctx = Resource.newResource(args[i])) 
                    {
                        if (!ctx.exists())
                            usage("Context '" + ctx + "' does not exist");

                        if (contextPathSet && !(contextPath.startsWith("/")))
                            contextPath = "/" + contextPath;

                        // Configure the context
                        if (!ctx.isDirectory() && ctx.toString().toLowerCase().endsWith(".xml")) 
                        {
                            // It is a context config file
                            XmlConfiguration xmlConfiguration = new XmlConfiguration(ctx.getURL());
                            xmlConfiguration.getIdMap().put("Server", _server);
                            ContextHandler handler = (ContextHandler) xmlConfiguration.configure();
                            if (contextPathSet)
                                handler.setContextPath(contextPath);
                            _contexts.addHandler(handler);
                            handler.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", __containerIncludeJarPattern);
                        }
                        else 
                        {
                            // assume it is a WAR file
                            WebAppContext webapp = new WebAppContext(_contexts, ctx.toString(), contextPath);
                            webapp.setConfigurationClasses(__plusConfigurationClasses);
                            webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                                    __containerIncludeJarPattern);
                        }
                    }
                    //reset
                    contextPathSet = false;
                    contextPath = __defaultContextPath;
                    break;
            }
        }

        if (_server==null)
            usage("No Contexts defined");
        _server.setStopAtShutdown(true);

        switch ((stopPort > 0 ? 1 : 0) + (stopKey != null ? 2 : 0))
        {
            case 1:
                usage("Must specify --stop-key when --stop-port is specified");
                break;

            case 2:
                usage("Must specify --stop-port when --stop-key is specified");
                break;

            case 3:
                ShutdownMonitor monitor = ShutdownMonitor.getInstance();
                monitor.setPort(stopPort);
                monitor.setKey(stopKey);
                monitor.setExitVm(true);
                break;
        }

        if (_logFile!=null)
        {
            NCSARequestLog requestLog = new NCSARequestLog(_logFile);
            requestLog.setExtended(false);
            _logHandler.setRequestLog(requestLog);
        }
    }


    protected void prependHandler (Handler handler, HandlerCollection handlers)
    {
        if (handler == null || handlers == null)
            return;

       Handler[] existing = handlers.getChildHandlers();
       Handler[] children = new Handler[existing.length + 1];
       children[0] = handler;
       System.arraycopy(existing, 0, children, 1, existing.length);
       handlers.setHandlers(children);
    }




    public void run() throws Exception
    {
        _server.start();
        _server.join();
    }


    /**
     * Establish a classloader with custom paths (if any)
     */
    protected void initClassLoader()
    {
        URL[] paths = _classpath.asArray();

        if (_classLoader==null && paths !=null && paths.length > 0)
        {
            ClassLoader context=Thread.currentThread().getContextClassLoader();

            if (context==null)
                _classLoader=new URLClassLoader(paths);
            else
                _classLoader=new URLClassLoader(paths, context);

            Thread.currentThread().setContextClassLoader(_classLoader);
        }
    }




    public static void main(String[] args)
    {
        Runner runner = new Runner();

        try
        {
            if (args.length>0&&args[0].equalsIgnoreCase("--help"))
            {
                runner.usage(null);
            }
            else if (args.length>0&&args[0].equalsIgnoreCase("--version"))
            {
                runner.version();
            }
            else
            {
                runner.configure(args);
                runner.run();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            runner.usage(null);
        }
    }
}
