/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.camel.component.jetty;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.management.MBeanServer;
import javax.servlet.Filter;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.camel.CamelContext;
import org.apache.camel.Consumer;
import org.apache.camel.Endpoint;
import org.apache.camel.Processor;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.SSLContextParametersAware;
import org.apache.camel.http.common.CamelServlet;
import org.apache.camel.http.common.HttpBinding;
import org.apache.camel.http.common.HttpCommonComponent;
import org.apache.camel.http.common.HttpCommonEndpoint;
import org.apache.camel.http.common.HttpConfiguration;
import org.apache.camel.http.common.HttpConsumer;
import org.apache.camel.http.common.HttpRestServletResolveConsumerStrategy;
import org.apache.camel.http.common.UrlRewrite;
import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.spi.ManagementAgent;
import org.apache.camel.spi.ManagementStrategy;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.RestApiConsumerFactory;
import org.apache.camel.spi.RestConfiguration;
import org.apache.camel.spi.RestConsumerFactory;
import org.apache.camel.support.IntrospectionSupport;
import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.support.service.ServiceHelper;
import org.apache.camel.util.FileUtil;
import org.apache.camel.util.HostUtils;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.URISupport;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpClientTransport;
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.servlets.MultiPartFilter;
import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;

/**
 * An HttpComponent which starts an embedded Jetty for to handle consuming from
 * the http endpoints.
 */
public abstract class JettyHttpComponent extends HttpCommonComponent implements RestConsumerFactory, RestApiConsumerFactory, SSLContextParametersAware {
    public static final String TMP_DIR = "CamelJettyTempDir";

    protected static final HashMap<String, ConnectorRef> CONNECTORS = new HashMap<>();

    private static final String JETTY_SSL_KEYSTORE = "org.eclipse.jetty.ssl.keystore";
    private static final String JETTY_SSL_KEYPASSWORD = "org.eclipse.jetty.ssl.keypassword";
    private static final String JETTY_SSL_PASSWORD = "org.eclipse.jetty.ssl.password";

    protected String sslKeyPassword;
    protected String sslPassword;
    protected String sslKeystore;
    protected Map<Integer, Connector> sslSocketConnectors;
    protected Map<Integer, Connector> socketConnectors;
    protected Map<String, Object> sslSocketConnectorProperties;
    protected Map<String, Object> socketConnectorProperties;
    protected Integer httpClientMinThreads;
    protected Integer httpClientMaxThreads;
    protected Integer minThreads;
    protected Integer maxThreads;
    protected ThreadPool threadPool;
    protected MBeanContainer mbContainer;
    protected boolean enableJmx;
    protected JettyHttpBinding jettyHttpBinding;
    protected Long continuationTimeout;
    protected boolean useContinuation = true;
    protected SSLContextParameters sslContextParameters;
    protected boolean useGlobalSslContextParameters;
    protected Integer requestBufferSize;
    protected Integer requestHeaderSize;
    protected Integer responseBufferSize;
    protected Integer responseHeaderSize;
    protected String proxyHost;
    protected ErrorHandler errorHandler;
    protected boolean useXForwardedForHeader;
    private Integer proxyPort;
    private boolean sendServerVersion = true;

    public JettyHttpComponent() {
    }

    class ConnectorRef {
        CamelContext camelContext;
        Server server;
        Connector connector;
        CamelServlet servlet;
        int refCount;

        ConnectorRef(CamelContext camelContext, Server server, Connector connector, CamelServlet servlet) {
            this.camelContext = camelContext;
            this.server = server;
            this.connector = connector;
            this.servlet = servlet;
            increment();
        }

        public int increment() {
            return ++refCount;
        }

        public int decrement() {
            return --refCount;
        }

        public int getRefCount() {
            return refCount;
        }
    }

    @Override
    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {

        // must extract well known parameters before we create the endpoint
        List<Handler> handlerList = resolveAndRemoveReferenceListParameter(parameters, "handlers", Handler.class);
        HttpBinding binding = resolveAndRemoveReferenceParameter(parameters, "httpBindingRef", HttpBinding.class);
        JettyHttpBinding jettyBinding = resolveAndRemoveReferenceParameter(parameters, "jettyHttpBindingRef", JettyHttpBinding.class);
        Boolean enableJmx = getAndRemoveParameter(parameters, "enableJmx", Boolean.class);
        Boolean enableMultipartFilter = getAndRemoveParameter(parameters, "enableMultipartFilter",
                                                              Boolean.class, true);
        Filter multipartFilter = resolveAndRemoveReferenceParameter(parameters, "multipartFilterRef", Filter.class);
        List<Filter> filters = resolveAndRemoveReferenceListParameter(parameters, "filtersRef", Filter.class);
        Boolean enableCors = getAndRemoveParameter(parameters, "enableCORS", Boolean.class, false);
        HeaderFilterStrategy headerFilterStrategy = resolveAndRemoveReferenceParameter(parameters, "headerFilterStrategy", HeaderFilterStrategy.class);
        UrlRewrite urlRewrite = resolveAndRemoveReferenceParameter(parameters, "urlRewrite", UrlRewrite.class);
        SSLContextParameters sslContextParameters = resolveAndRemoveReferenceParameter(parameters, "sslContextParameters", SSLContextParameters.class);
        SSLContextParameters ssl = sslContextParameters != null ? sslContextParameters : this.sslContextParameters;
        ssl = ssl != null ? ssl : retrieveGlobalSslContextParameters();
        String proxyHost = getAndRemoveParameter(parameters, "proxyHost", String.class, getProxyHost());
        Integer proxyPort = getAndRemoveParameter(parameters, "proxyPort", Integer.class, getProxyPort());
        Boolean async = getAndRemoveParameter(parameters, "async", Boolean.class);

        // extract filterInit. parameters
        Map<String, String> filterInitParameters =  IntrospectionSupport.extractStringProperties(IntrospectionSupport.extractProperties(parameters, "filterInit."));

        String address = remaining;
        URI addressUri = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(address));
        URI endpointUri = URISupport.createRemainingURI(addressUri, parameters);
        // need to keep the httpMethodRestrict parameter for the endpointUri
        String httpMethodRestrict = getAndRemoveParameter(parameters, "httpMethodRestrict", String.class);
        // restructure uri to be based on the parameters left as we dont want to include the Camel internal options
        URI httpUri = URISupport.createRemainingURI(addressUri, parameters);
        // create endpoint after all known parameters have been extracted from parameters

        // include component scheme in the uri
        String scheme = StringHelper.before(uri, ":");
        endpointUri = new URI(scheme + ":" + endpointUri);

        JettyHttpEndpoint endpoint = createEndpoint(endpointUri, httpUri);
        if (async != null) {
            endpoint.setAsync(async);
        }

        if (headerFilterStrategy != null) {
            endpoint.setHeaderFilterStrategy(headerFilterStrategy);
        } else {
            setEndpointHeaderFilterStrategy(endpoint);
        }
        // setup the proxy host and proxy port
        if (proxyHost != null) {
            endpoint.setProxyHost(proxyHost);
            endpoint.setProxyPort(proxyPort);
        }
        if (urlRewrite != null) {
            // let CamelContext deal with the lifecycle of the url rewrite
            // this ensures its being shutdown when Camel shutdown etc.
            getCamelContext().addService(urlRewrite);
            endpoint.setUrlRewrite(urlRewrite);
        }
        // setup the proxy host and proxy port

        if (filterInitParameters != null && !filterInitParameters.isEmpty()) {
            endpoint.setFilterInitParameters(filterInitParameters);
        }
        if (handlerList.size() > 0) {
            endpoint.setHandlers(handlerList);
        }
        // prefer to use endpoint configured over component configured
        if (binding == null) {
            // fallback to component configured
            binding = getHttpBinding();
        }
        if (binding != null) {
            endpoint.setBinding(binding);
        }
        // prefer to use endpoint configured over component configured
        if (jettyBinding == null) {
            // fallback to component configured
            jettyBinding = getJettyHttpBinding();
        }
        if (enableJmx != null) {
            endpoint.setEnableJmx(enableJmx);
        } else {
            // set this option based on setting of JettyHttpComponent
            endpoint.setEnableJmx(isEnableJmx());
        }

        endpoint.setEnableMultipartFilter(enableMultipartFilter);
        if (multipartFilter != null) {
            endpoint.setMultipartFilter(multipartFilter);
            endpoint.setEnableMultipartFilter(true);
        }
        if (enableCors) {
            endpoint.setEnableCORS(enableCors);
            if (filters == null) {
                filters = new ArrayList<>(1);
            }
            filters.add(new CrossOriginFilter());
        }
        if (filters != null) {
            endpoint.setFilters(filters);
        }

        if (httpMethodRestrict != null) {
            endpoint.setHttpMethodRestrict(httpMethodRestrict);
        }
        if (ssl != null) {
            endpoint.setSslContextParameters(ssl);
        }
        endpoint.setSendServerVersion(isSendServerVersion());

        setProperties(endpoint, parameters);

        // re-create http uri after all parameters has been set on the endpoint, as the remainders are for http uri
        httpUri = URISupport.createRemainingURI(addressUri, parameters);
        endpoint.setHttpUri(httpUri);

        return endpoint;
    }

    protected abstract JettyHttpEndpoint createEndpoint(URI endpointUri, URI httpUri) throws URISyntaxException;

    @Override
    public boolean canConnect(HttpConsumer consumer) throws Exception {
        // Make sure that there is a connector for the requested endpoint.
        JettyHttpEndpoint endpoint = (JettyHttpEndpoint)consumer.getEndpoint();
        String connectorKey = getConnectorKey(endpoint);

        synchronized (CONNECTORS) {
            ConnectorRef connectorRef = CONNECTORS.get(connectorKey);

            // check if there are already another consumer on the same context-path and if so fail
            if (connectorRef != null) {
                for (Map.Entry<String, HttpConsumer> entry : connectorRef.servlet.getConsumers().entrySet()) {
                    String path = entry.getValue().getPath();
                    CamelContext camelContext = entry.getValue().getEndpoint().getCamelContext();
                    if (consumer.getPath().equals(path)) {
                        // its allowed if they are from the same camel context
                        boolean sameContext = consumer.getEndpoint().getCamelContext() == camelContext;
                        if (!sameContext) {
                            return false;
                        }
                    }
                }
            }
        }

        return true;
    }

    /**
     * Connects the URL specified on the endpoint to the specified processor.
     */
    @Override
    public void connect(HttpConsumer consumer) throws Exception {
        // Make sure that there is a connector for the requested endpoint.
        JettyHttpEndpoint endpoint = (JettyHttpEndpoint)consumer.getEndpoint();
        String connectorKey = getConnectorKey(endpoint);

        synchronized (CONNECTORS) {
            ConnectorRef connectorRef = CONNECTORS.get(connectorKey);
            if (connectorRef == null) {
                Server server = createServer();
                Connector connector = getConnector(server, endpoint);
                if ("localhost".equalsIgnoreCase(endpoint.getHttpUri().getHost())) {
                    log.warn("You use localhost interface! It means that no external connections will be available."
                            + " Don't you want to use 0.0.0.0 instead (all network interfaces)? " + endpoint);
                }
                if (endpoint.isEnableJmx()) {
                    enableJmx(server);
                }
                server.addConnector(connector);

                connectorRef = new ConnectorRef(getCamelContext(), server, connector, createServletForConnector(server, connector, endpoint.getHandlers(), endpoint));
                // must enable session before we start
                if (endpoint.isSessionSupport()) {
                    enableSessionSupport(connectorRef.server, connectorKey);
                }
                connectorRef.server.start();

                log.debug("Adding connector key: {} -> {}", connectorKey, connectorRef);
                CONNECTORS.put(connectorKey, connectorRef);

            } else {
                log.debug("Using existing connector key: {} -> {}", connectorKey, connectorRef);

                // check if there are any new handlers, and if so then we need to re-start the server
                if (endpoint.getHandlers() != null && !endpoint.getHandlers().isEmpty()) {
                    List<Handler> existingHandlers = new ArrayList<>();
                    if (connectorRef.server.getHandlers() != null && connectorRef.server.getHandlers().length > 0) {
                        existingHandlers = Arrays.asList(connectorRef.server.getHandlers());
                    }
                    List<Handler> newHandlers = new ArrayList<>(endpoint.getHandlers());
                    boolean changed = !existingHandlers.containsAll(newHandlers) && !newHandlers.containsAll(existingHandlers);
                    if (changed) {
                        log.debug("Restarting Jetty server due to adding new Jetty Handlers: {}", newHandlers);
                        connectorRef.server.stop();
                        addJettyHandlers(connectorRef.server, endpoint.getHandlers());
                        connectorRef.server.start();
                    }
                }
                // check the session support
                if (endpoint.isSessionSupport()) {
                    enableSessionSupport(connectorRef.server, connectorKey);
                }
                // ref track the connector
                connectorRef.increment();
            }

            if (endpoint.isEnableMultipartFilter()) {
                enableMultipartFilter(endpoint, connectorRef.server, connectorKey);
            }

            if (endpoint.getFilters() != null && endpoint.getFilters().size() > 0) {
                setFilters(endpoint, connectorRef.server, connectorKey);
            }
            connectorRef.servlet.connect(consumer);
        }
    }

    private void enableJmx(Server server) {
        MBeanContainer containerToRegister = getMbContainer();
        if (containerToRegister != null) {
            log.info("Jetty JMX Extensions is enabled");
            addServerMBean(server);
            // Since we may have many Servers running, don't tie the MBeanContainer
            // to a Server lifecycle or we end up closing it while it is still in use.
            //server.addBean(mbContainer);
        }
    }

    private void enableSessionSupport(Server server, String connectorKey) throws Exception {
        ServletContextHandler context = server.getChildHandlerByClass(ServletContextHandler.class);
        if (context.getSessionHandler() == null) {
            SessionHandler sessionHandler = new SessionHandler();
            if (context.isStarted()) {
                throw new IllegalStateException("Server has already been started. Cannot enabled sessionSupport on " + connectorKey);
            } else {
                context.setSessionHandler(sessionHandler);
            }
        }
    }

    private void setFilters(JettyHttpEndpoint endpoint, Server server, String connectorKey) {
        ServletContextHandler context = server.getChildHandlerByClass(ServletContextHandler.class);
        List<Filter> filters = endpoint.getFilters();
        for (Filter filter : filters) {
            FilterHolder filterHolder = new FilterHolder();
            if (endpoint.getFilterInitParameters() != null) {
                filterHolder.setInitParameters(endpoint.getFilterInitParameters());
            }
            filterHolder.setFilter(new CamelFilterWrapper(filter));
            String pathSpec = endpoint.getPath();
            if (pathSpec == null || "".equals(pathSpec)) {
                pathSpec = "/";
            }
            if (endpoint.isMatchOnUriPrefix()) {
                pathSpec = pathSpec.endsWith("/") ? pathSpec + "*" : pathSpec + "/*";
            }
            addFilter(context, filterHolder, pathSpec);
        }
    }

    private void addFilter(ServletContextHandler context, FilterHolder filterHolder, String pathSpec) {
        context.getServletHandler().addFilterWithMapping(filterHolder, pathSpec, 0);
    }

    private void enableMultipartFilter(HttpCommonEndpoint endpoint, Server server, String connectorKey) throws Exception {
        ServletContextHandler context = server.getChildHandlerByClass(ServletContextHandler.class);
        CamelContext camelContext = this.getCamelContext();
        FilterHolder filterHolder = new FilterHolder();
        filterHolder.setInitParameter("deleteFiles", "true");
        if (ObjectHelper.isNotEmpty(camelContext.getGlobalOption(TMP_DIR))) {
            File file = new File(camelContext.getGlobalOption(TMP_DIR));
            if (!file.isDirectory()) {
                throw new RuntimeCamelException(
                        "The temp file directory of camel-jetty is not exists, please recheck it with directory name :"
                                + camelContext.getGlobalOptions().get(TMP_DIR));
            }
            context.setAttribute("javax.servlet.context.tempdir", file);
        }
        // if a filter ref was provided, use it.
        Filter filter = ((JettyHttpEndpoint) endpoint).getMultipartFilter();
        if (filter == null) {
            // if no filter ref was provided, use the default filter
            filter = new MultiPartFilter();
        }
        filterHolder.setFilter(new CamelFilterWrapper(filter));
        String pathSpec = endpoint.getPath();
        if (pathSpec == null || "".equals(pathSpec)) {
            pathSpec = "/";
        }
        if (endpoint.isMatchOnUriPrefix()) {
            pathSpec = pathSpec.endsWith("/") ? pathSpec + "*" : pathSpec + "/*";
        }
        addFilter(context, filterHolder, pathSpec);
        log.debug("using multipart filter implementation " + filter.getClass().getName() + " for path " + pathSpec);
    }

    /**
     * Disconnects the URL specified on the endpoint from the specified processor.
     */
    @Override
    public void disconnect(HttpConsumer consumer) throws Exception {
        // If the connector is not needed anymore then stop it
        HttpCommonEndpoint endpoint = consumer.getEndpoint();
        String connectorKey = getConnectorKey(endpoint);

        synchronized (CONNECTORS) {
            ConnectorRef connectorRef = CONNECTORS.get(connectorKey);
            if (connectorRef != null) {
                connectorRef.servlet.disconnect(consumer);
                if (connectorRef.decrement() == 0) {
                    connectorRef.server.removeConnector(connectorRef.connector);
                    connectorRef.connector.stop();
                    connectorRef.server.stop();
                    CONNECTORS.remove(connectorKey);
                    // Camel controls the lifecycle of these entities so remove the
                    // registered MBeans when Camel is done with the managed objects.
                    if (mbContainer != null) {
                        this.removeServerMBean(connectorRef.server);
                        //mbContainer.removeBean(connectorRef.connector);
                    }
                }
            }
        }
    }

    private String getConnectorKey(HttpCommonEndpoint endpoint) {
        return endpoint.getProtocol() + ":" + endpoint.getHttpUri().getHost() + ":" + endpoint.getPort();
    }

    // Properties
    // -------------------------------------------------------------------------

    public String getSslKeyPassword() {
        return sslKeyPassword;
    }

    /**
     * The key password, which is used to access the certificate's key entry in the keystore (this is the same password that is supplied to the keystore command's -keypass option).
     */
    @Metadata(description = "The key password, which is used to access the certificate's key entry in the keystore "
            + "(this is the same password that is supplied to the keystore command's -keypass option).",
            label = "security", secret = true)
    public void setSslKeyPassword(String sslKeyPassword) {
        this.sslKeyPassword = sslKeyPassword;
    }

    public String getSslPassword() {
        return sslPassword;
    }

    /**
     * The ssl password, which is required to access the keystore file (this is the same password that is supplied to the keystore command's -storepass option).
     */
    @Metadata(description = "The ssl password, which is required to access the keystore file (this is the same password that is supplied to the keystore command's -storepass option).",
            label = "security", secret = true)
    public void setSslPassword(String sslPassword) {
        this.sslPassword = sslPassword;
    }

    /**
     * Specifies the location of the Java keystore file, which contains the Jetty server's own X.509 certificate in a key entry.
     */
    @Metadata(description = "Specifies the location of the Java keystore file, which contains the Jetty server's own X.509 certificate in a key entry.",
            label = "security", secret = true)
    public void setKeystore(String sslKeystore) {
        this.sslKeystore = sslKeystore;
    }

    public String getKeystore() {
        return sslKeystore;
    }

    public ErrorHandler getErrorHandler() {
        return errorHandler;
    }

    /**
     * This option is used to set the ErrorHandler that Jetty server uses.
     */
    @Metadata(description = "This option is used to set the ErrorHandler that Jetty server uses.", label = "advanced")
    public void setErrorHandler(ErrorHandler errorHandler) {
        this.errorHandler = errorHandler;
    }

    protected Connector getConnector(Server server, JettyHttpEndpoint endpoint) {
        Connector connector;
        if ("https".equals(endpoint.getProtocol())) {
            connector = getSslSocketConnector(server, endpoint);
        } else {
            connector = getSocketConnector(server, endpoint);
        }
        return connector;
    }
    protected Connector getSocketConnector(Server server, JettyHttpEndpoint endpoint) {
        Connector answer = null;
        if (socketConnectors != null) {
            answer = socketConnectors.get(endpoint.getPort());
        }
        if (answer == null) {
            answer = createConnector(server, endpoint);
        }
        return answer;
    }

    protected Connector getSslSocketConnector(Server server, JettyHttpEndpoint endpoint) {
        Connector answer = null;
        if (sslSocketConnectors != null) {
            answer = sslSocketConnectors.get(endpoint.getPort());
        }
        if (answer == null) {
            answer = createConnector(server, endpoint);
        }
        return answer;
    }

    protected Connector createConnector(Server server, JettyHttpEndpoint endpoint) {

        // now we just use the SelectChannelConnector as the default connector
        SslContextFactory sslcf = null;

        // Note that this was set on the endpoint when it was constructed.  It was
        // either explicitly set at the component or on the endpoint, but either way,
        // the value is already set.  We therefore do not need to look at the component
        // level SSLContextParameters again in this method.
        SSLContextParameters endpointSslContextParameters = endpoint.getSslContextParameters();

        if (endpointSslContextParameters != null) {
            try {
                sslcf = createSslContextFactory(endpointSslContextParameters, false);
            } catch (Exception e) {
                throw new RuntimeCamelException(e);
            }
        } else if ("https".equals(endpoint.getProtocol())) {
            sslcf = new SslContextFactory();
            sslcf.setEndpointIdentificationAlgorithm(null);
            String keystoreProperty = System.getProperty(JETTY_SSL_KEYSTORE);
            if (keystoreProperty != null) {
                sslcf.setKeyStorePath(keystoreProperty);
            } else if (sslKeystore != null) {
                sslcf.setKeyStorePath(sslKeystore);
            }

            String keystorePassword = System.getProperty(JETTY_SSL_KEYPASSWORD);
            if (keystorePassword != null) {
                sslcf.setKeyManagerPassword(keystorePassword);
            } else if (sslKeyPassword != null) {
                sslcf.setKeyManagerPassword(sslKeyPassword);
            }

            String password = System.getProperty(JETTY_SSL_PASSWORD);
            if (password != null) {
                sslcf.setKeyStorePassword(password);
            } else if (sslPassword != null) {
                sslcf.setKeyStorePassword(sslPassword);
            }
        }

        return createConnectorJettyInternal(server, endpoint, sslcf);
    }

    protected abstract AbstractConnector createConnectorJettyInternal(Server server, JettyHttpEndpoint endpoint, SslContextFactory sslcf);

    private SslContextFactory createSslContextFactory(SSLContextParameters ssl, boolean client) throws GeneralSecurityException, IOException {
        SslContextFactory answer = new SslContextFactory();
        if (!client) {
            answer.setEndpointIdentificationAlgorithm(null);
        }
        if (ssl != null) {
            answer.setSslContext(ssl.createSSLContext(getCamelContext()));
        }

        // jetty default is
        // addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
        // setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$");

        // configure include/exclude ciphers and protocols
        if (ssl != null && ssl.getCipherSuitesFilter() != null)  {
            List<String> includeCiphers = ssl.getCipherSuitesFilter().getInclude();
            if (includeCiphers != null && !includeCiphers.isEmpty()) {
                String[] arr = includeCiphers.toArray(new String[includeCiphers.size()]);
                answer.setIncludeCipherSuites(arr);
            } else {
                answer.setIncludeCipherSuites(".*");
            }
            List<String> excludeCiphers = ssl.getCipherSuitesFilter().getExclude();
            if (excludeCiphers != null && !excludeCiphers.isEmpty()) {
                String[] arr = excludeCiphers.toArray(new String[excludeCiphers.size()]);
                answer.setExcludeCipherSuites(arr);
            }
        }
        if (ssl != null && ssl.getSecureSocketProtocolsFilter() != null) {
            List<String> includeProtocols = ssl.getSecureSocketProtocolsFilter().getInclude();
            if (includeProtocols != null && !includeProtocols.isEmpty()) {
                String[] arr = includeProtocols.toArray(new String[includeProtocols.size()]);
                answer.setIncludeProtocols(arr);
            } else {
                answer.setIncludeProtocols(".*");
            }
            List<String> excludeProtocols = ssl.getSecureSocketProtocolsFilter().getExclude();
            if (excludeProtocols != null && !excludeProtocols.isEmpty()) {
                String[] arr = excludeProtocols.toArray(new String[excludeProtocols.size()]);
                answer.setExcludeProtocols(arr);
            }
        }

        return answer;
    }

    protected boolean checkSSLContextFactoryConfig(Object instance) {
        try {
            Method method = instance.getClass().getMethod("checkConfig");
            return (Boolean)method.invoke(instance);
        } catch (NoSuchMethodException ex) {
            // ignore
        } catch (IllegalArgumentException e) {
            // ignore
        } catch (IllegalAccessException e) {
            // ignore
        } catch (InvocationTargetException e) {
            // ignore
        }
        return false;
    }

    public Map<Integer, Connector> getSslSocketConnectors() {
        return sslSocketConnectors;
    }

    /**
     * A map which contains per port number specific SSL connectors.
     */
    @Metadata(description = "A map which contains per port number specific SSL connectors.", label = "security")
    public void setSslSocketConnectors(Map <Integer, Connector> connectors) {
        sslSocketConnectors = connectors;
    }

    /**
     * A map which contains per port number specific HTTP connectors. Uses the same principle as sslSocketConnectors.
     */
    @Metadata(description = "A map which contains per port number specific HTTP connectors. Uses the same principle as sslSocketConnectors.", label = "security")
    public void setSocketConnectors(Map<Integer, Connector> socketConnectors) {
        this.socketConnectors = socketConnectors;
    }

    /**
     * Creates a new {@link HttpClient} and configures its proxy/thread pool and SSL based on this
     * component settings.
     *
     * @param endpoint   the instance of JettyHttpEndpoint
     * @param minThreads optional minimum number of threads in client thread pool
     * @param maxThreads optional maximum number of threads in client thread pool
     * @param ssl        option SSL parameters
     */
    public CamelHttpClient createHttpClient(JettyHttpEndpoint endpoint, Integer minThreads, Integer maxThreads, SSLContextParameters ssl) throws Exception {
        SslContextFactory sslContextFactory = createSslContextFactory(ssl, true);
        HttpClientTransport transport = createHttpClientTransport(maxThreads);
        CamelHttpClient httpClient = createCamelHttpClient(transport, sslContextFactory);

        CamelContext context = endpoint.getCamelContext();

        if (context != null
            && ObjectHelper.isNotEmpty(context.getGlobalOption("http.proxyHost"))
            && ObjectHelper.isNotEmpty(context.getGlobalOption("http.proxyPort"))) {
            String host = context.getGlobalOption("http.proxyHost");
            int port = Integer.parseInt(context.getGlobalOption("http.proxyPort"));
            log.debug("CamelContext properties http.proxyHost and http.proxyPort detected. Using http proxy host: {} port: {}", host, port);
            httpClient.setProxy(host, port);
        }

        if (ObjectHelper.isNotEmpty(endpoint.getProxyHost()) && endpoint.getProxyPort() > 0) {
            String host = endpoint.getProxyHost();
            int port = endpoint.getProxyPort();
            log.debug("proxyHost and proxyPort options detected. Using http proxy host: {} port: {}", host, port);
            httpClient.setProxy(host, port);
        }

        // must have both min and max
        if (minThreads != null || maxThreads != null) {

            // must have both options
            if (minThreads == null || maxThreads == null) {
                throw new IllegalArgumentException("Both min and max thread pool sizes must be provided.");
            }

            // use QueueThreadPool as the default bounded is deprecated (see SMXCOMP-157)
            QueuedThreadPool qtp = new QueuedThreadPool();
            qtp.setMinThreads(minThreads.intValue());
            qtp.setMaxThreads(maxThreads.intValue());
            // and we want to use daemon threads
            qtp.setDaemon(true);
            // let the thread names indicate they are from the client
            qtp.setName("CamelJettyClient(" + ObjectHelper.getIdentityHashCode(httpClient) + ")");
            httpClient.setThreadPoolOrExecutor(qtp);
        }

        if (log.isDebugEnabled()) {
            if (minThreads != null) {
                log.debug("Created HttpClient with thread pool {}-{} -> {}", minThreads, maxThreads, httpClient);
            } else {
                log.debug("Created HttpClient with default thread pool size -> {}", httpClient);
            }
        }

        return httpClient;
    }

    private HttpClientTransport createHttpClientTransport(Integer maxThreads) {
        if (maxThreads == null) {
            return new HttpClientTransportOverHTTP();
        }

        int selectors = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);

        if (selectors >= maxThreads) {
            selectors = maxThreads - 1;
        }

        return new HttpClientTransportOverHTTP(selectors);
    }

    protected abstract CamelHttpClient createCamelHttpClient(HttpClientTransport transport, SslContextFactory sslContextFactory);

    public Integer getHttpClientMinThreads() {
        return httpClientMinThreads;
    }

    /**
     * To set a value for minimum number of threads in HttpClient thread pool. Notice that both a min and max size must be configured.
     */
    @Metadata(description = "To set a value for minimum number of threads in HttpClient thread pool. Notice that both a min and max size must be configured.", label = "producer")
    public void setHttpClientMinThreads(Integer httpClientMinThreads) {
        this.httpClientMinThreads = httpClientMinThreads;
    }

    public Integer getHttpClientMaxThreads() {
        return httpClientMaxThreads;
    }

    /**
     * To set a value for maximum number of threads in HttpClient thread pool. Notice that both a min and max size must be configured.
     */
    @Metadata(description = "To set a value for maximum number of threads in HttpClient thread pool. Notice that both a min and max size must be configured.", label = "producer")
    public void setHttpClientMaxThreads(Integer httpClientMaxThreads) {
        this.httpClientMaxThreads = httpClientMaxThreads;
    }

    public Integer getMinThreads() {
        return minThreads;
    }

    /**
     * To set a value for minimum number of threads in server thread pool. Notice that both a min and max size must be configured.
     */
    @Metadata(description = "To set a value for minimum number of threads in server thread pool. Notice that both a min and max size must be configured.", label = "consumer")
    public void setMinThreads(Integer minThreads) {
        this.minThreads = minThreads;
    }

    public Integer getMaxThreads() {
        return maxThreads;
    }

    /**
     * To set a value for maximum number of threads in server thread pool. Notice that both a min and max size must be configured.
     */
    @Metadata(description = "To set a value for maximum number of threads in server thread pool. Notice that both a min and max size must be configured.", label = "consumer")
    public void setMaxThreads(Integer maxThreads) {
        this.maxThreads = maxThreads;
    }

    public ThreadPool getThreadPool() {
        return threadPool;
    }

    /**
     * To use a custom thread pool for the server. This option should only be used in special circumstances.
     */
    @Metadata(description = "To use a custom thread pool for the server. This option should only be used in special circumstances.", label = "consumer,advanced")
    public void setThreadPool(ThreadPool threadPool) {
        this.threadPool = threadPool;
    }

    public boolean isEnableJmx() {
        return enableJmx;
    }

    /**
     * If this option is true, Jetty JMX support will be enabled for this endpoint.
     */
    @Metadata(description = "If this option is true, Jetty JMX support will be enabled for this endpoint.")
    public void setEnableJmx(boolean enableJmx) {
        this.enableJmx = enableJmx;
    }

    public JettyHttpBinding getJettyHttpBinding() {
        return jettyHttpBinding;
    }

    /**
     * To use a custom org.apache.camel.component.jetty.JettyHttpBinding, which are used to customize how a response should be written for the producer.
     */
    @Metadata(description = "To use a custom org.apache.camel.component.jetty.JettyHttpBinding, which are used to customize how a response should be written for the producer.", label = "advanced")
    public void setJettyHttpBinding(JettyHttpBinding jettyHttpBinding) {
        this.jettyHttpBinding = jettyHttpBinding;
    }

    /**
     * Not to be used - use JettyHttpBinding instead.
     */
    @Override
    @Metadata(description = "Not to be used - use JettyHttpBinding instead.", label = "advanced")
    public void setHttpBinding(HttpBinding httpBinding) {
        throw new IllegalArgumentException("Not to be used - use JettyHttpBinding instead.");
    }

    /**
     * Jetty component does not use HttpConfiguration.
     */
    @Override
    @Metadata(description = "Jetty component does not use HttpConfiguration.", label = "advanced")
    public void setHttpConfiguration(HttpConfiguration httpConfiguration) {
        throw new IllegalArgumentException("Jetty component does not use HttpConfiguration.");
    }

    public synchronized MBeanContainer getMbContainer() {
        // If null, provide the default implementation.
        if (mbContainer == null) {
            MBeanServer mbs = null;

            final ManagementStrategy mStrategy = this.getCamelContext().getManagementStrategy();
            final ManagementAgent mAgent = mStrategy.getManagementAgent();
            if (mAgent != null) {
                mbs = mAgent.getMBeanServer();
            }

            if (mbs != null) {
                mbContainer = new MBeanContainer(mbs);
                startMbContainer();
            } else {
                log.warn("JMX disabled in CamelContext. Jetty JMX extensions will remain disabled.");
            }
        }

        return this.mbContainer;
    }

    /**
     * To use a existing configured org.eclipse.jetty.jmx.MBeanContainer if JMX is enabled that Jetty uses for registering mbeans.
     */
    @Metadata(description = "To use a existing configured org.eclipse.jetty.jmx.MBeanContainer if JMX is enabled that Jetty uses for registering mbeans.", label = "advanced")
    public void setMbContainer(MBeanContainer mbContainer) {
        this.mbContainer = mbContainer;
    }

    public Map<String, Object> getSslSocketConnectorProperties() {
        return sslSocketConnectorProperties;
    }

    /**
     * A map which contains general SSL connector properties.
     */
    @Metadata(description = "A map which contains general SSL connector properties.", label = "security")
    public void setSslSocketConnectorProperties(Map<String, Object> sslSocketConnectorProperties) {
        this.sslSocketConnectorProperties = sslSocketConnectorProperties;
    }

    public Map<String, Object> getSocketConnectorProperties() {
        return socketConnectorProperties;
    }

    /**
     * A map which contains general HTTP connector properties. Uses the same principle as sslSocketConnectorProperties.
     */
    @Metadata(description = "A map which contains general HTTP connector properties. Uses the same principle as sslSocketConnectorProperties.", label = "security")
    public void setSocketConnectorProperties(Map<String, Object> socketConnectorProperties) {
        this.socketConnectorProperties = socketConnectorProperties;
    }

    public void addSocketConnectorProperty(String key, Object value) {
        if (socketConnectorProperties == null) {
            socketConnectorProperties = new HashMap<>();
        }
        socketConnectorProperties.put(key, value);
    }

    public void addSslSocketConnectorProperty(String key, Object value) {
        if (sslSocketConnectorProperties == null) {
            sslSocketConnectorProperties = new HashMap<>();
        }
        sslSocketConnectorProperties.put(key, value);
    }

    public Long getContinuationTimeout() {
        return continuationTimeout;
    }

    /**
     * Allows to set a timeout in millis when using Jetty as consumer (server).
     * By default Jetty uses 30000. You can use a value of <= 0 to never expire.
     * If a timeout occurs then the request will be expired and Jetty will return back a http error 503 to the client.
     * This option is only in use when using Jetty with the Asynchronous Routing Engine.
     */
    @Metadata(description = "Allows to set a timeout in millis when using Jetty as consumer (server)."
            + " By default Jetty uses 30000. You can use a value of <= 0 to never expire."
            + " If a timeout occurs then the request will be expired and Jetty will return back a http error 503 to the client."
            + " This option is only in use when using Jetty with the Asynchronous Routing Engine.", defaultValue = "30000", label = "consumer")
    public void setContinuationTimeout(Long continuationTimeout) {
        this.continuationTimeout = continuationTimeout;
    }

    public boolean isUseContinuation() {
        return useContinuation;
    }

    /**
     * Whether or not to use Jetty continuations for the Jetty Server.
     */
    @Metadata(description = "Whether or not to use Jetty continuations for the Jetty Server.", defaultValue = "true", label = "consumer")
    public void setUseContinuation(boolean useContinuation) {
        this.useContinuation = useContinuation;
    }

    public SSLContextParameters getSslContextParameters() {
        return sslContextParameters;
    }

    /**
     * To configure security using SSLContextParameters
     */
    @Metadata(description = "To configure security using SSLContextParameters", label = "security")
    public void setSslContextParameters(SSLContextParameters sslContextParameters) {
        this.sslContextParameters = sslContextParameters;
    }

    @Override
    public boolean isUseGlobalSslContextParameters() {
        return this.useGlobalSslContextParameters;
    }

    /**
     * Enable usage of global SSL context parameters
     */
    @Override
    @Metadata(description = "Enable usage of global SSL context parameters", label = "security", defaultValue = "false")
    public void setUseGlobalSslContextParameters(boolean useGlobalSslContextParameters) {
        this.useGlobalSslContextParameters = useGlobalSslContextParameters;
    }

    public Integer getResponseBufferSize() {
        return responseBufferSize;
    }

    /**
     * Allows to configure a custom value of the response buffer size on the Jetty connectors.
     */
    @Metadata(description = "Allows to configure a custom value of the response buffer size on the Jetty connectors.")
    public void setResponseBufferSize(Integer responseBufferSize) {
        this.responseBufferSize = responseBufferSize;
    }

    public Integer getRequestBufferSize() {
        return requestBufferSize;
    }

    /**
     * Allows to configure a custom value of the request buffer size on the Jetty connectors.
     */
    @Metadata(description = "Allows to configure a custom value of the request buffer size on the Jetty connectors.")
    public void setRequestBufferSize(Integer requestBufferSize) {
        this.requestBufferSize = requestBufferSize;
    }

    public Integer getRequestHeaderSize() {
        return requestHeaderSize;
    }

    /**
     * Allows to configure a custom value of the request header size on the Jetty connectors.
     */
    @Metadata(description = "Allows to configure a custom value of the request header size on the Jetty connectors.")
    public void setRequestHeaderSize(Integer requestHeaderSize) {
        this.requestHeaderSize = requestHeaderSize;
    }

    public Integer getResponseHeaderSize() {
        return responseHeaderSize;
    }

    /**
     * Allows to configure a custom value of the response header size on the Jetty connectors.
     */
    @Metadata(description = "Allows to configure a custom value of the response header size on the Jetty connectors.")
    public void setResponseHeaderSize(Integer responseHeaderSize) {
        this.responseHeaderSize = responseHeaderSize;
    }

    public String getProxyHost() {
        return proxyHost;
    }

    /**
     * To use a http proxy to configure the hostname.
     */
    @Metadata(description = "To use a http proxy to configure the hostname.", label = "proxy")
    public void setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
    }

    public Integer getProxyPort() {
        return proxyPort;
    }

    /**
     * To use a http proxy to configure the port number.
     */
    @Metadata(description = "To use a http proxy to configure the port number.", label = "proxy")
    public void setProxyPort(Integer proxyPort) {
        this.proxyPort = proxyPort;
    }

    public boolean isUseXForwardedForHeader() {
        return useXForwardedForHeader;
    }

    /**
     * To use the X-Forwarded-For header in HttpServletRequest.getRemoteAddr.
     */
    @Metadata(description = "To use the X-Forwarded-For header in HttpServletRequest.getRemoteAddr.")
    public void setUseXForwardedForHeader(boolean useXForwardedForHeader) {
        this.useXForwardedForHeader = useXForwardedForHeader;
    }

    public boolean isSendServerVersion() {
        return sendServerVersion;
    }

    /**
     * If the option is true, jetty will send the server header with the jetty version information to the client which sends the request.
     * NOTE please make sure there is no any other camel-jetty endpoint is share the same port, otherwise this option may not work as expected.
     */
    @Metadata(description = "If the option is true, jetty will send the server header with the jetty version information to the client which sends the request."
            + " NOTE please make sure there is no any other camel-jetty endpoint is share the same port, otherwise this option may not work as expected.",
            defaultValue = "true", label = "consumer")
    public void setSendServerVersion(boolean sendServerVersion) {
        this.sendServerVersion = sendServerVersion;
    }

    // Implementation methods
    // -------------------------------------------------------------------------

    @Override
    public Consumer createConsumer(CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
                                   String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters) throws Exception {
        return doCreateConsumer(camelContext, processor, verb, basePath, uriTemplate, consumes, produces, configuration, parameters, false);
    }

    @Override
    public Consumer createApiConsumer(CamelContext camelContext, Processor processor, String contextPath,
                                      RestConfiguration configuration, Map<String, Object> parameters) throws Exception {
        // reuse the createConsumer method we already have. The api need to use GET and match on uri prefix
        return doCreateConsumer(camelContext, processor, "GET", contextPath, null, null, null, configuration, parameters, true);
    }

    Consumer doCreateConsumer(CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
                              String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters, boolean api) throws Exception {

        String path = basePath;
        if (uriTemplate != null) {
            // make sure to avoid double slashes
            if (uriTemplate.startsWith("/")) {
                path = path + uriTemplate;
            } else {
                path = path + "/" + uriTemplate;
            }
        }
        path = FileUtil.stripLeadingSeparator(path);

        String scheme = "http";
        String host = "";
        int port = 0;

        // if no explicit port/host configured, then use port from rest configuration
        RestConfiguration config = configuration;
        if (config == null) {
            config = camelContext.getRestConfiguration("jetty", true);
        }
        if (config.getScheme() != null) {
            scheme = config.getScheme();
        }
        if (config.getHost() != null) {
            host = config.getHost();
        }
        int num = config.getPort();
        if (num > 0) {
            port = num;
        }

        // prefix path with context-path if configured in rest-dsl configuration
        String contextPath = config.getContextPath();
        if (ObjectHelper.isNotEmpty(contextPath)) {
            contextPath = FileUtil.stripTrailingSeparator(contextPath);
            contextPath = FileUtil.stripLeadingSeparator(contextPath);
            if (ObjectHelper.isNotEmpty(contextPath)) {
                path = contextPath + "/" + path;
            }
        }

        // if no explicit hostname set then resolve the hostname
        if (ObjectHelper.isEmpty(host)) {
            if (config.getHostNameResolver() == RestConfiguration.RestHostNameResolver.allLocalIp) {
                host = "0.0.0.0";
            } else if (config.getHostNameResolver() == RestConfiguration.RestHostNameResolver.localHostName) {
                host = HostUtils.getLocalHostName();
            } else if (config.getHostNameResolver() == RestConfiguration.RestHostNameResolver.localIp) {
                host = HostUtils.getLocalIp();
            }
        }

        Map<String, Object> map = new HashMap<>();
        // build query string, and append any endpoint configuration properties
        if (config.getComponent() == null || config.getComponent().equals("jetty")) {
            // setup endpoint options
            if (config.getEndpointProperties() != null && !config.getEndpointProperties().isEmpty()) {
                map.putAll(config.getEndpointProperties());
            }
        }

        boolean cors = config.isEnableCORS();
        if (cors) {
            // allow HTTP Options as we want to handle CORS in rest-dsl
            map.put("optionsEnabled", "true");
        }

        String query = URISupport.createQueryString(map);

        String url;
        if (api) {
            url = "jetty:%s://%s:%s/%s?matchOnUriPrefix=true&httpMethodRestrict=%s";
        } else {
            url = "jetty:%s://%s:%s/%s?httpMethodRestrict=%s";
        }

        // must use upper case for restrict
        String restrict = verb.toUpperCase(Locale.US);
        if (cors) {
            restrict += ",OPTIONS";
        }
        // get the endpoint
        url = String.format(url, scheme, host, port, path, restrict);

        if (!query.isEmpty()) {
            url = url + "&" + query;
        }

        JettyHttpEndpoint endpoint = camelContext.getEndpoint(url, JettyHttpEndpoint.class);
        setProperties(camelContext, endpoint, parameters);

        if (!map.containsKey("httpBindingRef")) {
            // use the rest binding, if not using a custom http binding
            endpoint.setHttpBinding(new JettyRestHttpBinding(endpoint));
            // disable this filter as we want to use ours
            endpoint.setEnableMultipartFilter(false);
        }

        // configure consumer properties
        Consumer consumer = endpoint.createConsumer(processor);
        if (config.getConsumerProperties() != null && !config.getConsumerProperties().isEmpty()) {
            setProperties(camelContext, consumer, config.getConsumerProperties());
        }

        // the endpoint must be started before creating the producer
        ServiceHelper.startService(endpoint);

        return consumer;
    }

    protected CamelServlet createServletForConnector(Server server, Connector connector,
                                                     List<Handler> handlers, JettyHttpEndpoint endpoint) throws Exception {
        ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.NO_SECURITY | ServletContextHandler.NO_SESSIONS);
        if (Server.getVersion().startsWith("8")) {
            context.getClass().getMethod("setConnectorNames", new Class[] {String[].class})
                .invoke(context, new Object[] {new String[] {connector.getName()}});
        }

        addJettyHandlers(server, handlers);

        CamelServlet camelServlet = new CamelContinuationServlet();
        ServletHolder holder = new ServletHolder();
        holder.setServlet(camelServlet);
        holder.setAsyncSupported(true);
        holder.setInitParameter(CamelServlet.ASYNC_PARAM, Boolean.toString(endpoint.isAsync()));
        context.addServlet(holder, "/*");

        // use rest enabled resolver in case we use rest
        camelServlet.setServletResolveConsumerStrategy(new HttpRestServletResolveConsumerStrategy());

        return camelServlet;
    }

    protected void addJettyHandlers(Server server, List<Handler> handlers) {
        if (handlers != null && !handlers.isEmpty()) {
            for (Handler handler : handlers) {
                if (handler instanceof HandlerWrapper) {
                    // avoid setting a handler more than once
                    if (!isHandlerInChain(server.getHandler(), handler)) {
                        ((HandlerWrapper) handler).setHandler(server.getHandler());
                        server.setHandler(handler);
                    }
                } else {
                    HandlerCollection handlerCollection = new HandlerCollection();
                    handlerCollection.addHandler(server.getHandler());
                    handlerCollection.addHandler(handler);
                    server.setHandler(handlerCollection);
                }
            }
        }
    }

    protected boolean isHandlerInChain(Handler current, Handler handler) {

        if (handler.equals(current)) {
            //Found a match in the chain
            return true;
        } else if (current instanceof HandlerWrapper) {
            //Inspect the next handler in the chain
            return isHandlerInChain(((HandlerWrapper) current).getHandler(), handler);
        } else {
            //End of chain
            return false;
        }
    }

    protected Server createServer() {
        Server s = null;
        ThreadPool tp = threadPool;
        QueuedThreadPool qtp = null;
        // configure thread pool if min/max given
        if (minThreads != null || maxThreads != null) {
            if (getThreadPool() != null) {
                throw new IllegalArgumentException("You cannot configure both minThreads/maxThreads and a custom threadPool on JettyHttpComponent: " + this);
            }
            qtp = new QueuedThreadPool();
            if (minThreads != null) {
                qtp.setMinThreads(minThreads.intValue());
            }
            if (maxThreads != null) {
                qtp.setMaxThreads(maxThreads.intValue());
            }
            tp = qtp;
        }
        if (tp != null) {
            try {
                if (!Server.getVersion().startsWith("8")) {
                    s = Server.class.getConstructor(ThreadPool.class).newInstance(tp);

                } else {
                    s = new Server();
                    if (isEnableJmx()) {
                        enableJmx(s);
                    }
                    Server.class.getMethod("setThreadPool", ThreadPool.class).invoke(s, tp);
                }
            } catch (Exception e) {
                //ignore
            }
        }
        if (s == null) {
            s = new Server();
        }
        if (qtp != null) {
            // let the thread names indicate they are from the server
            qtp.setName("CamelJettyServer(" + ObjectHelper.getIdentityHashCode(s) + ")");
            try {
                qtp.start();
            } catch (Exception e) {
                throw new RuntimeCamelException("Error starting JettyServer thread pool: " + qtp, e);
            }
        }
        ContextHandlerCollection collection = new ContextHandlerCollection();
        s.setHandler(collection);
        // setup the error handler if it set to Jetty component
        if (getErrorHandler() != null) {
            s.addBean(getErrorHandler());
        } else if (!Server.getVersion().startsWith("8")) {
            //need an error handler that won't leak information about the exception
            //back to the client.
            ErrorHandler eh = new ErrorHandler() {
                public void handle(String target, Request baseRequest,
                                   HttpServletRequest request, HttpServletResponse response)
                    throws IOException {
                    String msg = HttpStatus.getMessage(response.getStatus());
                    request.setAttribute(RequestDispatcher.ERROR_MESSAGE, msg);
                    if (response instanceof Response) {
                        //need to use the deprecated method to support compiling with Jetty 8
                        ((Response)response).setStatus(response.getStatus(), msg);
                    }
                    super.handle(target, baseRequest, request, response);
                }
                protected void writeErrorPage(HttpServletRequest request, Writer writer, int code,
                                              String message, boolean showStacks)
                    throws IOException {
                    super.writeErrorPage(request, writer, code, message, false);
                }
            };
            s.addBean(eh, false);
        }
        return s;
    }


    /**
     * Starts {@link #mbContainer} and registers the container with itself as a managed bean
     * logging an error if there is a problem starting the container.
     * Does nothing if {@link #mbContainer} is {@code null}.
     */
    protected void startMbContainer() {
        if (mbContainer != null
            && Server.getVersion().startsWith("8")) {
            //JETTY8 only
            try {
                boolean b = (Boolean)mbContainer.getClass().getMethod("isStarted").invoke(mbContainer);
                if (b) {
                    mbContainer.getClass().getMethod("start").invoke(mbContainer);
                    // Publish the container itself for consistency with
                    // traditional embedded Jetty configurations.
                    mbContainer.getClass().getMethod("addBean", Object.class).invoke(mbContainer, mbContainer);
                }
            } catch (Throwable e) {
                log.warn("Could not start Jetty MBeanContainer. Jetty JMX extensions will remain disabled.", e);
            }
        }
    }

    @Override
    protected void doStart() throws Exception {
        super.doStart();

        RestConfiguration config = getCamelContext().getRestConfiguration("jetty", true);
        // configure additional options on jetty configuration
        if (config.getComponentProperties() != null && !config.getComponentProperties().isEmpty()) {
            setProperties(this, config.getComponentProperties());
        }

        startMbContainer();
    }

    @Override
    protected void doStop() throws Exception {
        super.doStop();
        if (CONNECTORS.size() > 0) {
            for (String connectorKey : CONNECTORS.keySet()) {
                ConnectorRef connectorRef = CONNECTORS.get(connectorKey);
                if (connectorRef != null && connectorRef.getRefCount() == 0) {
                    connectorRef.server.removeConnector(connectorRef.connector);
                    connectorRef.connector.stop();
                    // Camel controls the lifecycle of these entities so remove the
                    // registered MBeans when Camel is done with the managed objects.
                    removeServerMBean(connectorRef.server);
                    connectorRef.server.stop();
                    //removeServerMBean(connectorRef.connector);
                    CONNECTORS.remove(connectorKey);
                }
            }
        }
        if (mbContainer != null) {
            try {
                //JETTY8
                mbContainer.getClass().getMethod("stop").invoke(mbContainer);
            } catch (Throwable t) {
                //JETTY9
                mbContainer.getClass().getMethod("destroy").invoke(mbContainer);
            }
            mbContainer = null;
        }
    }

    private void addServerMBean(Server server) {
        if (mbContainer == null) {
            return;
        }

        try {
            Object o = getContainer(server);
            o.getClass().getMethod("addEventListener", Container.Listener.class).invoke(o, mbContainer);
            if (Server.getVersion().startsWith("8")) {
                return;
            }
            mbContainer.getClass().getMethod("beanAdded", Container.class, Object.class)
                .invoke(mbContainer, null, server);
        } catch (RuntimeException rex) {
            throw rex;
        } catch (Exception r) {
            throw new RuntimeException(r);
        }
    }
    private void removeServerMBean(Server server) {
        try {
            mbContainer.getClass().getMethod("beanRemoved", Container.class, Object.class)
                .invoke(mbContainer, null, server);
        } catch (RuntimeException rex) {
            throw rex;
        } catch (Exception r) {
            try {
                mbContainer.getClass().getMethod("removeBean", Object.class)
                    .invoke(mbContainer, server);
            } catch (RuntimeException rex) {
                throw rex;
            } catch (Exception r2) {
                throw new RuntimeException(r);
            }
        }
    }
    private static Container getContainer(Object server) {
        if (server instanceof Container) {
            return (Container)server;
        }
        try {
            return (Container)server.getClass().getMethod("getContainer").invoke(server);
        } catch (RuntimeException t) {
            throw t;
        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

}
