/*
 * 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.emptyMap;
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.FileNotFoundException;
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.Collections;
import java.util.HashMap;
import java.util.LinkedList;
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.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.Manager;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
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.ManagerBase;
import org.apache.catalina.session.StandardManager;
import org.apache.catalina.startup.Catalina;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.http2.Http2Protocol;
import org.apache.meecrowave.api.StartListening;
import org.apache.meecrowave.api.StopListening;
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.runner.cli.CliOption;
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 Builder 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 Builder builder) {
        this.configuration = builder;
        this.ownedTempDir = new File(configuration.tempDir, "meecrowave_" + System.nanoTime());
    }

    public Builder getConfiguration() {
        return 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.tomcatFilter).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", configuration);
            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.webResourceCached);
                    break;
                case Lifecycle.BEFORE_INIT_EVENT:
                    if (configuration.loginConfig != null) {
                        ctx.setLoginConfig(configuration.loginConfig.build());
                    }
                    for (final SecurityConstaintBuilder sc : configuration.securityConstraints) {
                        ctx.addConstraint(sc.build());
                    }
                    if (configuration.webXml != null) {
                        ctx.getServletContext().setAttribute(Globals.ALT_DD_ATTR, configuration.webXml);
                    }
                    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");
            try {
                final Field mimesField = Tomcat.class.getDeclaredField("DEFAULT_MIME_MAPPINGS");
                if (!mimesField.isAccessible()) {
                    mimesField.setAccessible(true);
                }
                final String[] defaultMimes = String[].class.cast(mimesField.get(null));
                for (int i = 0; i < defaultMimes.length; ) {
                    ctx.addMimeMapping(defaultMimes[i++], defaultMimes[i++]);
                }
            } catch (final NoSuchFieldException | IllegalAccessException e) {
                throw new IllegalStateException("Incompatible Tomcat", e);
            }
        } else if (configuration.getWebSessionTimeout() != null) {
            ctx.setSessionTimeout(configuration.getWebSessionTimeout());
        }

        ofNullable(meta.consumer).ifPresent(c -> c.accept(ctx));
        if (configuration.antiResourceLocking && 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.loggingGlobalSetup && 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;

        if (configuration.quickSession) {
            tomcat = new TomcatWithFastSessionIDs();
        } else {
            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.conf);
        }

        final Properties props = configuration.properties;
        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.httpPort));
                    placeHolders.put("meecrowave.embedded.https", Integer.toString(configuration.httpsPort));
                    placeHolders.put("meecrowave.embedded.stop", Integer.toString(configuration.stopPort));
                    substitutor = new Substitutor(placeHolders);
                }
                props.put(s, substitutor.replace(v));
            }
        }

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

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

        final boolean initialized;
        if (configuration.serverXml != null) {
            final File file = new File(conf, "server.xml");
            if (!file.equals(configuration.serverXml)) {
                try (final InputStream is = new FileInputStream(configuration.serverXml);
                     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.keepServerXmlAsThis) {
                configuration.httpPort = Integer.parseInt(ports.http());
                configuration.stopPort = Integer.parseInt(ports.stop());
            } else {
                final Map<String, String> replacements = new HashMap<>();
                replacements.put(ports.http(), String.valueOf(configuration.httpPort));
                replacements.put(ports.https(), String.valueOf(configuration.httpsPort));
                replacements.put(ports.stop(), String.valueOf(configuration.stopPort));

                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.stopPort);
            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.host);
            tomcat.getEngine().setDefaultHost(configuration.host);
            final StandardHost host = new StandardHost();
            host.setName(configuration.host);

            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.realm != null) {
            tomcat.getEngine().setRealm(configuration.realm);
        }

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

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

        // create https connector
        if (configuration.ssl) {
            final Connector httpsConnector = createConnector();
            httpsConnector.setPort(configuration.httpsPort);
            httpsConnector.setSecure(true);
            httpsConnector.setScheme("https");
            httpsConnector.setProperty("SSLEnabled", "true");
            if (configuration.sslProtocol != null) {
                configuration.property("connector.sslhostconfig.sslProtocol", configuration.sslProtocol);
            }
            if (configuration.properties.getProperty("connector.sslhostconfig.hostName") != null) {
                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.properties.getProperty("connector.sslhostconfig.hostName"));
            }
            if (configuration.keystoreFile != null) {
                configuration.property("connector.sslhostconfig.certificateKeystoreFile", configuration.keystoreFile);
            }
            if (configuration.keystorePass != null) {
                configuration.property("connector.sslhostconfig.certificateKeystorePassword", configuration.keystorePass);
            }
            configuration.property("connector.sslhostconfig.certificateKeystoreType", configuration.keystoreType);
            if (configuration.clientAuth != null) {
                httpsConnector.setAttribute("clientAuth", configuration.clientAuth);
            }

            if (configuration.keyAlias != null) {
                configuration.property("connector.sslhostconfig.certificateKeyAlias", configuration.keyAlias);
            }
            if (configuration.http2) {
                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.defaultSSLHostConfigName != null) {
                httpsConnector.setAttribute("defaultSSLHostConfigName", configuration.defaultSSLHostConfigName);
            }
            tomcat.getService().addConnector(httpsConnector);
            if (configuration.skipHttp) {
                tomcat.setConnector(httpsConnector);
            }
        }

        for (final Connector c : configuration.connectors) {
            tomcat.getService().addConnector(c);
        }
        if (!configuration.skipHttp && !configuration.ssl && !configuration.connectors.isEmpty()) {
            tomcat.setConnector(configuration.connectors.iterator().next());
        }

        if (configuration.users != null) {
            for (final Map.Entry<String, String> user : configuration.users.entrySet()) {
                tomcat.addUser(user.getKey(), user.getValue());
            }
        }
        if (configuration.roles != null) {
            for (final Map.Entry<String, String> user : configuration.roles.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);
                    }
                })
                .forEach(c -> c.accept(tomcat));
        configuration.instanceCustomizers.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);
                    }
                })
                .forEach(configuration::addGlobalContextCustomizer);

        beforeStart();


        if (configuration.initializeClientBus && 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.properties.stringPropertyNames().stream()
                                .filter(key -> key.startsWith("valves.") && key.endsWith("._className"))
                                .sorted(comparing(key -> Integer.parseInt(configuration.properties
                                        .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.properties.getProperty(prefix + key[2]));
            configuration.properties.stringPropertyNames().stream()
                    .filter(it -> it.startsWith(prefix) && !it.endsWith("._order") && !it.endsWith("._className"))
                    .forEach(propKey -> {
                        final String value = configuration.properties.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.properties.stringPropertyNames()) {
            if (key.startsWith("connector.sslhostconfig.") && key.split("\\.").length == 3) {
                final String substring = key.substring("connector.sslhostconfig.".length());
                defaultSslHostConfig.setProperty(substring, configuration.properties.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.properties.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.properties.stringPropertyNames().stream()
                                    .filter(k -> k.startsWith(prefix))
                                    .forEach(key -> {
                                        final String keyName = key.split("\\.")[3];
                                        recipe.setProperty(keyName, configuration.properties.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.properties;
        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.dir;
        if (dir != null) {
            final File dirFile = new File(dir);
            if (dirFile.exists()) {
                if (base != null && base.exists() && configuration.deleteBaseOnStartup) {
                    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 {
        @CliOption(name = "pid-file", description = "A file path to write the process id if the server starts")
        private File pidFile;

        @CliOption(name = "watcher-bouncing", description = "Activate redeployment on directories update using this bouncing.")
        private int watcherBouncing = 500;

        @CliOption(name = "http", description = "HTTP port")
        private int httpPort = 8080;

        @CliOption(name = "https", description = "HTTPS port")
        private int httpsPort = 8443;

        @CliOption(name = "stop", description = "Shutdown port if used or -1")
        private int stopPort = -1;

        @CliOption(name = "host", description = "Default host")
        private String host = "localhost";

        @CliOption(name = "dir", description = "Root folder if provided otherwise a fake one is created in tmp-dir")
        private String dir;

        @CliOption(name = "server-xml", description = "Provided server.xml")
        private File serverXml;

        @CliOption(name = "keep-server-xml-as-this", description = "Don't replace ports in server.xml")
        private boolean keepServerXmlAsThis;

        @CliOption(name = "properties", description = "Passthrough properties")
        private Properties properties = new Properties();

        @CliOption(name = "quick-session", description = "Should an unsecured but fast session id generator be used")
        private boolean quickSession = true;

        @CliOption(name = "skip-http", description = "Skip HTTP connector")
        private boolean skipHttp;

        @CliOption(name = "ssl", description = "Use HTTPS")
        private boolean ssl;

        @CliOption(name = "keystore-file", description = "HTTPS keystore location")
        private String keystoreFile;

        @CliOption(name = "keystore-password", description = "HTTPS keystore password")
        private String keystorePass;

        @CliOption(name = "keystore-type", description = "HTTPS keystore type")
        private String keystoreType = "JKS";

        @CliOption(name = "client-auth", description = "HTTPS keystore client authentication")
        private String clientAuth;

        @CliOption(name = "keystore-alias", description = "HTTPS keystore alias")
        private String keyAlias;

        @CliOption(name = "ssl-protocol", description = "HTTPS protocol")
        private String sslProtocol;

        @CliOption(name = "web-xml", description = "Global web.xml")
        private String webXml;

        @CliOption(name = "login-config", description = "web.xml login config")
        private LoginConfigBuilder loginConfig;

        @CliOption(name = "security-constraint", description = "web.xml security constraint")
        private Collection<SecurityConstaintBuilder> securityConstraints = new LinkedList<>();

        @CliOption(name = "realm", description = "realm")
        private Realm realm;

        @CliOption(name = "users", description = "In memory users")
        private Map<String, String> users;

        @CliOption(name = "roles", description = "In memory roles")
        private Map<String, String> roles;

        @CliOption(name = "http2", description = "Activate HTTP 2")
        private boolean http2;

        @CliOption(name = "connector", description = "Custom connectors")
        private final Collection<Connector> connectors = new ArrayList<>();

        @CliOption(name = "tmp-dir", description = "Temporary directory")
        private String tempDir = System.getProperty("java.io.tmpdir");

        @CliOption(name = "web-resource-cached", description = "Cache web resources")
        private boolean webResourceCached = true;

        @CliOption(name = "conf", description = "Conf folder to synchronize")
        private String conf;

        @CliOption(name = "delete-on-startup", description = "Should the directory be cleaned on startup if existing")
        private boolean deleteBaseOnStartup = true;

        @CliOption(name = "jaxrs-mapping", description = "Default jaxrs mapping")
        private String jaxrsMapping = "/*";

        @CliOption(name = "cdi-conversation", description = "Should CDI conversation be activated")
        private boolean cdiConversation;

        @CliOption(name = "jaxrs-provider-setup", description = "Should default JAX-RS provider be configured")
        private boolean jaxrsProviderSetup = true;

        @CliOption(name = "jaxrs-default-providers", description = "If jaxrsProviderSetup is true the list of default providers to load (or defaulting to johnson jsonb and jsonp ones)")
        private String jaxrsDefaultProviders;

        @CliOption(name = "jaxrs-beanvalidation", description = "Should bean validation be activated on JAX-RS endpoint if present in the classpath.")
        private boolean jaxrsAutoActivateBeanValidation = true;

        @CliOption(name = "jaxrs-log-provider", description = "Should JAX-RS providers be logged")
        private boolean jaxrsLogProviders = false;

        @CliOption(name = "jsonp-buffer-strategy", description = "JSON-P JAX-RS provider buffer strategy (see johnzon)")
        private String jsonpBufferStrategy = "QUEUE";

        @CliOption(name = "jsonp-max-string-length", description = "JSON-P JAX-RS provider max string limit size (see johnzon)")
        private int jsonpMaxStringLen = 64 * 1024;

        @CliOption(name = "jsonp-read-buffer-length", description = "JSON-P JAX-RS provider read buffer limit size (see johnzon)")
        private int jsonpMaxReadBufferLen = 64 * 1024;

        @CliOption(name = "jsonp-write-buffer-length", description = "JSON-P JAX-RS provider write buffer limit size (see johnzon)")
        private int jsonpMaxWriteBufferLen = 64 * 1024;

        @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider support comments (see johnzon)")
        private boolean jsonpSupportsComment = false;

        @CliOption(name = "jsonp-supports-comment", description = "Should JSON-P JAX-RS provider prettify the outputs (see johnzon)")
        private boolean jsonpPrettify = false;

        @CliOption(name = "jsonb-encoding", description = "Which encoding provider JSON-B should use")
        private String jsonbEncoding = "UTF-8";

        @CliOption(name = "jsonb-nulls", description = "Should JSON-B provider serialize nulls")
        private boolean jsonbNulls = false;

        @CliOption(name = "jsonb-ijson", description = "Should JSON-B provider comply to I-JSON")
        private boolean jsonbIJson = false;

        @CliOption(name = "jsonb-prettify", description = "Should JSON-B provider prettify the output")
        private boolean jsonbPrettify = false;

        @CliOption(name = "jsonb-binary-strategy", description = "Should JSON-B provider prettify the output")
        private String jsonbBinaryStrategy;

        @CliOption(name = "jsonb-naming-strategy", description = "Should JSON-B provider prettify the output")
        private String jsonbNamingStrategy;

        @CliOption(name = "jsonb-order-strategy", description = "Should JSON-B provider prettify the output")
        private String jsonbOrderStrategy;

        @CliOption(name = "logging-global-setup", description = "Should logging be configured to use log4j2 (it is global)")
        private boolean loggingGlobalSetup = true;

        @CliOption(name = "cxf-servlet-params", description = "Init parameters passed to CXF servlet")
        private Map<String, String> cxfServletParams;

        @CliOption(name = "tomcat-scanning", description = "Should Tomcat scanning be used (@HandleTypes, @WebXXX)")
        private boolean tomcatScanning = true;

        @CliOption(name = "tomcat-default-setup", description = "Add default servlet")
        private boolean tomcatAutoSetup = true;

        @CliOption(name = "tomcat-default-setup-jsp-development", description = "Should JSP support if available be set in development mode")
        private boolean tomcatJspDevelopment = false;

        @CliOption(name = "use-shutdown-hook", description = "Use shutdown hook to automatically stop the container on Ctrl+C")
        private boolean useShutdownHook = true;

        @CliOption(name = "tomcat-filter", description = "A Tomcat JarScanFilter")
        private String tomcatFilter;

        @CliOption(name = "scanning-include", description = "A forced include list of jar names (comma separated values)")
        private String scanningIncludes;

        @CliOption(name = "scanning-exclude", description = "A forced exclude list of jar names (comma separated values)")
        private String scanningExcludes;

        @CliOption(name = "scanning-package-include", description = "A forced include list of packages names (comma separated values)")
        private String scanningPackageIncludes;

        @CliOption(name = "scanning-package-exclude", description = "A forced exclude list of packages names (comma separated values)")
        private String scanningPackageExcludes;

        @CliOption(name = "web-session-timeout", description = "Force the session timeout for webapps")
        private Integer webSessionTimeout;

        @CliOption(name = "web-session-cookie-config", description = "Force the cookie-config, it uses a properties syntax with the keys being the web.xml tag names.")
        private String webSessionCookieConfig;

        @CliOption(name = "tomcat-default", description = "Should Tomcat default be set (session timeout, mime mapping etc...)")
        private boolean useTomcatDefaults = true;

        @CliOption(name = "tomcat-wrap-loader", description = "(Experimental) When deploying a classpath (current classloader), " +
                "should meecrowave wrap the loader to define another loader identity but still use the same classes and resources.")
        private boolean tomcatWrapLoader = false;

        @CliOption(name = "tomcat-skip-jmx", description = "(Experimental) Should Tomcat MBeans be skipped.")
        private boolean tomcatNoJmx = true;

        @CliOption(name = "shared-libraries", description = "A folder containing shared libraries.", alias = "shared-librairies")
        private String sharedLibraries;

        @CliOption(name = "log4j2-jul-bridge", description = "Should JUL logs be redirected to Log4j2 - only works before JUL usage.")
        private boolean useLog4j2JulLogManager = System.getProperty("java.util.logging.manager") == null;

        @CliOption(name = "servlet-container-initializer-injection", description = "Should ServletContainerInitialize support injections.")
        private boolean injectServletContainerInitializer = true;

        @CliOption(
                name = "tomcat-access-log-pattern",
                description = "Activates and configure the access log valve. Value example: '%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"'")
        private String tomcatAccessLogPattern;

        @CliOption(
                name = "meecrowave-properties",
                description = "Loads a meecrowave properties, defaults to meecrowave.properties.")
        private String meecrowaveProperties = "meecrowave.properties";

        @CliOption(name = "jaxws-support-if-present", description = "Should @WebService CDI beans be deployed if cxf-rt-frontend-jaxws is in the classpath.")
        private boolean jaxwsSupportIfAvailable = true;

        @CliOption(name = "default-ssl-hostconfig-name", description = "The name of the default SSLHostConfig that will be used for secure https connections.")
        private String defaultSSLHostConfigName;

        @CliOption(name = "cxf-initialize-client-bus", description = "Should the client bus be set. If false the server one will likely be reused.")
        private boolean initializeClientBus = true;

        private final Map<Class<?>, Object> extensions = new HashMap<>();
        private final Collection<Consumer<Tomcat>> instanceCustomizers = new ArrayList<>();

        @CliOption(name = "servlet-container-initializer", description = "ServletContainerInitializer instances.")
        private Collection<ServletContainerInitializer> initializers = new ArrayList<>();

        @CliOption(name = "tomcat-antiresourcelocking", description = "Should Tomcat anti resource locking feature be activated on StandardContext.")
        private boolean antiResourceLocking;

        @CliOption(name = "tomcat-context-configurer", description = "Configurers for all webapps. The Consumer<Context> instances will be applied to all deployments.")
        private Collection<Consumer<Context>> contextConfigurers;

        public Builder() { // load defaults
            extensions.put(ValueTransformers.class, new ValueTransformers());
            StreamSupport.stream(ServiceLoader.load(Meecrowave.ConfigurationCustomizer.class).spliterator(), false)
                    .forEach(c -> c.accept(this));
            loadFrom(meecrowaveProperties);
        }

        public <T> T getExtension(final Class<T> extension) {
            // in the cli we read the values from the cli but in other mode from properties
            // to ensure we can do the same in all modes keeping a nice cli
            return extension.cast(extensions.computeIfAbsent(extension, k -> {
                try {
                    return bind(k.newInstance());
                } catch (final InstantiationException | IllegalAccessException e) {
                    throw new IllegalArgumentException(e);
                }
            }));
        }

        public boolean isAntiResourceLocking() {
            return antiResourceLocking;
        }

        public void setAntiResourceLocking(final boolean antiResourceLocking) {
            this.antiResourceLocking = antiResourceLocking;
        }

        public Collection<Consumer<Context>> getGlobalContextConfigurers() {
            return ofNullable(contextConfigurers).orElseGet(Collections::emptySet);
        }

        public boolean isTomcatJspDevelopment() {
            return tomcatJspDevelopment;
        }

        public void setTomcatJspDevelopment(final boolean tomcatJspDevelopment) {
            this.tomcatJspDevelopment = tomcatJspDevelopment;
        }

        public Integer getWebSessionTimeout() {
            return webSessionTimeout;
        }

        public void setWebSessionTimeout(final Integer webSessionTimeout) {
            this.webSessionTimeout = webSessionTimeout;
        }

        public String getWebSessionCookieConfig() {
            return webSessionCookieConfig;
        }

        public void setWebSessionCookieConfig(final String webSessionCookieConfig) {
            this.webSessionCookieConfig = webSessionCookieConfig;
        }

        public boolean isInitializeClientBus() {
            return initializeClientBus;
        }

        public void setInitializeClientBus(final boolean initializeClientBus) {
            this.initializeClientBus = initializeClientBus;
        }

        public boolean isJaxwsSupportIfAvailable() {
            return jaxwsSupportIfAvailable;
        }

        public void setJaxwsSupportIfAvailable(final boolean jaxwsSupportIfAvailable) {
            this.jaxwsSupportIfAvailable = jaxwsSupportIfAvailable;
        }

        public int getWatcherBouncing() {
            return watcherBouncing;
        }

        public void setWatcherBouncing(final int watcherBouncing) {
            this.watcherBouncing = watcherBouncing;
        }

        public String getTomcatAccessLogPattern() {
            return tomcatAccessLogPattern;
        }

        public void setTomcatAccessLogPattern(final String tomcatAccessLogPattern) {
            this.tomcatAccessLogPattern = tomcatAccessLogPattern;
        }

        public boolean isTomcatNoJmx() {
            return tomcatNoJmx;
        }

        public void setTomcatNoJmx(final boolean tomcatNoJmx) {
            this.tomcatNoJmx = tomcatNoJmx;
        }

        public File getPidFile() {
            return pidFile;
        }

        public void setPidFile(final File pidFile) {
            this.pidFile = pidFile;
        }

        public String getScanningPackageIncludes() {
            return scanningPackageIncludes;
        }

        /**
         * Define some package names (startsWith) which must get scanned for beans.
         * This rule get's applied before {@link #setScanningPackageExcludes(String)}
         */
        public void setScanningPackageIncludes(final String scanningPackageIncludes) {
            this.scanningPackageIncludes = scanningPackageIncludes;
        }

        public String getScanningPackageExcludes() {
            return scanningPackageExcludes;
        }

        /**
         * Define some package names (startsWith) which must <em>NOT</em> get scanned for beans.
         * This rule get's applied after {@link #setScanningPackageIncludes(String)}.
         *
         * Defining just a '*' will be a marker for skipping all not-included packages.
         * Otherwise we will defer to the standard OpenWebBeans class Filter mechanism.
         */
        public void setScanningPackageExcludes(final String scanningPackageExcludes) {
            this.scanningPackageExcludes = scanningPackageExcludes;
        }

        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 void setExtension(final Class<?> type, final Object value) {
            extensions.put(type, value);
        }

        public String getScanningIncludes() {
            return scanningIncludes;
        }

        public void setScanningIncludes(final String scanningIncludes) {
            this.scanningIncludes = scanningIncludes;
        }

        public String getScanningExcludes() {
            return scanningExcludes;
        }

        public void setScanningExcludes(final String scanningExcludes) {
            this.scanningExcludes = scanningExcludes;
        }

        public String getJsonpBufferStrategy() {
            return jsonpBufferStrategy;
        }

        public String getJsonbEncoding() {
            return jsonbEncoding;
        }

        public void setJsonbEncoding(final String jsonbEncoding) {
            this.jsonbEncoding = jsonbEncoding;
        }

        public boolean isJsonbNulls() {
            return jsonbNulls;
        }

        public void setJsonbNulls(final boolean jsonbNulls) {
            this.jsonbNulls = jsonbNulls;
        }

        public boolean isJsonbIJson() {
            return jsonbIJson;
        }

        public void setJsonbIJson(final boolean jsonbIJson) {
            this.jsonbIJson = jsonbIJson;
        }

        public boolean isJsonbPrettify() {
            return jsonbPrettify;
        }

        public void setJsonbPrettify(final boolean jsonbPrettify) {
            this.jsonbPrettify = jsonbPrettify;
        }

        public String getJsonbBinaryStrategy() {
            return jsonbBinaryStrategy;
        }

        public void setJsonbBinaryStrategy(final String jsonbBinaryStrategy) {
            this.jsonbBinaryStrategy = jsonbBinaryStrategy;
        }

        public String getJsonbNamingStrategy() {
            return jsonbNamingStrategy;
        }

        public void setJsonbNamingStrategy(final String jsonbNamingStrategy) {
            this.jsonbNamingStrategy = jsonbNamingStrategy;
        }

        public String getJsonbOrderStrategy() {
            return jsonbOrderStrategy;
        }

        public void setJsonbOrderStrategy(final String jsonbOrderStrategy) {
            this.jsonbOrderStrategy = jsonbOrderStrategy;
        }

        public Builder withJsonpBufferStrategy(final String jsonpBufferStrategy) {
            this.jsonpBufferStrategy = jsonpBufferStrategy;
            return this;
        }

        public void setJsonpBufferStrategy(final String jsonpBufferStrategy) {
            this.jsonpBufferStrategy = jsonpBufferStrategy;
        }

        public int getJsonpMaxStringLen() {
            return jsonpMaxStringLen;
        }

        public void setJsonpMaxStringLen(final int jsonpMaxStringLen) {
            this.jsonpMaxStringLen = jsonpMaxStringLen;
        }

        public int getJsonpMaxReadBufferLen() {
            return jsonpMaxReadBufferLen;
        }

        public void setJsonpMaxReadBufferLen(final int jsonpMaxReadBufferLen) {
            this.jsonpMaxReadBufferLen = jsonpMaxReadBufferLen;
        }

        public int getJsonpMaxWriteBufferLen() {
            return jsonpMaxWriteBufferLen;
        }

        public void setJsonpMaxWriteBufferLen(final int jsonpMaxWriteBufferLen) {
            this.jsonpMaxWriteBufferLen = jsonpMaxWriteBufferLen;
        }

        public boolean isJsonpSupportsComment() {
            return jsonpSupportsComment;
        }

        public void setJsonpSupportsComment(final boolean jsonpSupportsComment) {
            this.jsonpSupportsComment = jsonpSupportsComment;
        }

        public boolean isJsonpPrettify() {
            return jsonpPrettify;
        }

        public void setJsonpPrettify(final boolean jsonpPrettify) {
            this.jsonpPrettify = jsonpPrettify;
        }

        public String getSharedLibraries() {
            return sharedLibraries;
        }

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

        public void setSharedLibraries(final String sharedLibraries) {
            this.sharedLibraries = sharedLibraries;
        }

        public boolean isJaxrsLogProviders() {
            return jaxrsLogProviders;
        }

        public void setJaxrsLogProviders(final boolean jaxrsLogProviders) {
            this.jaxrsLogProviders = jaxrsLogProviders;
        }

        public boolean isUseTomcatDefaults() {
            return useTomcatDefaults;
        }

        public void setUseTomcatDefaults(final boolean useTomcatDefaults) {
            this.useTomcatDefaults = useTomcatDefaults;
        }

        public String getTomcatFilter() {
            return tomcatFilter;
        }

        public void setTomcatFilter(final String tomcatFilter) {
            this.tomcatFilter = tomcatFilter;
        }

        public boolean isTomcatScanning() {
            return tomcatScanning;
        }

        public void setTomcatScanning(final boolean tomcatScanning) {
            this.tomcatScanning = tomcatScanning;
        }

        public Map<String, String> getCxfServletParams() {
            return cxfServletParams;
        }

        public void setCxfServletParams(final Map<String, String> cxfServletParams) {
            this.cxfServletParams = cxfServletParams;
        }

        public boolean isLoggingGlobalSetup() {
            return loggingGlobalSetup;
        }

        public void setLoggingGlobalSetup(final boolean loggingGlobalSetup) {
            this.loggingGlobalSetup = loggingGlobalSetup;
        }

        public boolean isJaxrsAutoActivateBeanValidation() {
            return jaxrsAutoActivateBeanValidation;
        }

        public void setJaxrsAutoActivateBeanValidation(final boolean jaxrsAutoActivateBeanValidation) {
            this.jaxrsAutoActivateBeanValidation = jaxrsAutoActivateBeanValidation;
        }

        public boolean isJaxrsProviderSetup() {
            return jaxrsProviderSetup;
        }

        public void setJaxrsProviderSetup(final boolean jaxrsProviderSetup) {
            this.jaxrsProviderSetup = jaxrsProviderSetup;
        }

        public int getHttpPort() {
            return httpPort;
        }

        public void setHttpPort(final int httpPort) {
            this.httpPort = httpPort;
        }

        public int getHttpsPort() {
            return httpsPort;
        }

        public void setHttpsPort(final int httpsPort) {
            this.httpsPort = httpsPort;
        }

        public int getStopPort() {
            return stopPort;
        }

        public void setStopPort(final int stopPort) {
            this.stopPort = stopPort;
        }

        public String getHost() {
            return host;
        }

        public void setHost(final String host) {
            this.host = host;
        }

        public String getDir() {
            return dir;
        }

        public void setDir(final String dir) {
            this.dir = dir;
        }

        public File getServerXml() {
            return serverXml;
        }

        public void setServerXml(final File serverXml) {
            this.serverXml = serverXml;
        }

        public boolean isKeepServerXmlAsThis() {
            return keepServerXmlAsThis;
        }

        public void setKeepServerXmlAsThis(final boolean keepServerXmlAsThis) {
            this.keepServerXmlAsThis = keepServerXmlAsThis;
        }

        public Properties getProperties() {
            return properties;
        }

        public void setProperties(final Properties properties) {
            this.properties = properties;
        }

        public boolean isQuickSession() {
            return quickSession;
        }

        public void setQuickSession(final boolean quickSession) {
            this.quickSession = quickSession;
        }

        public boolean isSkipHttp() {
            return skipHttp;
        }

        public void setSkipHttp(final boolean skipHttp) {
            this.skipHttp = skipHttp;
        }

        public boolean isSsl() {
            return ssl;
        }

        public void setSsl(final boolean ssl) {
            this.ssl = ssl;
        }

        public String getKeystoreFile() {
            return keystoreFile;
        }

        public void setKeystoreFile(final String keystoreFile) {
            this.keystoreFile = keystoreFile;
        }

        public String getKeystorePass() {
            return keystorePass;
        }

        public void setKeystorePass(final String keystorePass) {
            this.keystorePass = keystorePass;
        }

        public String getKeystoreType() {
            return keystoreType;
        }

        public void setKeystoreType(final String keystoreType) {
            this.keystoreType = keystoreType;
        }

        public String getClientAuth() {
            return clientAuth;
        }

        public void setClientAuth(final String clientAuth) {
            this.clientAuth = clientAuth;
        }

        public String getKeyAlias() {
            return keyAlias;
        }

        public void setKeyAlias(final String keyAlias) {
            this.keyAlias = keyAlias;
        }

        public String getSslProtocol() {
            return sslProtocol;
        }

        public void setSslProtocol(final String sslProtocol) {
            this.sslProtocol = sslProtocol;
        }

        public String getWebXml() {
            return webXml;
        }

        public void setWebXml(final String webXml) {
            this.webXml = webXml;
        }

        public LoginConfigBuilder getLoginConfig() {
            return loginConfig;
        }

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

        public void setLoginConfig(final LoginConfigBuilder loginConfig) {
            this.loginConfig = loginConfig;
        }

        public Collection<SecurityConstaintBuilder> getSecurityConstraints() {
            return securityConstraints;
        }

        public Builder securityConstraints(final SecurityConstaintBuilder securityConstraint) {
            securityConstraints = securityConstraints == null ? new ArrayList<>() : securityConstraints;
            securityConstraints.add(securityConstraint);
            return this;
        }

        public void setSecurityConstraints(final Collection<SecurityConstaintBuilder> securityConstraints) {
            this.securityConstraints = securityConstraints;
        }

        public Realm getRealm() {
            return realm;
        }

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

        public void setRealm(final Realm realm) {
            this.realm = realm;
        }

        public Map<String, String> getUsers() {
            return users;
        }

        public void setUsers(final Map<String, String> users) {
            this.users = users;
        }

        public Map<String, String> getRoles() {
            return roles;
        }

        public void setRoles(final Map<String, String> roles) {
            this.roles = roles;
        }

        public boolean isHttp2() {
            return http2;
        }

        public void setHttp2(final boolean http2) {
            this.http2 = http2;
        }

        public Collection<Connector> getConnectors() {
            return connectors;
        }

        public String getTempDir() {
            return tempDir;
        }

        public void setTempDir(final String tempDir) {
            this.tempDir = tempDir;
        }

        public boolean isWebResourceCached() {
            return webResourceCached;
        }

        public void setWebResourceCached(final boolean webResourceCached) {
            this.webResourceCached = webResourceCached;
        }

        public String getConf() {
            return conf;
        }

        public void setConf(final String conf) {
            this.conf = conf;
        }

        public boolean isDeleteBaseOnStartup() {
            return deleteBaseOnStartup;
        }

        public void setDeleteBaseOnStartup(final boolean deleteBaseOnStartup) {
            this.deleteBaseOnStartup = deleteBaseOnStartup;
        }

        public String getJaxrsMapping() {
            return jaxrsMapping;
        }

        public void setJaxrsMapping(final String jaxrsMapping) {
            this.jaxrsMapping = jaxrsMapping;
        }

        public boolean isCdiConversation() {
            return cdiConversation;
        }

        public void setCdiConversation(final boolean cdiConversation) {
            this.cdiConversation = cdiConversation;
        }

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

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

        public Builder loadFrom(final String resource) {
            try (final InputStream is = findStream(resource)) {
                if (is != null) {
                    final Properties config = new Properties() {{
                        load(is);
                    }};
                    loadFromProperties(config);
                }
                return this;
            } catch (final IOException e) {
                throw new IllegalStateException(e);
            }
        }

        public void setServerXml(final String file) {
            if (file == null) {
                serverXml = null;
            } else {
                final File sXml = new File(file);
                if (sXml.exists()) {
                    serverXml = sXml;
                }
            }
        }

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

        private InputStream findStream(final String resource) throws FileNotFoundException {
            InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
            if (stream == null) {
                final File file = new File(resource);
                if (file.exists()) {
                    return new FileInputStream(file);
                }
            }
            return stream;
        }

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

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

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

        public String getActiveProtocol() {
            return isSkipHttp() ? "https" : "http";
        }

        public int getActivePort() {
            return isSkipHttp() ? getHttpsPort() : getHttpPort();
        }

        public boolean isTomcatAutoSetup() {
            return tomcatAutoSetup;
        }

        public void setTomcatAutoSetup(final boolean tomcatAutoSetup) {
            this.tomcatAutoSetup = tomcatAutoSetup;
        }

        public boolean isUseShutdownHook() {
            return useShutdownHook;
        }

        public void setUseShutdownHook(final boolean useShutdownHook) {
            this.useShutdownHook = useShutdownHook;
        }

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

        public boolean isTomcatWrapLoader() {
            return tomcatWrapLoader;
        }

        public void setTomcatWrapLoader(final boolean tomcatWrapLoader) {
            this.tomcatWrapLoader = tomcatWrapLoader;
        }

        public void addInstanceCustomizer(final Consumer<Tomcat> customizer) {
            instanceCustomizers.add(customizer);
        }

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

        public void addCustomizer(final Consumer<Builder> configurationCustomizer) {
            configurationCustomizer.accept(this);
        }

        public void addGlobalContextCustomizer(final Consumer<Context> contextConfigurer) {
            if (contextConfigurers == null) {
                contextConfigurers = new ArrayList<>();
            }
            contextConfigurers.add(contextConfigurer);
        }

        public void addServletContextInitializer(final ServletContainerInitializer initializer) {
            initializers.add(initializer);
        }

        public Collection<ServletContainerInitializer> getInitializers() {
            return initializers;
        }

        public String getJaxrsDefaultProviders() {
            return jaxrsDefaultProviders;
        }

        public void setJaxrsDefaultProviders(final String jaxrsDefaultProviders) {
            this.jaxrsDefaultProviders = jaxrsDefaultProviders;
        }

        public boolean isUseLog4j2JulLogManager() {
            return useLog4j2JulLogManager;
        }

        public void setUseLog4j2JulLogManager(final boolean useLog4j2JulLogManager) {
            this.useLog4j2JulLogManager = useLog4j2JulLogManager;
        }

        public String getDefaultSSLHostConfigName() {
            return defaultSSLHostConfigName;
        }

        public void setDefaultSSLHostConfigName(final String defaultSSLHostConfigName) {
            this.defaultSSLHostConfigName = defaultSSLHostConfigName;
        }

        public void loadFromProperties(final Properties config) {
            // filtering properties with system properties or themself
            final Substitutor strSubstitutor = new Substitutor(emptyMap()) {
                @Override
                public String getOrDefault(final String key, final String or) {
                    final String property = System.getProperty(key);
                    return property == null ? config.getProperty(key, or) : or;
                }
            };

            final ValueTransformers transformers = getExtension(ValueTransformers.class);
            for (final String key : config.stringPropertyNames()) {
                final String val = config.getProperty(key);
                if (val == null || val.trim().isEmpty()) {
                    continue;
                }
                final String newVal = transformers.apply(strSubstitutor.replace(config.getProperty(key)));
                if (!val.equals(newVal)) {
                    config.setProperty(key, newVal);
                }
            }

            for (final Field field : Builder.class.getDeclaredFields()) {
                final CliOption annotation = field.getAnnotation(CliOption.class);
                if (annotation == null) {
                    continue;
                }
                final String name = field.getName();
                Stream.of(Stream.of(annotation.name()), Stream.of(annotation.alias()))
                        .flatMap(a -> a)
                        .map(config::getProperty)
                        .filter(Objects::nonNull)
                        .findAny().ifPresent(val -> {
                    final Object toSet;
                    if (field.getType() == String.class) {
                        toSet = val;
                    } else if (field.getType() == int.class) {
                        if ("httpPort".equals(name) && "-1".equals(val)) { // special case in case of random port
                            randomHttpPort();
                            toSet = null;
                        } else {
                            toSet = Integer.parseInt(val);
                        }
                    } else if (field.getType() == boolean.class) {
                        toSet = Boolean.parseBoolean(val);
                    } else if (field.getType() == File.class) {
                        toSet = new File(val);
                    } else {
                        toSet = null;
                    }
                    if (toSet == null) { // handled elsewhere
                        return;
                    }

                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    try {
                        field.set(this, toSet);
                    } catch (final IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    }
                });
            }

            // not trivial types
            for (final String prop : config.stringPropertyNames()) {
                if (prop.startsWith("properties.")) {
                    property(prop.substring("properties.".length()), config.getProperty(prop));
                } else if (prop.startsWith("users.")) {
                    user(prop.substring("users.".length()), config.getProperty(prop));
                } else if (prop.startsWith("roles.")) {
                    role(prop.substring("roles.".length()), config.getProperty(prop));
                } else if (prop.startsWith("cxf.servlet.params.")) {
                    cxfServletParam(prop.substring("cxf.servlet.params.".length()), config.getProperty(prop));
                } else if (prop.startsWith("connector.")) { // created in container
                    property(prop, config.getProperty(prop));
                } else if (prop.equals("realm")) {
                    final ObjectRecipe recipe = newRecipe(config.getProperty(prop));
                    for (final String realmConfig : config.stringPropertyNames()) {
                        if (realmConfig.startsWith("realm.")) {
                            recipe.setProperty(realmConfig.substring("realm.".length()), config.getProperty(realmConfig));
                        }
                    }
                    this.realm = Realm.class.cast(recipe.create());
                } else if (prop.equals("login")) {
                    final ObjectRecipe recipe = newRecipe(LoginConfigBuilder.class.getName());
                    for (final String nestedConfig : config.stringPropertyNames()) {
                        if (nestedConfig.startsWith("login.")) {
                            recipe.setProperty(nestedConfig.substring("login.".length()), config.getProperty(nestedConfig));
                        }
                    }
                    loginConfig = LoginConfigBuilder.class.cast(recipe.create());
                } else if (prop.equals("securityConstraint")) {
                    final ObjectRecipe recipe = newRecipe(SecurityConstaintBuilder.class.getName());
                    for (final String nestedConfig : config.stringPropertyNames()) {
                        if (nestedConfig.startsWith("securityConstraint.")) {
                            recipe.setProperty(nestedConfig.substring("securityConstraint.".length()), config.getProperty(nestedConfig));
                        }
                    }
                    securityConstraints.add(SecurityConstaintBuilder.class.cast(recipe.create()));
                } else if (prop.equals("configurationCustomizer")) {
                    final ObjectRecipe recipe = newRecipe(prop);
                    for (final String nestedConfig : config.stringPropertyNames()) {
                        if (nestedConfig.startsWith(prop + '.')) {
                            recipe.setProperty(nestedConfig.substring(prop.length() + 2 /*dot*/), config.getProperty(nestedConfig));
                        }
                    }
                    addCustomizer(Consumer.class.cast(recipe.create()));
                }
            }
        }

        public <T> T bind(final T instance) {
            final ValueTransformers transformers = getExtension(ValueTransformers.class);
            Class<? extends Object> type = instance.getClass();
            do {
                Stream.of(type.getDeclaredFields())
                        .filter(f -> f.isAnnotationPresent(CliOption.class))
                        .forEach(f -> {
                            final CliOption annotation = f.getAnnotation(CliOption.class);
                            String value = properties.getProperty(annotation.name());
                            if (value == null) {
                                value = Stream.of(annotation.alias()).map(properties::getProperty).findFirst().orElse(null);
                                if (value == null) {
                                    return;
                                }
                            }

                            value = transformers.apply(value);

                            if (!f.isAccessible()) {
                                f.setAccessible(true);
                            }
                            final Class<?> t = f.getType();
                            try {
                                if (t == String.class) {
                                    f.set(instance, value);
                                } else if (t == int.class) {
                                    f.set(instance, Integer.parseInt(value));
                                } else if (t == boolean.class) {
                                    f.set(instance, Boolean.parseBoolean(value));
                                } else {
                                    throw new IllegalArgumentException("Unsupported type " + t);
                                }
                            } catch (final IllegalAccessException iae) {
                                throw new IllegalStateException(iae);
                            }
                        });
                type = type.getSuperclass();
            } while (type != Object.class);
            return instance;
        }

        public boolean isInjectServletContainerInitializer() {
            return injectServletContainerInitializer;
        }

        public void setInjectServletContainerInitializer(final boolean injectServletContainerInitializer) {
            this.injectServletContainerInitializer = injectServletContainerInitializer;
        }

        public String getMeecrowaveProperties() {
            return meecrowaveProperties;
        }

        public void setMeecrowaveProperties(final String meecrowaveProperties) {
            this.meecrowaveProperties = meecrowaveProperties;
        }
    }

    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 TomcatWithFastSessionIDs extends InternalTomcat {
        @Override
        public void start() throws LifecycleException {
            // Use fast, insecure session ID generation for all tests
            final Server server = getServer();
            for (final Service service : server.findServices()) {
                final org.apache.catalina.Container e = service.getContainer();
                for (final org.apache.catalina.Container h : e.findChildren()) {
                    for (final org.apache.catalina.Container c : h.findChildren()) {
                        Manager m = ((org.apache.catalina.Context) c).getManager();
                        if (m == null) {
                            m = new StandardManager();
                            org.apache.catalina.Context.class.cast(c).setManager(m);
                        }
                        if (m instanceof ManagerBase) {
                            ManagerBase.class.cast(m).setSecureRandomClass(
                                    "org.apache.catalina.startup.FastNonSecureRandom");
                        }
                    }
                }
            }
            super.start();
        }
    }

    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<Meecrowave.Builder> {
    }

    public interface InstanceCustomizer extends Consumer<Tomcat> {
    }

    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);
        }
    }
}
