<commit_before>package io.bootique.jetty.server;

import io.bootique.jetty.JettyModule;
import io.bootique.jetty.MappedFilter;
import io.bootique.jetty.MappedServlet;
import io.bootique.jetty.connector.HttpConnectorFactory;
import io.bootique.resource.FolderResourceFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Slf4jRequestLog;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventListener;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;

public class ServerFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerFactory.class);

    @Deprecated
    protected HttpConnectorFactory connector;
    protected List<HttpConnectorFactory> connectors;
    protected String context;
    protected int idleThreadTimeout;
    protected Map<String, FilterFactory> filters;
    protected int maxThreads;
    protected int minThreads;
    protected int maxQueuedRequests;
    protected Map<String, ServletFactory> servlets;
    protected boolean sessions;
    private Map<String, String> params;
    private FolderResourceFactory staticResourceBase;
    private boolean compression;

    public ServerFactory() {
        this.context = "/";
        this.minThreads = 4;
        this.maxThreads = 1024;
        this.maxQueuedRequests = 1024;
        this.idleThreadTimeout = 60000;
        this.sessions = true;
        this.compression = true;
    }

    public Server createServer(Set<MappedServlet> servlets, Set<MappedFilter> filters, Set<EventListener> listeners) {

        ThreadPool threadPool = createThreadPool();
        Server server = new Server(threadPool);
        server.setStopAtShutdown(true);
        server.setStopTimeout(1000L);
        server.setHandler(createHandler(servlets, filters, listeners));

        createRequestLog(server);

        Collection<HttpConnectorFactory> connectorFactories = connectorFactories(server);

        Collection<Integer> ports = new LinkedHashSet<>();

        if (connectorFactories.isEmpty()) {
            LOGGER.warn("Jetty starts with no connectors configured. Is that expected?");
        } else {
            connectorFactories.forEach(cf -> {
                server.addConnector(cf.createConnector(server));
                ports.add(cf.getPort());
            });
        }

        server.addLifeCycleListener(new ServerLifecycleLogger(ports, context));
        return server;
    }

    protected Handler createHandler(Set<MappedServlet> servlets, Set<MappedFilter> filters,
                                    Set<EventListener> listeners) {

        int options = 0;

        if (sessions) {
            options |= ServletContextHandler.SESSIONS;
        }

        ServletContextHandler handler = new ServletContextHandler(options);
        handler.setContextPath(context);
        if (params != null) {
            params.forEach((k, v) -> handler.setInitParameter(k, v));
        }

        if (staticResourceBase != null) {
            handler.setResourceBase(staticResourceBase.getUrl().toExternalForm());
        }

        if (compression) {
            handler.setGzipHandler(createGzipHandler());
        }

        installListeners(handler, listeners);
        installServlets(handler, servlets);
        installFilters(handler, filters);

        return handler;
    }

    protected GzipHandler createGzipHandler() {
        GzipHandler gzipHandler = new GzipHandler();
        gzipHandler.setCheckGzExists(false);
        return gzipHandler;
    }

    protected void installServlets(ServletContextHandler handler, Set<MappedServlet> servlets) {
        servlets.forEach(mappedServlet -> getServletFactory(mappedServlet.getName()).createAndAddJettyServlet(handler,
                mappedServlet));
    }

    protected ServletFactory getServletFactory(String name) {
        ServletFactory factory = null;
        if (servlets != null && name != null) {
            factory = servlets.get(name);
        }

        return factory != null ? factory : new ServletFactory();
    }

    protected void installFilters(ServletContextHandler handler, Set<MappedFilter> filters) {
        sortedFilters(filters).forEach(mappedFilter -> getFilterFactory(mappedFilter.getName())
                .createAndAddJettyFilter(handler, mappedFilter));
    }

    protected FilterFactory getFilterFactory(String name) {
        FilterFactory factory = null;
        if (filters != null && name != null) {
            factory = filters.get(name);
        }

        return factory != null ? factory : new FilterFactory();
    }

    protected void installListeners(ServletContextHandler handler, Set<EventListener> listeners) {
        listeners.forEach(listener -> {

            LOGGER.info("Adding listener {}", listener.getClass().getName());
            handler.addEventListener(listener);
        });
    }

    private List<MappedFilter> sortedFilters(Set<MappedFilter> unsorted) {
        List<MappedFilter> sorted = new ArrayList<>(unsorted);

        Collections.sort(sorted, Comparator.comparing(MappedFilter::getOrder));
        return sorted;
    }

    protected Collection<HttpConnectorFactory> connectorFactories(Server server) {
        Collection<HttpConnectorFactory> connectorFactories = new ArrayList<>();

        if (this.connector != null) {
            LOGGER.warn("Using deprecated 'connector' property. Consider changing configuration to 'connectors'");
            connectorFactories.add(this.connector);
        }

        if (this.connectors != null) {
            connectorFactories.addAll(this.connectors);
        }

        return connectorFactories;
    }

    protected QueuedThreadPool createThreadPool() {
        BlockingQueue<Runnable> queue = new BlockingArrayQueue<>(minThreads, maxThreads, maxQueuedRequests);
        QueuedThreadPool threadPool = createThreadPool(queue);
        threadPool.setName("bootique-http");

        return threadPool;
    }

    protected QueuedThreadPool createThreadPool(BlockingQueue<Runnable> queue) {
        return new QueuedThreadPool(maxThreads, minThreads, idleThreadTimeout, queue);<commit_msg>Support for multiple connectors #45<commit_after>package io.bootique.jetty.server;

import io.bootique.jetty.JettyModule;
import io.bootique.jetty.MappedFilter;
import io.bootique.jetty.MappedServlet;
import io.bootique.jetty.connector.HttpConnectorFactory;
import io.bootique.resource.FolderResourceFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.Slf4jRequestLog;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventListener;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;

public class ServerFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerFactory.class);

    @Deprecated
    protected HttpConnectorFactory connector;
    protected List<HttpConnectorFactory> connectors;
    protected String context;
    protected int idleThreadTimeout;
    protected Map<String, FilterFactory> filters;
    protected int maxThreads;
    protected int minThreads;
    protected int maxQueuedRequests;
    protected Map<String, ServletFactory> servlets;
    protected boolean sessions;
    private Map<String, String> params;
    private FolderResourceFactory staticResourceBase;
    private boolean compression;

    public ServerFactory() {
        this.context = "/";
        this.minThreads = 4;
        this.maxThreads = 1024;
        this.maxQueuedRequests = 1024;
        this.idleThreadTimeout = 60000;
        this.sessions = true;
        this.compression = true;
    }

    public Server createServer(Set<MappedServlet> servlets, Set<MappedFilter> filters, Set<EventListener> listeners) {

        ThreadPool threadPool = createThreadPool();
        Server server = new Server(threadPool);
        server.setStopAtShutdown(true);
        server.setStopTimeout(1000L);
        server.setHandler(createHandler(servlets, filters, listeners));

        createRequestLog(server);

        Collection<HttpConnectorFactory> connectorFactories = connectorFactories(server);

        Collection<Integer> ports = new LinkedHashSet<>();

        if (connectorFactories.isEmpty()) {
            LOGGER.warn("Jetty starts with no connectors configured. Is that expected?");
        } else {
            connectorFactories.forEach(cf -> {
                server.addConnector(cf.createConnector(server));
                ports.add(cf.getPort());
            });
        }

        server.addLifeCycleListener(new ServerLifecycleLogger(ports, context));
        return server;
    }

    protected Handler createHandler(Set<MappedServlet> servlets, Set<MappedFilter> filters,
                                    Set<EventListener> listeners) {

        int options = 0;

        if (sessions) {
            options |= ServletContextHandler.SESSIONS;
        }

        ServletContextHandler handler = new ServletContextHandler(options);
        handler.setContextPath(context);
        if (params != null) {
            params.forEach((k, v) -> handler.setInitParameter(k, v));
        }

        if (staticResourceBase != null) {
            handler.setResourceBase(staticResourceBase.getUrl().toExternalForm());
        }

        if (compression) {
            handler.setGzipHandler(createGzipHandler());
        }

        installListeners(handler, listeners);
        installServlets(handler, servlets);
        installFilters(handler, filters);

        return handler;
    }

    protected GzipHandler createGzipHandler() {
        GzipHandler gzipHandler = new GzipHandler();
        gzipHandler.setCheckGzExists(false);
        return gzipHandler;
    }

    protected void installServlets(ServletContextHandler handler, Set<MappedServlet> servlets) {
        servlets.forEach(mappedServlet -> getServletFactory(mappedServlet.getName()).createAndAddJettyServlet(handler,
                mappedServlet));
    }

    protected ServletFactory getServletFactory(String name) {
        ServletFactory factory = null;
        if (servlets != null && name != null) {
            factory = servlets.get(name);
        }

        return factory != null ? factory : new ServletFactory();
    }

    protected void installFilters(ServletContextHandler handler, Set<MappedFilter> filters) {
        sortedFilters(filters).forEach(mappedFilter -> getFilterFactory(mappedFilter.getName())
                .createAndAddJettyFilter(handler, mappedFilter));
    }

    protected FilterFactory getFilterFactory(String name) {
        FilterFactory factory = null;
        if (filters != null && name != null) {
            factory = filters.get(name);
        }

        return factory != null ? factory : new FilterFactory();
    }

    protected void installListeners(ServletContextHandler handler, Set<EventListener> listeners) {
        listeners.forEach(listener -> {

            LOGGER.info("Adding listener {}", listener.getClass().getName());
            handler.addEventListener(listener);
        });
    }

    private List<MappedFilter> sortedFilters(Set<MappedFilter> unsorted) {
        List<MappedFilter> sorted = new ArrayList<>(unsorted);

        Collections.sort(sorted, Comparator.comparing(MappedFilter::getOrder));
        return sorted;
    }

    protected Collection<HttpConnectorFactory> connectorFactories(Server server) {
        Collection<HttpConnectorFactory> connectorFactories = new ArrayList<>();

        if (this.connector != null) {
            LOGGER.warn("Using deprecated 'connector' property. Consider changing configuration to 'connectors'");
            connectorFactories.add(this.connector);
        }

        if (this.connectors != null) {
            connectorFactories.addAll(this.connectors);
        }

        // add default connector if none are configured
        if(connectorFactories.isEmpty()) {
            connectorFactories.add(new HttpConnectorFactory());
        }

        return connectorFactories;
    }

    protected QueuedThreadPool createThreadPool() {
        BlockingQueue<Runnable> queue = new BlockingArrayQueue<>(minThreads, maxThreads, maxQueuedRequests);
        QueuedThreadPool threadPool = createThreadPool(queue);
        threadPool.setName("bootique-http");

        return threadPool;
    }

    protected QueuedThreadPool createThreadPool(BlockingQueue<Runnable> queue) {
        return new QueuedThreadPool(maxThreads, minThreads, idleThreadTimeout, queue);
{'fraction_non_alphanumeric': 0.09341794569067297, 'fraction_numerical': 0.003394332939787485, 'mean_word_length': 3.2234340916173263, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7251403', 'n_tokens_mistral': 3610, 'n_tokens_neox': 3501, 'n_words': 723}