All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testatoo.container.impl.TomcatContainer Maven / Gradle / Ivy

There is a newer version: 1.1.ga
Show newest version
/**
 * Copyright (C) 2008 Ovea 
 *
 * Licensed 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.testatoo.container.impl;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Catalina;
import org.apache.catalina.startup.Tomcat;
import org.testatoo.container.ContainerConfiguration;
import org.testatoo.container.ContainerSkeleton;
import org.testatoo.container.util.FileUtils;

import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.CountDownLatch;

import static org.testatoo.container.util.ClassloaderUtils.tryEnhanceContextClassloaderWithClasspath;
import static org.testatoo.container.util.ResourceUtils.contextResource;

public final class TomcatContainer extends ContainerSkeleton {

    public static final String PROPERTY_TOMCAT_ENV = "tomcat.env";
    public static final String PROPERTY_TOMCAT_CONF = "tomcat.conf";

    private Thread serverThread;
    private CountDownLatch stop;

    public TomcatContainer(ContainerConfiguration properties) {
        super(properties);
    }

    protected Tomcat buildServer() {
        // Create tomcat structure
        File homeDir = FileUtils.createTemporaryFolder("tomcat-");
        File confDir = new File(homeDir, "conf");
        File webappsDir = new File(homeDir, "webapps");
        new File(homeDir, "logs").mkdir();
        confDir.mkdir();
        webappsDir.mkdir();
        try {
            FileUtils.copyURLToFile(contextResource("org/testatoo/container/impl/web.xml"), new File(confDir, "web.xml"));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }

        // Server classpath
        if (settings().hasServerClassPath()) {
            tryEnhanceContextClassloaderWithClasspath(settings().serverClassPath());
        }

        // Create server if it is configured through a server.xml file
        if (settings().has(PROPERTY_TOMCAT_CONF)) {
            Tomcat server = new Tomcat();
            Catalina catalina = new Catalina();
            server.setBaseDir(homeDir.getAbsolutePath());
            File conf = new File(settings().get(PROPERTY_TOMCAT_CONF));
            if (!conf.exists() || !conf.canRead())
                throw new IllegalArgumentException("Cannot access configuration file " + conf);

            catalina.setConfigFile(conf.getAbsolutePath());
            catalina.load();

            // In tomcat config file, you can set the server port.
            // If it is set, we must get it.
            // But as Tomcat supports several connectors, we can only reset the port of the first connector we find, hopping it will be the one we want...
            for (Service service : catalina.getServer().findServices()) {
                try {
                    settings().port(service.findConnectors()[0].getPort());
                    break;
                } catch (Exception e) {
                }
            }
            return server;
        }

        // Otherwise create an embedded server
        Tomcat server = new Tomcat();
        server.setBaseDir(homeDir.getAbsolutePath());
        server.setHostname("localhost");
        server.getServer().setAddress("localhost");
        server.setPort(port());
        server.getHost().setAppBase(webappsDir.getAbsolutePath());
        server.enableNaming();

        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(port());

        server.setConnector(connector);
        server.getService().addConnector(connector);

        // Create webapp loader with extra classpath of there are some
        WebappLoader loader = new WebappLoader();
        if (settings().hasWebappClassPath()) {
            for (URL url : settings().webappClassPath()) {
                loader.addRepository(url.toString());
            }
        }

        // Create context
        //Context context = server.addContext(contextPath(), webappRoot().getAbsolutePath());
        Context context = null;
        try {
            context = server.addWebapp(contextPath(), webappRoot().getAbsolutePath());
        } catch (ServletException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        context.setLoader(loader);
        context.setReloadable(true);

        // Set optionnal context.xml file
        if (settings().has(PROPERTY_TOMCAT_ENV)) {
            File ctx = new File(settings().get(PROPERTY_TOMCAT_ENV));
            if (!ctx.exists() || !ctx.canRead())
                throw new IllegalArgumentException("Cannot access configuration file " + ctx);
            try {
                context.setConfigFile(new File(ctx.getAbsolutePath()).toURI().toURL());
            } catch (MalformedURLException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        } else {
            File ctx = new File(webappRoot(), "META-INF/context.xml");
            try {
                context.setConfigFile(new File(ctx.getAbsolutePath()).toURI().toURL());
            } catch (MalformedURLException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        return server;
    }

    protected void start(final Tomcat server) {
        final CountDownLatch startupComplete = new CountDownLatch(1);
        stop = new CountDownLatch(1);
        serverThread = new Thread("Tomcat Server") {
            @Override
            public void run() {
                try {
                    server.start();
                    startupComplete.countDown();
                    stop.await();
                } catch (LifecycleException e) {
                    throw new RuntimeException(e.getMessage(), e);
                } catch (InterruptedException ignored) {
                } finally {
                    serverThread = null;
                    stop = null;
                }
            }
        };
        serverThread.start();
        try {
            startupComplete.await();
        } catch (InterruptedException ignored) {
        }
    }

    protected void stop(final Tomcat server) {
        try {
            server.stop();
            server.getConnector().destroy();
        } catch (LifecycleException e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (stop != null) stop.countDown();
            stop = null;
            serverThread = null;
        }
    }

    @Override
    protected boolean isRunning(Tomcat embedded) {
        return serverThread != null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy