/*
 * 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.meecrowave;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static java.util.Comparator.comparing;
import static java.util.Locale.ROOT;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.Writer;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.CDI;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.SessionCookieConfig;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Server;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.startup.Catalina;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.util.StandardSessionIdGenerator;
import org.apache.coyote.http2.Http2Protocol;
import org.apache.meecrowave.api.StartListening;
import org.apache.meecrowave.api.StopListening;
import org.apache.meecrowave.configuration.Configuration;
import org.apache.meecrowave.cxf.ConfigurableBus;
import org.apache.meecrowave.cxf.CxfCdiAutoSetup;
import org.apache.meecrowave.cxf.Cxfs;
import org.apache.meecrowave.io.IO;
import org.apache.meecrowave.lang.Substitutor;
import org.apache.meecrowave.logging.jul.Log4j2Logger;
import org.apache.meecrowave.logging.log4j2.Log4j2Shutdown;
import org.apache.meecrowave.logging.log4j2.Log4j2s;
import org.apache.meecrowave.logging.openwebbeans.Log4j2LoggerFactory;
import org.apache.meecrowave.logging.tomcat.Log4j2Log;
import org.apache.meecrowave.logging.tomcat.LogFacade;
import org.apache.meecrowave.openwebbeans.OWBAutoSetup;
import org.apache.meecrowave.service.Priotities;
import org.apache.meecrowave.service.ValueTransformer;
import org.apache.meecrowave.tomcat.CDIInstanceManager;
import org.apache.meecrowave.tomcat.LoggingAccessLogPattern;
import org.apache.meecrowave.tomcat.MeecrowaveContextConfig;
import org.apache.meecrowave.tomcat.OWBJarScanner;
import org.apache.meecrowave.tomcat.ProvidedLoader;
import org.apache.meecrowave.tomcat.TomcatAutoInitializer;
import org.apache.tomcat.JarScanFilter;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.xbean.finder.ResourceFinder;
import org.apache.xbean.recipe.ObjectRecipe;
import org.apache.xbean.recipe.Option;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Meecrowave implements AutoCloseable {
    private final Configuration configuration;
    protected ConfigurableBus clientBus;
    protected File base;
    protected final File ownedTempDir;
    protected File workDir;
    protected InternalTomcat tomcat;
    protected volatile Thread hook;

    // we can undeploy webapps with that later
    private final Map<String, Runnable> contexts = new HashMap<>();
    private Runnable postTask;
    private boolean clearCatalinaSystemProperties;
    private boolean deleteBase;

    public Meecrowave() {
        this(new Builder());
    }

    public Meecrowave(final Configuration configuration) {
        this.configuration = configuration;
        this.ownedTempDir = new File(this.configuration.getTempDir(), "meecrowave_" + System.nanoTime());
    }

    public Builder getConfiguration() {
        return Builder.class.isInstance(configuration) ?
                Builder.class.cast(configuration) :
                new Builder(configuration);
    }

    public File getBase() {
        return base;
    }

    public Tomcat getTomcat() {
        return tomcat;
    }

    public boolean isServing() {
        return tomcat != null && tomcat.getHost().getState() == LifecycleState.STARTED;
    }

    public void undeploy(final String root) {
        ofNullable(this.contexts.remove(root)).ifPresent(Runnable::run);
    }

    public Meecrowave deployClasspath(final DeploymentMeta meta) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        final ClassLoader parentLoader = tomcat.getServer().getParentClassLoader();
        if (parentLoader.getParent() == classLoader) {
            classLoader = parentLoader;
        }

        final ProvidedLoader loader = new ProvidedLoader(classLoader, configuration.isTomcatWrapLoader());
        final Consumer<Context> builtInCustomizer = c -> c.setLoader(loader);
        return deployWebapp(new DeploymentMeta(meta.context, meta.docBase, ofNullable(meta.consumer).map(c -> (Consumer<Context>) ctx -> {
            builtInCustomizer.accept(ctx);
            c.accept(ctx);
        }).orElse(builtInCustomizer)));
    }

    // shortcut
    public Meecrowave deployClasspath() {
        return deployClasspath("");
    }

    // shortcut
    public Meecrowave bake(final Consumer<Context> customizer) {
        start();
        return deployClasspath(new DeploymentMeta("", null, customizer));
    }

    // shortcut (used by plugins)
    public Meecrowave deployClasspath(final String context) {
        return deployClasspath(new DeploymentMeta(context, null, null));
    }

    // shortcut
    public Meecrowave deployWebapp(final File warOrDir) {
        return deployWebapp("", warOrDir);
    }

    // shortcut (used by plugins)
    public Meecrowave deployWebapp(final String context, final File warOrDir) {
        return deployWebapp(new DeploymentMeta(context, warOrDir, null));
    }

    public Meecrowave deployWebapp(final DeploymentMeta meta) {
        if (contexts.containsKey(meta.context)) {
            throw new IllegalArgumentException("Already deployed: '" + meta.context + "'");
        }
        // always nice to see the deployment with something else than internals
        final String base = tomcat.getService().findConnectors().length > 0 ?
                (configuration.getActiveProtocol() + "://" + tomcat.getHost().getName() + ':' + configuration.getActivePort()) : "";
        new LogFacade(Meecrowave.class.getName()).info("--------------- " + base + meta.context);


        final OWBJarScanner scanner = new OWBJarScanner();
        final StandardContext ctx = new StandardContext() {
            @Override
            public void setApplicationEventListeners(final Object[] listeners) {
                if (listeners == null) {
                    super.setApplicationEventListeners(null);
                    return;
                }

                // ensure owb is first and cxf is last otherwise surprises,
                // if we don't -> no @RequestScoped in request listeners :(
                for (int i = 1; i < listeners.length; i++) {
                    if (OWBAutoSetup.EagerBootListener.class.isInstance(listeners[i])) {
                        final Object first = listeners[0];
                        listeners[0] = listeners[i];
                        listeners[i] = first;
                        break;
                    }
                }

                // and finally let it go after our re-ordering
                super.setApplicationEventListeners(listeners);
            }
        };
        ctx.setPath(meta.context);
        ctx.setName(meta.context);
        ctx.setJarScanner(scanner);
        ctx.setInstanceManager(new CDIInstanceManager());
        ofNullable(meta.docBase).ifPresent(d -> {
            try {
                ctx.setDocBase(meta.docBase.getCanonicalPath());
            } catch (final IOException e) {
                ctx.setDocBase(meta.docBase.getAbsolutePath());
            }
        });
        ofNullable(configuration.getTomcatFilter()).ifPresent(filter -> {
            try {
                scanner.setJarScanFilter(JarScanFilter.class.cast(Thread.currentThread().getContextClassLoader().loadClass(filter).newInstance()));
            } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                throw new IllegalArgumentException(e);
            }
        });

        final AtomicReference<Runnable> releaseSCI = new AtomicReference<>();
        final ServletContainerInitializer meecrowaveInitializer = (c, ctx1) -> {
            ctx1.setAttribute("meecrowave.configuration", getConfiguration());
            ctx1.setAttribute("meecrowave.instance", Meecrowave.this);

            new OWBAutoSetup().onStartup(c, ctx1);
            if (Cxfs.IS_PRESENT) {
                new CxfCdiAutoSetup().onStartup(c, ctx1);
            }
            new TomcatAutoInitializer().onStartup(c, ctx1);

            if (configuration.isInjectServletContainerInitializer()) {
                final Field f;
                try { // now cdi is on, we can inject cdi beans in ServletContainerInitializer
                    f = StandardContext.class.getDeclaredField("initializers");
                    if (!f.isAccessible()) {
                        f.setAccessible(true);
                    }
                } catch (final Exception e) {
                    throw new IllegalStateException("Bad tomcat version", e);
                }

                final List<AutoCloseable> cc;
                try {
                    cc = ((Map<ServletContainerInitializer, Set<Class<?>>>) f.get(ctx)).keySet().stream()
                            .filter(i -> !i.getClass().getName().startsWith(Meecrowave.class.getName()))
                            .map(i -> {
                                try {
                                    return this.inject(i);
                                } catch (final IllegalArgumentException iae) {
                                    return null;
                                }
                            })
                            .filter(Objects::nonNull)
                            .collect(toList());
                } catch (final IllegalAccessException e) {
                    throw new IllegalStateException("Can't read initializers", e);
                }
                releaseSCI.set(() -> cc.forEach(closeable -> {
                    try {
                        closeable.close();
                    } catch (final Exception e) {
                        throw new IllegalStateException(e);
                    }
                }));
            }
        };

        ctx.addLifecycleListener(new MeecrowaveContextConfig(configuration, meta.docBase != null, meecrowaveInitializer));
        ctx.addLifecycleListener(event -> {
            switch (event.getType()) {
                case Lifecycle.BEFORE_START_EVENT:
                    if (configuration.getWebSessionCookieConfig() != null) {
                        final Properties p = new Properties();
                        try {
                            p.load(new StringReader(configuration.getWebSessionCookieConfig()));
                        } catch (final IOException e) {
                            throw new IllegalArgumentException(e);
                        }
                        if (p.containsKey("domain")) {
                            ctx.setSessionCookieDomain(p.getProperty("domain"));
                        }
                        if (p.containsKey("path")) {
                            ctx.setSessionCookiePath(p.getProperty("path"));
                        }
                        if (p.containsKey("name")) {
                            ctx.setSessionCookieName(p.getProperty("name"));
                        }
                        if (p.containsKey("use-trailing-slash")) {
                            ctx.setSessionCookiePathUsesTrailingSlash(Boolean.parseBoolean(p.getProperty("use-trailing-slash")));
                        }
                        if (p.containsKey("http-only")) {
                            ctx.setUseHttpOnly(Boolean.parseBoolean(p.getProperty("http-only")));
                        }
                        if (p.containsKey("secured")) {
                            final SessionCookieConfig sessionCookieConfig = ctx.getServletContext().getSessionCookieConfig();
                            sessionCookieConfig.setSecure(Boolean.parseBoolean(p.getProperty("secured")));
                        }
                    }
                    break;
                case Lifecycle.AFTER_START_EVENT:
                    ctx.getResources().setCachingAllowed(configuration.isWebResourceCached());
                    break;
                case Lifecycle.BEFORE_INIT_EVENT:
                    if (configuration.getLoginConfig() != null) {
                        ctx.setLoginConfig(configuration.getLoginConfig().build());
                    }
                    for (final SecurityConstaintBuilder sc : configuration.getSecurityConstraints()) {
                        ctx.addConstraint(sc.build());
                    }
                    if (configuration.getWebXml() != null) {
                        ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.getWebXml());
                    }
                    break;
                default:
            }

        });
        ctx.addLifecycleListener(new Tomcat.FixContextListener()); // after having configured the security!!!

        ctx.addServletContainerInitializer(meecrowaveInitializer, emptySet());

        if (configuration.isUseTomcatDefaults()) {
            ctx.setSessionTimeout(configuration.getWebSessionTimeout() != null ? configuration.getWebSessionTimeout() : 30);
            ctx.addWelcomeFile("index.html");
            ctx.addWelcomeFile("index.htm");
            Tomcat.addDefaultMimeTypeMappings(ctx);
        } else if (configuration.getWebSessionTimeout() != null) {
            ctx.setSessionTimeout(configuration.getWebSessionTimeout());
        }

        ofNullable(meta.consumer).ifPresent(c -> c.accept(ctx));
        if (configuration.isQuickSession() && ctx.getManager() == null) {
            final StandardManager manager = new StandardManager();
            manager.setSessionIdGenerator(new StandardSessionIdGenerator() {
                @Override
                protected void getRandomBytes(final byte bytes[]) {
                    ThreadLocalRandom.current().nextBytes(bytes);
                }

                @Override
                public String toString() {
                    return "MeecrowaveSessionIdGenerator@" + System.identityHashCode(this);
                }
            });
            ctx.setManager(manager);
        }
        if (configuration.isAntiResourceLocking() && StandardContext.class.isInstance(ctx)) {
            StandardContext.class.cast(ctx).setAntiResourceLocking(true);
        }
        configuration.getInitializers().forEach(i -> ctx.addServletContainerInitializer(i, emptySet()));
        configuration.getGlobalContextConfigurers().forEach(it -> it.accept(ctx));

        final Host host = tomcat.getHost();
        host.addChild(ctx);

        final ClassLoader classLoader = ctx.getLoader().getClassLoader();
        if (host.getState().isAvailable()) {
            fire(new StartListening(findFirstConnector(), host, ctx), classLoader);
        }
        contexts.put(meta.context, () -> {
            if (host.getState().isAvailable()) {
                fire(new StopListening(findFirstConnector(), host, ctx), classLoader);
            }
            ofNullable(releaseSCI.get()).ifPresent(Runnable::run);
            tomcat.getHost().removeChild(ctx);
        });
        return this;
    }

    public Meecrowave bake() {
        return bake("");
    }

    public Meecrowave bake(final String ctx) {
        start();
        return deployClasspath(ctx);
    }

    public Meecrowave start() {
        final Map<String, String> systemPropsToRestore = new HashMap<>();

        if (configuration.getMeecrowaveProperties() != null && !"meecrowave.properties".equals(configuration.getMeecrowaveProperties())) {
            configuration.loadFrom(configuration.getMeecrowaveProperties());
        }

        if (configuration.isUseLog4j2JulLogManager() && Log4j2s.IS_PRESENT) { // /!\ don't move this line or add anything before without checking log setup
            System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
        }

        if (configuration.isLoggingGlobalSetup() && Log4j2s.IS_PRESENT) {

            setSystemProperty(systemPropsToRestore, "log4j.shutdownHookEnabled", "false");
            setSystemProperty(systemPropsToRestore, "openwebbeans.logging.factory", Log4j2LoggerFactory.class.getName());
            setSystemProperty(systemPropsToRestore, "org.apache.cxf.Logger", Log4j2Logger.class.getName());
            setSystemProperty(systemPropsToRestore, "org.apache.tomcat.Logger", Log4j2Log.class.getName());

            postTask = () -> {
                if (Log4j2s.IS_PRESENT) {
                    new Log4j2Shutdown().shutdown();
                }
                systemPropsToRestore.forEach((key, value) -> {
                    if (value == null) {
                        System.clearProperty(key);
                    } else {
                        System.setProperty(key, value);
                    }
                });
            };
        }

        setupJmx(configuration.isTomcatNoJmx());

        clearCatalinaSystemProperties = System.getProperty("catalina.base") == null && System.getProperty("catalina.home") == null;

        tomcat = new InternalTomcat();

        { // setup
            base = new File(newBaseDir());

            // create the temp dir folder.
            File tempDir;
            if (configuration.getTempDir() == null || configuration.getTempDir().length() == 0) {
                tempDir = createDirectory(base, "temp");
            } else {
                tempDir = new File(configuration.getTempDir());
                if (!tempDir.exists()) {
                    tempDir.mkdirs();
                }
            }

            try {
                workDir = createDirectory(base, "work");
            } catch (final IllegalStateException ise) {
                // in case we could not create that directory we create it in the temp dir folder
                workDir = createDirectory(tempDir, "work");
            }

            synchronize(new File(base, "conf"), configuration.getConf());
        }

        final Properties props = configuration.getProperties();
        Substitutor substitutor = null;
        for (final String s : props.stringPropertyNames()) {
            final String v = props.getProperty(s);
            if (v != null && v.contains("${")) {
                if (substitutor == null) {
                    final Map<String, String> placeHolders = new HashMap<>();
                    placeHolders.put("meecrowave.embedded.http", Integer.toString(configuration.getHttpPort()));
                    placeHolders.put("meecrowave.embedded.https", Integer.toString(configuration.getHttpsPort()));
                    placeHolders.put("meecrowave.embedded.stop", Integer.toString(configuration.getStopPort()));
                    substitutor = new Substitutor(placeHolders);
                }
                props.put(s, substitutor.replace(v));
            }
        }

        final File conf = new File(base, "conf");

        tomcat.setBaseDir(base.getAbsolutePath());
        tomcat.setHostname(configuration.getHost());

        final boolean initialized;
        if (configuration.getServerXml() != null) {
            final File file = new File(conf, "server.xml");
            if (!file.equals(configuration.getServerXml())) {
                try (final InputStream is = new FileInputStream(configuration.getServerXml());
                     final FileOutputStream fos = new FileOutputStream(file)) {
                    IO.copy(is, fos);
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
            }

            // respect config (host/port) of the Configuration
            final QuickServerXmlParser ports = QuickServerXmlParser.parse(file);
            if (configuration.isKeepServerXmlAsThis()) {
                configuration.setHttpPort(Integer.parseInt(ports.http()));
                configuration.setStopPort(Integer.parseInt(ports.stop()));
            } else {
                final Map<String, String> replacements = new HashMap<>();
                replacements.put(ports.http(), String.valueOf(configuration.getHttpPort()));
                replacements.put(ports.https(), String.valueOf(configuration.getHttpsPort()));
                replacements.put(ports.stop(), String.valueOf(configuration.getStopPort()));

                String serverXmlContent;
                try (final InputStream stream = new FileInputStream(file)) {
                    serverXmlContent = IO.toString(stream);
                    for (final Map.Entry<String, String> pair : replacements.entrySet()) {
                        serverXmlContent = serverXmlContent.replace(pair.getKey(), pair.getValue());
                    }
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
                try (final OutputStream os = new FileOutputStream(file)) {
                    os.write(serverXmlContent.getBytes(StandardCharsets.UTF_8));
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
            }

            tomcat.server(createServer(file.getAbsolutePath()));
            initialized = true;
        } else {
            tomcat.getServer().setPort(configuration.getStopPort());
            initialized = false;
        }

        ofNullable(configuration.getSharedLibraries()).map(File::new).filter(File::isDirectory).ifPresent(libRoot -> {
            final Collection<URL> libs = new ArrayList<>();
            try {
                libs.add(libRoot.toURI().toURL());
            } catch (final MalformedURLException e) {
                throw new IllegalStateException(e);
            }
            libs.addAll(ofNullable(libRoot.listFiles((dir, name) -> name.endsWith(".jar") || name.endsWith(".zip")))
                    .map(Stream::of).map(s -> s.map(f -> {
                        try {
                            return f.toURI().toURL();
                        } catch (final MalformedURLException e) {
                            throw new IllegalStateException(e);
                        }
                    }).collect(toList()))
                    .orElse(emptyList()));
            tomcat.getServer().setParentClassLoader(new MeecrowaveContainerLoader(libs.toArray(new URL[libs.size()]), Thread.currentThread().getContextClassLoader()));
        });

        if (!initialized) {
            tomcat.setHostname(configuration.getHost());
            tomcat.getEngine().setDefaultHost(configuration.getHost());
            final StandardHost host = new StandardHost();
            host.setName(configuration.getHost());

            try {
                final File webapps = createDirectory(base, "webapps");
                host.setAppBase(webapps.getAbsolutePath());
            } catch (final IllegalStateException ise) {
                // never an issue since the webapps are deployed being put in webapps - so no dynamic folder
                // or through their path - so don't need webapps folder
            }

            host.setUnpackWARs(true); // forced for now cause OWB doesn't support war:file:// urls
            try {
                host.setWorkDir(workDir.getCanonicalPath());
            } catch (final IOException e) {
                host.setWorkDir(workDir.getAbsolutePath());
            }
            tomcat.setHost(host);
        }

        ofNullable(configuration.getTomcatAccessLogPattern())
                .ifPresent(pattern -> tomcat.getHost().getPipeline().addValve(new LoggingAccessLogPattern(pattern)));
        final List<Valve> valves = buildValves();
        if (!valves.isEmpty()) {
            final Pipeline pipeline = tomcat.getHost().getPipeline();
            valves.forEach(pipeline::addValve);
        }

        if (configuration.getRealm() != null) {
            tomcat.getEngine().setRealm(configuration.getRealm());
        }

        if (tomcat.getRawConnector() == null && !configuration.isSkipHttp()) {
            final Connector connector = createConnector();
            connector.setPort(configuration.getHttpPort());
            if (connector.getAttribute("connectionTimeout") == null) {
                connector.setAttribute("connectionTimeout", "3000");
            }

            tomcat.getService().addConnector(connector);
            tomcat.setConnector(connector);
        }

        // create https connector
        if (configuration.isSsl()) {
            final Connector httpsConnector = createConnector();
            httpsConnector.setPort(configuration.getHttpsPort());
            httpsConnector.setSecure(true);
            httpsConnector.setScheme("https");
            httpsConnector.setProperty("SSLEnabled", "true");
            if (configuration.getSslProtocol() != null) {
                configuration.getProperties().setProperty("connector.sslhostconfig.sslProtocol", configuration.getSslProtocol());
            }
            if (configuration.getProperties().getProperty("connector.sslhostconfig.hostName") != null) {
                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.getProperties().getProperty("connector.sslhostconfig.hostName"));
            }
            if (configuration.getKeystoreFile() != null) {
                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystoreFile", configuration.getKeystoreFile());
            }
            if (configuration.getKeystorePass() != null) {
                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystorePassword", configuration.getKeystorePass());
            }
            configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeystoreType", configuration.getKeystoreType());
            if (configuration.getClientAuth() != null) {
                httpsConnector.setAttribute("clientAuth", configuration.getClientAuth());
            }

            if (configuration.getKeyAlias() != null) {
                configuration.getProperties().setProperty("connector.sslhostconfig.certificateKeyAlias", configuration.getKeyAlias());
            }
            if (configuration.isHttp2()) {
                httpsConnector.addUpgradeProtocol(new Http2Protocol());
            }
            final List<SSLHostConfig> buildSslHostConfig = buildSslHostConfig();
            if (!buildSslHostConfig.isEmpty()) {
                createDirectory(base, "conf");
            }
            buildSslHostConfig.forEach(sslHostConf -> {
                if (isCertificateFromClasspath(sslHostConf.getCertificateKeystoreFile())) {
                    copyCertificateToConfDir(sslHostConf.getCertificateKeystoreFile());
                    sslHostConf.setCertificateKeystoreFile(base.getAbsolutePath() + "/conf/" + sslHostConf.getCertificateKeystoreFile());
                }
                if (isCertificateFromClasspath(sslHostConf.getCertificateKeyFile())) {
                    copyCertificateToConfDir(sslHostConf.getCertificateKeyFile());
                    sslHostConf.setCertificateKeyFile(base.getAbsolutePath() + "/conf/" + sslHostConf.getCertificateKeyFile());
                    copyCertificateToConfDir(sslHostConf.getCertificateFile());
                    sslHostConf.setCertificateFile(base.getAbsolutePath() + "/conf/" + sslHostConf.getCertificateFile());
                }
                if (isCertificateFromClasspath(sslHostConf.getTruststoreFile())) {
                    copyCertificateToConfDir(sslHostConf.getTruststoreFile());
                    sslHostConf.setTruststoreFile(base.getAbsolutePath() + "/conf/" + sslHostConf.getTruststoreFile());
                }
                if (isCertificateFromClasspath(sslHostConf.getCertificateChainFile())) {
                    copyCertificateToConfDir(sslHostConf.getCertificateChainFile());
                    sslHostConf.setCertificateChainFile(base.getAbsolutePath() + "/conf/" + sslHostConf.getCertificateChainFile());
                }
            });

            buildSslHostConfig.forEach(httpsConnector::addSslHostConfig);

            if (configuration.getDefaultSSLHostConfigName() != null) {
                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.getDefaultSSLHostConfigName());
            }
            tomcat.getService().addConnector(httpsConnector);
            if (configuration.isSkipHttp()) {
                tomcat.setConnector(httpsConnector);
            }
        }

        for (final Connector c : configuration.getConnectors()) {
            tomcat.getService().addConnector(c);
        }
        if (!configuration.isSkipHttp() && !configuration.isSsl() && !configuration.getConnectors().isEmpty()) {
            tomcat.setConnector(configuration.getConnectors().iterator().next());
        }

        if (configuration.getUsers() != null) {
            for (final Map.Entry<String, String> user : configuration.getUsers().entrySet()) {
                tomcat.addUser(user.getKey(), user.getValue());
            }
        }
        if (configuration.getRoles() != null) {
            for (final Map.Entry<String, String> user : configuration.getRoles().entrySet()) {
                for (final String role : user.getValue().split(" *, *")) {
                    tomcat.addRole(user.getKey(), role);
                }
            }
        }

        StreamSupport.stream(ServiceLoader.load(Meecrowave.InstanceCustomizer.class).spliterator(), false)
                .peek(i -> {
                    if (MeecrowaveAwareInstanceCustomizer.class.isInstance(i)) {
                        MeecrowaveAwareInstanceCustomizer.class.cast(i).setMeecrowave(this);
                    }
                })
                .sorted(Priotities::sortByPriority)
                .forEach(c -> c.accept(tomcat));
        configuration.getInstanceCustomizers().forEach(c -> c.accept(tomcat));

        StreamSupport.stream(ServiceLoader.load(Meecrowave.ContextCustomizer.class).spliterator(), false)
                .peek(i -> {
                    if (MeecrowaveAwareContextCustomizer.class.isInstance(i)) {
                        MeecrowaveAwareContextCustomizer.class.cast(i).setMeecrowave(this);
                    }
                })
                .sorted(Priotities::sortByPriority)
                .forEach(configuration::addGlobalContextCustomizer);

        beforeStart();


        if (configuration.isInitializeClientBus() && Cxfs.IS_PRESENT && !Cxfs.hasDefaultBus()) {
            clientBus = new ConfigurableBus();
            clientBus.initProviders(configuration,
                    ofNullable(Thread.currentThread().getContextClassLoader()).orElseGet(ClassLoader::getSystemClassLoader));
            clientBus.addClientLifecycleListener();
        }

        try {
            if (!initialized) {
                tomcat.init();
            }

            tomcat.getHost().addLifecycleListener(event -> {
                if (!Host.class.isInstance(event.getSource())) {
                    return;
                }
                broadcastHostEvent(event.getType(), Host.class.cast(event.getSource()));
            });

            tomcat.start();
        } catch (final LifecycleException e) {
            throw new IllegalStateException(e);
        }
        ofNullable(configuration.getPidFile()).ifPresent(pidFile -> {
            if (pidFile.getParentFile() != null && !pidFile.getParentFile().isDirectory() && !pidFile.getParentFile().mkdirs()) {
                throw new IllegalArgumentException("Can't create " + pidFile);
            }
            final String pid = ManagementFactory.getRuntimeMXBean().getName();
            final int at = pid.indexOf('@');
            try (final Writer w = new FileWriter(pidFile)) {
                w.write(at > 0 ? pid.substring(0, at) : pid);
            } catch (final IOException e) {
                throw new IllegalStateException("Can't write the pid in " + pid, e);
            }
        });
        if (configuration.isUseShutdownHook()) {
            hook = new Thread(() -> {
                hook = null; // prevent close to remove the hook which would throw an exception
                close();
            }, "meecrowave-stop-hook");
            Runtime.getRuntime().addShutdownHook(hook);
        }
        return this;
    }

    private boolean isCertificateFromClasspath(final String certificate) {
        final BiPredicate<String, String> equals = System.getProperty("os.name", "ignore").toLowerCase(ROOT).contains("win") ?
                String::equalsIgnoreCase : String::equals;
        return certificate != null && !(new File(certificate).exists())
                && !equals.test(
                        Paths.get(System.getProperty("user.home")).resolve(".keystore").toAbsolutePath().normalize().toString(),
                        Paths.get(certificate).toAbsolutePath().normalize().toString());
    }

    private void copyCertificateToConfDir(String certificate) {
        InputStream resourceAsStream = null;
        try {
            final Path dstFile = Paths.get(base.getAbsolutePath() + "/conf/" + certificate);
            resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(certificate);
            if (resourceAsStream == null) {
                resourceAsStream = new FileInputStream(new File((this.getClass().getResource("/").toString().replaceAll("file:", "") + "/" + certificate)));
            }
            Files.copy(resourceAsStream, dstFile, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        } finally {
            if (resourceAsStream != null) {
                try {
                    resourceAsStream.close();
                } catch (IOException e) {
                    throw new IllegalStateException(e);
                }
            }
        }
    }

    public ConfigurableBus getClientBus() {
        return clientBus;
    }

    /**
     * Store away the current system property for restoring it later
     * during shutdown.
     * @param backupPropertyMap a Map to store away the previous value before setting the newValue
     * @param propertyKey
     * @param newValue
     */
    private void setSystemProperty(Map<String, String> backupPropertyMap, String propertyKey, String newValue) {
        backupPropertyMap.put(propertyKey, System.getProperty(propertyKey));

        System.setProperty(propertyKey, newValue);
    }

    private void broadcastHostEvent(final String event, final Host host) {
        switch (event) {
            case Lifecycle.AFTER_START_EVENT: {
                final Connector connector = findFirstConnector();
                findContexts(host).forEach(ctx -> fire(new StartListening(connector, host, ctx), ctx.getLoader().getClassLoader()));
                break;
            }
            case Lifecycle.BEFORE_STOP_EVENT: {
                final Connector connector = findFirstConnector();
                findContexts(host).forEach(ctx -> fire(new StopListening(connector, host, ctx), ctx.getLoader().getClassLoader()));
                break;
            }
            default:
        }
    }

    private Connector findFirstConnector() {
        return Stream.of(tomcat.getServer().findServices())
                .flatMap(s -> Stream.of(s.findConnectors()))
                .findFirst()
                .orElse(null);
    }

    private Stream<Context> findContexts(final Host host) {
        return Stream.of(host.findChildren())
                .filter(Context.class::isInstance)
                .map(Context.class::cast)
                .filter(ctx -> ctx.getState().isAvailable());
    }

    private <T> void fire(final T event, final ClassLoader classLoader) {
        final Thread thread = Thread.currentThread();
        final ClassLoader loader = thread.getContextClassLoader();
        thread.setContextClassLoader(classLoader);
        try {
            WebBeansContext.currentInstance()
                    .getBeanManagerImpl()
                    .getEvent()
                    .select(Class.class.cast(event.getClass()))
                    .fire(event);
        } finally {
            thread.setContextClassLoader(loader);
        }
    }

    private void setupJmx(final boolean skip) {
        if (skip) {
            Registry.disableRegistry();
        }
    }

    /**
     * Syntax uses:
     * <code>
     *     valves.myValve1._className = org.apache.meecrowave.tomcat.LoggingAccessLogPattern
     *     valves.myValve1._order = 0
     *
     *     valves.myValve1._className = SSOVa
     *     valves.myValve1._order = 1
     *     valves.myValve1.showReportInfo = false
     * </code>
     *
     * @return the list of valve from the properties.
     */
    private List<Valve> buildValves() {
        final List<Valve> valves = new ArrayList<>();
        configuration.getProperties().stringPropertyNames().stream()
                                .filter(key -> key.startsWith("valves.") && key.endsWith("._className"))
                                .sorted(comparing(key -> Integer.parseInt(configuration.getProperties()
                                        .getProperty(key.replaceFirst("\\._className$", "._order"), "0"))))
                                .map(key -> key.split("\\."))
                                .filter(parts -> parts.length == 3)
                                .forEach(key -> {
            final String prefix = key[0] + '.' + key[1] + '.';
            final ObjectRecipe recipe = newRecipe(configuration.getProperties().getProperty(prefix + key[2]));
            configuration.getProperties().stringPropertyNames().stream()
                    .filter(it -> it.startsWith(prefix) && !it.endsWith("._order") && !it.endsWith("._className"))
                    .forEach(propKey -> {
                        final String value = configuration.getProperties().getProperty(propKey);
                        recipe.setProperty(propKey.substring(prefix.length()), value);
                    });
            valves.add(Valve.class.cast(recipe.create(Thread.currentThread().getContextClassLoader())));
        });
        return valves;
    }

    private List<SSLHostConfig> buildSslHostConfig() {
        final List<SSLHostConfig> sslHostConfigs = new ArrayList<>();
        // Configures default SSLHostConfig
        final ObjectRecipe defaultSslHostConfig = newRecipe(SSLHostConfig.class.getName());
        for (final String key : configuration.getProperties().stringPropertyNames()) {
            if (key.startsWith("connector.sslhostconfig.") && key.split("\\.").length == 3) {
                final String substring = key.substring("connector.sslhostconfig.".length());
                defaultSslHostConfig.setProperty(substring, configuration.getProperties().getProperty(key));
            }
        }
        if (!defaultSslHostConfig.getProperties().isEmpty()) {
            sslHostConfigs.add(SSLHostConfig.class.cast(defaultSslHostConfig.create()));
        }
        // Allows to add N Multiple SSLHostConfig elements not including the default one.
        final Collection<Integer> itemNumbers = configuration.getProperties().stringPropertyNames()
                                .stream()
                                .filter(key -> (key.startsWith("connector.sslhostconfig.") && key.split("\\.").length == 4))
                                .map(key -> Integer.parseInt(key.split("\\.")[2]))
                                .collect(toSet());
        itemNumbers.stream().sorted().forEach(itemNumber -> {
            final ObjectRecipe recipe = newRecipe(SSLHostConfig.class.getName());
            final String prefix = "connector.sslhostconfig." + itemNumber + '.';
            configuration.getProperties().stringPropertyNames().stream()
                                    .filter(k -> k.startsWith(prefix))
                                    .forEach(key -> {
                                        final String keyName = key.split("\\.")[3];
                                        recipe.setProperty(keyName, configuration.getProperties().getProperty(key));
                                    });
            if (!recipe.getProperties().isEmpty()) {
                final SSLHostConfig sslHostConfig = SSLHostConfig.class.cast(recipe.create());
                sslHostConfigs.add(sslHostConfig);
                new LogFacade(Meecrowave.class.getName())
                        .info("Created SSLHostConfig #" + itemNumber + " (" + sslHostConfig.getHostName() + ")");
            }
        });
        return sslHostConfigs;
    }

    protected void beforeStart() {
        // no-op
    }

    protected void beforeStop() {
        // no-op
    }

    public <T> AutoCloseable inject(final T instance) {
        final BeanManager bm = CDI.current().getBeanManager();
        final AnnotatedType<?> annotatedType = bm.createAnnotatedType(instance.getClass());
        final InjectionTarget injectionTarget = bm.createInjectionTarget(annotatedType);
        final CreationalContext<Object> creationalContext = bm.createCreationalContext(null);
        injectionTarget.inject(instance, creationalContext);
        return creationalContext::release;
    }

    @Override
    public synchronized void close() {
        if (tomcat == null) {
            return;
        }
        if (hook != null) {
            Runtime.getRuntime().removeShutdownHook(hook);
            this.hook = null;
        }
        beforeStop();
        if (MeecrowaveContainerLoader.class.isInstance(tomcat.getServer().getParentClassLoader())) {
            try {
                MeecrowaveContainerLoader.class.cast(tomcat.getServer().getParentClassLoader()).close();
            } catch (final IOException e) {
                new LogFacade(Meecrowave.class.getName()).error(e.getMessage(), e);
            }
        }
        try {
            contexts.values().forEach(Runnable::run);
        } finally {
            try {
                tomcat.stop();
                tomcat.destroy();
            } catch (final LifecycleException e) {
                throw new IllegalStateException(e);
            } finally {
                Cxfs.resetDefaultBusIfEquals(clientBus); // after if runnables or listeners trigger CXF
                tomcat = null; // ensure we can call close() N times and not have side effects
                contexts.clear();
                if (clearCatalinaSystemProperties) {
                    Stream.of("catalina.base", "catalina.home").forEach(System::clearProperty);
                }
                if (configuration.isUseLog4j2JulLogManager()) {
                    System.clearProperty("java.util.logging.manager");
                }
                ofNullable(postTask).ifPresent(Runnable::run);
                postTask = null;
                try {
                    if (deleteBase && base != null) {
                        IO.delete(base);
                    }

                    if (ownedTempDir != null) {
                        IO.delete(ownedTempDir);
                    }
                } catch (final IllegalArgumentException /*does not exist from the hook*/ e) {
                    // no-op
                } finally {
                    base = null;

                    // not very important if we can't delete it since next restart will write another value normally
                    ofNullable(configuration.getPidFile()).ifPresent(File::delete);
                }
            }
        }
    }

    protected Connector createConnector() {
        final Connector connector;
        final Properties properties = configuration.getProperties();
        if (properties != null) {
            final Map<String, String> attributes = new HashMap<>();
            final ObjectRecipe recipe = newRecipe(Connector.class.getName());
            for (final String key : properties.stringPropertyNames()) {
                if (!key.startsWith("connector.")) {
                    continue;
                }

                final String substring = key.substring("connector.".length());
                if (substring.startsWith("sslhostconfig.")) {
                    continue;
                }

                if (!substring.startsWith("attributes.")) {
                    recipe.setProperty(substring, properties.getProperty(key));
                } else {
                    attributes.put(substring.substring("attributes.".length()), properties.getProperty(key));
                }
            }
            connector = recipe.getProperties().isEmpty() ? new Connector() : Connector.class.cast(recipe.create());
            for (final Map.Entry<String, String> attr : attributes.entrySet()) {
                connector.setAttribute(attr.getKey(), attr.getValue());
            }
        } else {
            connector = new Connector();
        }
        return connector;
    }

    private static Server createServer(final String serverXml) {
        final Catalina catalina = new Catalina() {
            // skip few init we don't need *here*
            @Override
            protected void initDirs() {
                // no-op
            }

            @Override
            protected void initStreams() {
                // no-op
            }

            @Override
            protected void initNaming() {
                // no-op
            }
        };
        catalina.setConfigFile(serverXml);
        catalina.load();
        return catalina.getServer();
    }

    private File createDirectory(final File parent, final String directory) {
        final File dir = new File(parent, directory);
        IO.mkdirs(dir);
        return dir;
    }

    private void synchronize(final File base, final String resourceBase) {
        if (resourceBase == null) {
            return;
        }

        try {
            final Map<String, URL> urls = new ResourceFinder("").getResourcesMap(resourceBase);
            for (final Map.Entry<String, URL> u : urls.entrySet()) {
                try (final InputStream is = u.getValue().openStream()) {
                    final File to = new File(base, u.getKey());
                    final File parentFile = to.getParentFile();
                    createDirectory(parentFile.getParentFile(), parentFile.getName());
                    try (final OutputStream os = new FileOutputStream(to)) {
                        IO.copy(is, os);
                    }
                    if ("server.xml".equals(u.getKey())) {
                        configuration.setServerXml(to.getAbsolutePath());
                    }
                }
            }
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private String newBaseDir() {
        deleteBase = false;
        String dir = configuration.getDir();
        if (dir != null) {
            final File dirFile = new File(dir);
            if (dirFile.exists()) {
                if (base != null && base.exists() && configuration.isDeleteBaseOnStartup()) {
                    IO.delete(base);
                }
                return dir;
            }
            IO.mkdirs(dirFile);
            return dirFile.getAbsolutePath();
        }

        final String base = System.getProperty("meecrowave.base");
        if (base != null && new File(base).exists()) {
            return new File(base).getAbsolutePath();
        }

        deleteBase = true;
        final List<String> lookupPaths = new ArrayList<>();
        lookupPaths.add("target");
        lookupPaths.add("build");
        final File file = lookupPaths.stream()
                          .map(File::new)
                          .filter(File::isDirectory)
                          .findFirst()
                          .map(file1 -> new File(file1, "meecrowave-" + System.nanoTime())).orElse(ownedTempDir);
        IO.mkdirs(file);
        return file.getAbsolutePath();
    }

    public void await() {
        tomcat.getServer().await();
    }

    private static ObjectRecipe newRecipe(final String clazz) {
        final ObjectRecipe recipe = new ObjectRecipe(clazz);
        recipe.allow(Option.FIELD_INJECTION);
        recipe.allow(Option.PRIVATE_PROPERTIES);
        return recipe;
    }

    // this class holds all the built-in config,
    // extension can use extensions feature (see cli.html) which is basically the same kind of bean
    // accessible through builder.getExtension(type) builder being accessible through the meecrowave.configuration
    // attribute of the ServletContext.
    public static class Builder extends Configuration /* inheritance for backward compatibility */ {
        // IMPORTANT: this must stay without any field, use parent class to add config please
        //            this only holds builder methods

        public Builder() {
            // no-op
        }

        // mainly for backward compat
        public Builder(final Configuration configuration) {
            super(configuration);
        }

        @Override
        public Builder loadFrom(String resource) {
            super.loadFrom(resource);
            return this;
        }

        public Builder excludePackages(final String packages) {
            this.setScanningPackageExcludes(packages);
            return this;
        }

        /**
         * Only scan the very packages given (startsWith).
         * This will exclude <em>all</em> other packages from bean scanning
         */
        public Builder includePackages(final String packages) {
            this.setScanningPackageIncludes(packages);
            this.setScanningPackageExcludes("*");
            return this;
        }

        /**
         * Scan the very packages given (startsWith) <em>in addition</em> to the default rules.
         */
        public Builder withPackages(final String packages) {
            this.setScanningPackageIncludes(packages);
            return this;
        }

        public Builder sharedLibraries(final String sharedLibraries) {
            setSharedLibraries(sharedLibraries);
            return this;
        }

        public Builder securityConstraints(final Meecrowave.SecurityConstaintBuilder securityConstraint) {
            if (getSecurityConstraints() == null) {
                setSecurityConstraints(new ArrayList<>());
            }
            getSecurityConstraints().add(securityConstraint);
            return this;
        }

        public Builder randomHttpPort() {
            try (final ServerSocket serverSocket = new ServerSocket(0)) {
                setHttpPort(serverSocket.getLocalPort());
            } catch (final IOException e) {
                throw new IllegalStateException(e);
            }
            return this;
        }

        public Builder randomHttpsPort() {
            try (final ServerSocket serverSocket = new ServerSocket(0)) {
                setHttpsPort(serverSocket.getLocalPort());
            } catch (final IOException e) {
                throw new IllegalStateException(e);
            }
            return this;
        }

        public Builder property(final String key, final String value) {
            getProperties().setProperty(key, value);
            return this;
        }


        public Builder user(final String name, final String pwd) {
            if (getUsers() == null) {
                setUsers(new HashMap<>());
            }
            getUsers().put(name, pwd);
            return this;
        }

        public Builder role(final String user, final String roles) {
            if (getRoles() == null) {
                setRoles(new HashMap<>());
            }
            getRoles().put(user, roles);
            return this;
        }

        public Builder cxfServletParam(final String key, final String value) {
            if (getCxfServletParams() == null) {
                setCxfServletParams(new HashMap<>());
            }
            getCxfServletParams().put(key, value);
            return this;
        }

        @Deprecated // withers are deprecated, we prefer the no fluent API
        public Builder withJsonpBufferStrategy(final String jsonpBufferStrategy) {
            setJsonpBufferStrategy(jsonpBufferStrategy);
            return this;
        }

        public Builder noShutdownHook() {
            setUseShutdownHook(false);
            return this;
        }

        public Builder instanceCustomizer(final Consumer<Tomcat> customizer) {
            addInstanceCustomizer(customizer);
            return this;
        }

        public Builder pidFile(final Path pidFile) {
            setPidFile(pidFile.toFile());
            return this;
        }

        public Builder watcherBouncing(final int watcherBouncing) {
            setWatcherBouncing(watcherBouncing);
            return this;
        }

        public Builder httpPort(final int httpPort) {
            if (httpPort <= 0) {
                randomHttpPort();
            } else {
                setHttpPort(httpPort);
            }
            return this;
        }

        public Builder httpsPort(final int httpsPort) {
            if (httpsPort <= 0) {
                randomHttpsPort();
            } else {
                setHttpsPort(httpsPort);
            }
            return this;
        }

        public Builder stopPort(final int stopPort) {
            setStopPort(stopPort);
            return this;
        }

        public Builder host(final String host) {
            setHost(host);
            return this;
        }

        public Builder dir(final String dir) {
            setDir(dir);
            return this;
        }

        public Builder serverXml(final Path serverXml) {
            setServerXml(serverXml.toFile());
            return this;
        }

        public Builder keepServerXmlAsThis(final boolean keepServerXmlAsThis) {
            setKeepServerXmlAsThis(keepServerXmlAsThis);
            return this;
        }

        public Builder properties(final Properties properties) {
            getProperties().putAll(properties);
            return this;
        }

        public Builder quickSession(final boolean quickSession) {
            setQuickSession(quickSession);
            return this;
        }

        public Builder skipHttp(final boolean skipHttp) {
            setSkipHttp(skipHttp);
            return this;
        }

        public Builder ssl(final boolean ssl) {
            setSsl(ssl);
            return this;
        }

        public Builder keystoreFile(final String keystoreFile) {
            setKeystoreFile(keystoreFile);
            return this;
        }

        public Builder keystorePass(final String keystorePass) {
            setKeystorePass(keystorePass);
            return this;
        }

        public Builder keystoreType(final String keystoreType) {
            setKeystoreType(keystoreType);
            return this;
        }

        public Builder clientAuth(final String clientAuth) {
            setClientAuth(clientAuth);
            return this;
        }

        public Builder keyAlias(final String keyAlias) {
            setKeyAlias(keyAlias);
            return this;
        }

        public Builder sslProtocol(final String sslProtocol) {
            setSslProtocol(sslProtocol);
            return this;
        }

        public Builder webXml(final String webXml) {
            setWebXml(webXml);
            return this;
        }

        public Builder loginConfig(final LoginConfigBuilder loginConfig) {
            setLoginConfig(loginConfig);
            return this;
        }

        public Builder securityConstraint(final SecurityConstaintBuilder securityConstraint) {
            if (getSecurityConstraints() == null) {
                setSecurityConstraints(new ArrayList<>());
            }
            getSecurityConstraints().add(securityConstraint);
            return this;
        }

        public Builder realm(final Realm realm) {
            setRealm(realm);
            return this;
        }

        public Builder users(final Map<String, String> users) {
            if (getUsers() == null) {
                setUsers(new HashMap<>());
            }
            getUsers().putAll(users);
            return this;
        }

        public Builder roles(final Map<String, String> roles) {
            if (getRoles() == null) {
                setRoles(new HashMap<>());
            }
            getRoles().putAll(roles);
            return this;
        }

        public Builder http2(final boolean http2) {
            setHttp2(http2);
            return this;
        }

        public Builder connector(final Connector connector) {
            getConnectors().add(connector);
            return this;
        }

        public Builder tempDir(final String tempDir) {
            setTempDir(tempDir);
            return this;
        }

        public Builder webResourceCached(final boolean webResourceCached) {
            setWebResourceCached(webResourceCached);
            return this;
        }

        public Builder conf(final String conf) {
            setConf(conf);
            return this;
        }

        public Builder deleteBaseOnStartup(final boolean deleteBaseOnStartup) {
            setDeleteBaseOnStartup(deleteBaseOnStartup);
            return this;
        }

        public Builder jaxrsMapping(final String jaxrsMapping) {
            setJaxrsMapping(jaxrsMapping);
            return this;
        }

        public Builder cdiConversation(final boolean cdiConversation) {
            setCdiConversation(cdiConversation);
            return this;
        }

        public Builder jaxrsProviderSetup(final boolean jaxrsProviderSetup) {
            setJaxrsProviderSetup(jaxrsProviderSetup);
            return this;
        }

        public Builder jaxrsDefaultProviders(final String jaxrsDefaultProviders) {
            setJaxrsDefaultProviders(jaxrsDefaultProviders);
            return this;
        }

        public Builder jaxrsAutoActivateBeanValidation(final boolean jaxrsAutoActivateBeanValidation) {
            setJaxrsAutoActivateBeanValidation(jaxrsAutoActivateBeanValidation);
            return this;
        }

        public Builder jaxrsLogProviders(final boolean jaxrsLogProviders) {
            setJaxrsLogProviders(jaxrsLogProviders);
            return this;
        }

        public Builder jsonpBufferStrategy(final String jsonpBufferStrategy) {
            setJsonpBufferStrategy(jsonpBufferStrategy);
            return this;
        }

        public Builder jsonpMaxStringLen(final int jsonpMaxStringLen) {
            setJsonpMaxStringLen(jsonpMaxStringLen);
            return this;
        }

        public Builder jsonpMaxReadBufferLen(final int jsonpMaxReadBufferLen) {
            setJsonpMaxReadBufferLen(jsonpMaxReadBufferLen);
            return this;
        }

        public Builder jsonpMaxWriteBufferLen(final int jsonpMaxWriteBufferLen) {
            setJsonpMaxWriteBufferLen(jsonpMaxWriteBufferLen);
            return this;
        }

        public Builder jsonpSupportsComment(final boolean jsonpSupportsComment) {
            setJsonpSupportsComment(jsonpSupportsComment);
            return this;
        }

        public Builder jsonpPrettify(final boolean jsonpPrettify) {
            setJsonpPrettify(jsonpPrettify);
            return this;
        }

        public Builder jsonbEncoding(final String jsonbEncoding) {
            setJsonbEncoding(jsonbEncoding);
            return this;
        }

        public Builder jsonbNulls(final boolean jsonbNulls) {
            setJsonbNulls(jsonbNulls);
            return this;
        }

        public Builder jsonbIJson(final boolean jsonbIJson) {
            setJsonbIJson(jsonbIJson);
            return this;
        }

        public Builder jsonbPrettify(final boolean jsonbPrettify) {
            setJsonbPrettify(jsonbPrettify);
            return this;
        }

        public Builder jsonbBinaryStrategy(final String jsonbBinaryStrategy) {
            setJsonbBinaryStrategy(jsonbBinaryStrategy);
            return this;
        }

        public Builder jsonbNamingStrategy(final String jsonbNamingStrategy) {
            setJsonbNamingStrategy(jsonbNamingStrategy);
            return this;
        }

        public Builder jsonbOrderStrategy(final String jsonbOrderStrategy) {
            setJsonbOrderStrategy(jsonbOrderStrategy);
            return this;
        }

        public Builder loggingGlobalSetup(final boolean loggingGlobalSetup) {
            setLoggingGlobalSetup(loggingGlobalSetup);
            return this;
        }

        public Builder tomcatScanning(final boolean tomcatScanning) {
            setTomcatScanning(tomcatScanning);
            return this;
        }

        public Builder tomcatAutoSetup(final boolean tomcatAutoSetup) {
            setTomcatAutoSetup(tomcatAutoSetup);
            return this;
        }

        public Builder tomcatJspDevelopment(final boolean tomcatJspDevelopment) {
            setTomcatJspDevelopment(tomcatJspDevelopment);
            return this;
        }

        public Builder useShutdownHook(final boolean useShutdownHook) {
            setUseShutdownHook(useShutdownHook);
            return this;
        }

        public Builder tomcatFilter(final String tomcatFilter) {
            setTomcatFilter(tomcatFilter);
            return this;
        }

        public Builder scanningIncludes(final String scanningIncludes) {
            setScanningIncludes(scanningIncludes);
            return this;
        }

        public Builder scanningExcludes(final String scanningExcludes) {
            setScanningExcludes(scanningExcludes);
            return this;
        }

        public Builder scanningPackageIncludes(final String scanningPackageIncludes) {
            setScanningPackageIncludes(scanningPackageIncludes);
            return this;
        }

        public Builder scanningPackageIncludes(final Collection<String> scanningPackageIncludes) {
            setScanningPackageIncludes(String.join(",", scanningPackageIncludes));
            return this;
        }

        public Builder scanningPackageExcludes(final String scanningPackageExcludes) {
            setScanningPackageExcludes(scanningPackageExcludes);
            return this;
        }

        public Builder scanningPackageExcludes(final Collection<String> scanningPackageExcludes) {
            setScanningPackageExcludes(String.join(",", scanningPackageExcludes));
            return this;
        }

        public Builder webSessionTimeout(final int webSessionTimeout) {
            setWebSessionTimeout(webSessionTimeout);
            return this;
        }

        public Builder webSessionCookieConfig(final String webSessionCookieConfig) {
            setWebSessionCookieConfig(webSessionCookieConfig);
            return this;
        }

        public Builder useTomcatDefaults(final boolean useTomcatDefaults) {
            setUseTomcatDefaults(useTomcatDefaults);
            return this;
        }

        public Builder tomcatWrapLoader(final boolean tomcatWrapLoader) {
            setTomcatWrapLoader(tomcatWrapLoader);
            return this;
        }

        public Builder tomcatNoJmx(final boolean tomcatNoJmx) {
            setTomcatNoJmx(tomcatNoJmx);
            return this;
        }

        public Builder useLog4j2JulLogManager(final boolean useLog4j2JulLogManager) {
            setUseLog4j2JulLogManager(useLog4j2JulLogManager);
            return this;
        }

        public Builder injectServletContainerInitializer(final boolean injectServletContainerInitializer) {
            setInjectServletContainerInitializer(injectServletContainerInitializer);
            return this;
        }

        public Builder tomcatAccessLogPattern(final String tomcatAccessLogPattern) {
            setTomcatAccessLogPattern(tomcatAccessLogPattern);
            return this;
        }

        public Builder meecrowaveProperties(final String meecrowaveProperties) {
            setMeecrowaveProperties(meecrowaveProperties);
            return this;
        }

        public Builder jaxwsSupportIfAvailable(final boolean jaxwsSupportIfAvailable) {
            setJaxwsSupportIfAvailable(jaxwsSupportIfAvailable);
            return this;
        }

        public Builder defaultSSLHostConfigName(final String defaultSSLHostConfigName) {
            setDefaultSSLHostConfigName(defaultSSLHostConfigName);
            return this;
        }

        public Builder initializeClientBus(final boolean initializeClientBus) {
            setInitializeClientBus(initializeClientBus);
            return this;
        }

        public Builder instanceCustomizers(final Consumer<Tomcat> instanceCustomizer) {
            addInstanceCustomizer(instanceCustomizer);
            return this;
        }

        public Builder initializer(final ServletContainerInitializer initializer) {
            addServletContextInitializer(initializer);
            return this;
        }

        public Builder antiResourceLocking(final boolean antiResourceLocking) {
            setAntiResourceLocking(antiResourceLocking);
            return this;
        }

        public Builder contextConfigurer(final Consumer<Context> contextConfigurers) {
            addGlobalContextCustomizer(contextConfigurers);
            return this;
        }
    }

    public static class ValueTransformers implements Function<String, String> {
        private final Map<String, ValueTransformer> transformers = new HashMap<>();

        @Override
        public String apply(final String value) {
            if (value.startsWith("decode:")) {
                if (transformers.isEmpty()) { // lazy loading
                    transformers.put("Static3DES", new ValueTransformer() { // compatibility with tomee
                        private final SecretKeySpec key = new SecretKeySpec(new byte[]{
                                (byte) 0x76, (byte) 0x6F, (byte) 0xBA, (byte) 0x39, (byte) 0x31,
                                (byte) 0x2F, (byte) 0x0D, (byte) 0x4A, (byte) 0xA3, (byte) 0x90,
                                (byte) 0x55, (byte) 0xFE, (byte) 0x55, (byte) 0x65, (byte) 0x61,
                                (byte) 0x13, (byte) 0x34, (byte) 0x82, (byte) 0x12, (byte) 0x17,
                                (byte) 0xAC, (byte) 0x77, (byte) 0x39, (byte) 0x19}, "DESede");

                        @Override
                        public String name() {
                            return "Static3DES";
                        }

                        @Override
                        public String apply(final String encodedPassword) {
                            Objects.requireNonNull(encodedPassword, "value can't be null");
                            try {
                                final byte[] cipherText = Base64.getDecoder().decode(encodedPassword);
                                final Cipher cipher = Cipher.getInstance("DESede");
                                cipher.init(Cipher.DECRYPT_MODE, key);
                                return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8);
                            } catch (final Exception e) {
                                throw new IllegalArgumentException(e);
                            }
                        }
                    });
                    for (final ValueTransformer t : ServiceLoader.load(ValueTransformer.class)) {
                        transformers.put(t.name(), t);
                    }
                }

                final String substring = value.substring("decode:".length());
                final int sep = substring.indexOf(':');
                if (sep < 0) {
                    throw new IllegalArgumentException("No transformer algorithm for " + value);
                }
                final String algo = substring.substring(0, sep);
                return Objects.requireNonNull(transformers.get(algo), "No ValueTransformer for value '" + value + "'").apply(substring.substring(sep + 1));
            }
            return value;
        }
    }

    public static class LoginConfigBuilder {
        private final LoginConfig loginConfig = new LoginConfig();

        public void setErrorPage(final String errorPage) {
            loginConfig.setErrorPage(errorPage);
        }

        public void setLoginPage(final String loginPage) {
            loginConfig.setLoginPage(loginPage);
        }

        public void setRealmName(final String realmName) {
            loginConfig.setRealmName(realmName);
        }

        public void setAuthMethod(final String authMethod) {
            loginConfig.setAuthMethod(authMethod);
        }

        public LoginConfigBuilder errorPage(final String errorPage) {
            loginConfig.setErrorPage(errorPage);
            return this;
        }

        public LoginConfigBuilder loginPage(final String loginPage) {
            loginConfig.setLoginPage(loginPage);
            return this;
        }

        public LoginConfigBuilder realmName(final String realmName) {
            loginConfig.setRealmName(realmName);
            return this;
        }

        public LoginConfigBuilder authMethod(final String authMethod) {
            loginConfig.setAuthMethod(authMethod);
            return this;
        }

        public LoginConfig build() {
            return loginConfig;
        }

        public LoginConfigBuilder basic() {
            return authMethod("BASIC");
        }

        public LoginConfigBuilder digest() {
            return authMethod("DIGEST");
        }

        public LoginConfigBuilder clientCert() {
            return authMethod("CLIENT-CERT");
        }

        public LoginConfigBuilder form() {
            return authMethod("FORM");
        }
    }

    public static class SecurityConstaintBuilder {
        private final SecurityConstraint securityConstraint = new SecurityConstraint();

        public SecurityConstaintBuilder authConstraint(final boolean authConstraint) {
            securityConstraint.setAuthConstraint(authConstraint);
            return this;
        }

        public SecurityConstaintBuilder displayName(final String displayName) {
            securityConstraint.setDisplayName(displayName);
            return this;
        }

        public SecurityConstaintBuilder userConstraint(final String constraint) {
            securityConstraint.setUserConstraint(constraint);
            return this;
        }

        public SecurityConstaintBuilder addAuthRole(final String authRole) {
            securityConstraint.addAuthRole(authRole);
            return this;
        }

        public SecurityConstaintBuilder addCollection(final String name, final String pattern, final String... methods) {
            final SecurityCollection collection = new SecurityCollection();
            collection.setName(name);
            collection.addPattern(pattern);
            for (final String httpMethod : methods) {
                collection.addMethod(httpMethod);
            }
            securityConstraint.addCollection(collection);
            return this;
        }

        public void setAuthConstraint(final boolean authConstraint) {
            securityConstraint.setAuthConstraint(authConstraint);
        }

        public void setDisplayName(final String displayName) {
            securityConstraint.setDisplayName(displayName);
        }

        public void setUserConstraint(final String userConstraint) {
            securityConstraint.setUserConstraint(userConstraint);
        }

        public void setAuthRole(final String authRole) { // easier for config
            addAuthRole(authRole);
        }

        // name:pattern:method1/method2
        public void setCollection(final String value) { // for config
            final String[] split = value.split(":");
            if (split.length != 3 && split.length != 2) {
                throw new IllegalArgumentException("Can't parse " + value + ", syntax is: name:pattern:method1/method2");
            }
            addCollection(split[0], split[1], split.length == 2 ? new String[0] : split[2].split("/"));
        }

        public SecurityConstraint build() {
            return securityConstraint;
        }
    }

    private static class InternalTomcat extends Tomcat {
        private Connector connector;

        private void server(final Server s) {
            server = s;
            connector = server != null && server.findServices().length > 0 && server.findServices()[0].findConnectors().length > 0 ?
                    server.findServices()[0].findConnectors()[0] : null;
        }

        Connector getRawConnector() {
            return connector;
        }
    }

    private static class QuickServerXmlParser extends DefaultHandler {
        private static final SAXParserFactory FACTORY = SAXParserFactory.newInstance();

        static {
            FACTORY.setNamespaceAware(true);
            FACTORY.setValidating(false);
        }

        private static final String STOP_KEY = "STOP";
        private static final String HTTP_KEY = "HTTP";
        private static final String SECURED_SUFFIX = "S";
        private static final String HOST_KEY = "host";
        private static final String DEFAULT_CONNECTOR_KEY = HTTP_KEY;

        private static final String DEFAULT_HTTP_PORT = "8080";
        private static final String DEFAULT_HTTPS_PORT = "8443";
        private static final String DEFAULT_STOP_PORT = "8005";
        private static final String DEFAULT_HOST = "localhost";

        private final Map<String, String> values = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);

        private QuickServerXmlParser(final boolean useDefaults) {
            if (useDefaults) {
                values.put(STOP_KEY, DEFAULT_STOP_PORT);
                values.put(HTTP_KEY, DEFAULT_HTTP_PORT);
                values.put(HOST_KEY, DEFAULT_HOST);
            }
        }

        @Override
        public void startElement(final String uri, final String localName,
                                 final String qName, final Attributes attributes) throws SAXException {
            if ("Server".equalsIgnoreCase(localName)) {
                final String port = attributes.getValue("port");
                if (port != null) {
                    values.put(STOP_KEY, port);
                } else {
                    values.put(STOP_KEY, DEFAULT_STOP_PORT);
                }
            } else if ("Connector".equalsIgnoreCase(localName)) {
                String protocol = attributes.getValue("protocol");
                if (protocol == null) {
                    protocol = DEFAULT_CONNECTOR_KEY;
                } else if (protocol.contains("/")) {
                    protocol = protocol.substring(0, protocol.indexOf("/"));
                }
                final String port = attributes.getValue("port");
                final String ssl = attributes.getValue("secure");

                if (ssl == null || "false".equalsIgnoreCase(ssl)) {
                    values.put(protocol.toUpperCase(), port);
                } else {
                    values.put(protocol.toUpperCase() + SECURED_SUFFIX, port);
                }
            } else if ("Host".equalsIgnoreCase(localName)) {
                final String host = attributes.getValue("name");
                if (host != null) {
                    values.put(HOST_KEY, host);
                }
            }
        }

        private static QuickServerXmlParser parse(final File serverXml) {
            return parse(serverXml, true);
        }

        private static QuickServerXmlParser parse(final File serverXml, final boolean defaults) {
            final QuickServerXmlParser handler = new QuickServerXmlParser(defaults);
            try {
                final SAXParser parser = FACTORY.newSAXParser();
                parser.parse(serverXml, handler);
            } catch (final Exception e) {
                // no-op: using defaults
            }
            return handler;
        }

        public String http() {
            return value(HTTP_KEY, DEFAULT_HTTP_PORT);
        }

        private String https() { // enough common to be exposed as method
            return securedValue(HTTP_KEY, DEFAULT_HTTPS_PORT);
        }

        private String stop() {
            return value(STOP_KEY, DEFAULT_STOP_PORT);
        }

        private String value(final String key, final String defaultValue) {
            final String val = values.get(key);
            if (val == null) {
                return defaultValue;
            }
            return val;
        }

        private String securedValue(final String key, final String defaultValue) {
            return value(key + SECURED_SUFFIX, defaultValue);
        }
    }

    // there to be able to stack config later on without breaking all methods
    public static class DeploymentMeta {
        private final String context;
        private final File docBase;
        private final Consumer<Context> consumer;

        public DeploymentMeta(final String context, final File docBase, final Consumer<Context> consumer) {
            this.context = context;
            this.docBase = docBase;
            this.consumer = consumer;
        }
    }

    // just to type it and allow some extensions to use a ServiceLoader
    public interface ConfigurationCustomizer extends Consumer<Configuration> {
    }

    /**
     * SPI to customize Tomcat instance. They are sorted by Priority, default being 0.
     */
    public interface InstanceCustomizer extends Consumer<Tomcat> {
    }

    /**
     * SPI to customize context instances. They are sorted by Priority, default being 0.
     */
    public interface ContextCustomizer extends Consumer<Context> {
    }

    public interface MeecrowaveAwareContextCustomizer extends ContextCustomizer {
        void setMeecrowave(Meecrowave meecrowave);
    }

    // since it is too early to have CDI and lookup the instance we must set it manually
    public interface MeecrowaveAwareInstanceCustomizer extends InstanceCustomizer {
        void setMeecrowave(Meecrowave meecrowave);
    }

    private static final class MeecrowaveContainerLoader extends URLClassLoader {
        private MeecrowaveContainerLoader(final URL[] urls, final ClassLoader parent) {
            super(urls, parent);
        }
    }
}
