public Meecrowave start()

in meecrowave-core/src/main/java/org/apache/meecrowave/Meecrowave.java [434:779]


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

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

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

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

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

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

        setupJmx(configuration.isTomcatNoJmx());

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

        tomcat = new InternalTomcat();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            buildSslHostConfig.forEach(httpsConnector::addSslHostConfig);

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

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

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

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

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

        beforeStart();


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

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

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

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