Package com.bsb.common.vaadin.embed

Source Code of com.bsb.common.vaadin.embed.AbstractEmbedVaadinTomcat$TomcatLifecycleListener

/*
* Copyright 2012 the original author or authors.
*
* 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 com.bsb.common.vaadin.embed;

import com.bsb.common.vaadin.embed.util.BrowserUtils;
import com.google.common.io.Files;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.Serializable;

/**
* A base {@link EmbedVaadinServer} implementation based on Apache Tomcat.
*
* @author Stephane Nicoll
*/
public abstract class AbstractEmbedVaadinTomcat implements EmbedVaadinServer, Serializable {

    public static final String PRODUCTION_MODE_PARAM = "productionMode";

    private static final long serialVersionUID = 8211718040277785632L;

    private static final Logger logger = LoggerFactory.getLogger(AbstractEmbedVaadinTomcat.class);

    private final EmbedVaadinConfig config;

    // Note this class has to be serializable to make sure the session can be saved when
    // Tomcat stops

    private final transient Tomcat tomcat;
    private final transient Thread shutdownThread;
    private final transient File baseDir;
    private transient Context context;

    /**
     * Creates a new instance with the specified config.
     *
     * @param config the config to use
     */
    protected AbstractEmbedVaadinTomcat(EmbedVaadinConfig config) {
        this.config = config;

        this.tomcat = new Tomcat();
        this.shutdownThread = new TomcatShutdownHook(tomcat);
        this.baseDir = Files.createTempDir();
    }

    /**
     * Configures the current {@link Tomcat} instance with the current
     * {@link EmbedVaadinConfig config}.
     * <p/>
     * Port, context and servlet configuration(s) should be added here. Consider
     * calling {@link #initConfiguration()} to perform a basic initialization
     * of the tomcat server.
     *
     * @see #getTomcat()
     * @see #getConfig()
     * @see #initConfiguration()
     * @see #initializeVaadinServlet(com.vaadin.terminal.gwt.server.AbstractApplicationServlet)
     */
    protected abstract void configure();

    public void start() {
        configure();
        try {
            doStart();
            addShutdownHook();
        } catch (LifecycleException e) {
            throw new IllegalStateException("Failed to start tomcat", e);
        }
    }

    public boolean isWaiting() {
        return config.isWaiting();
    }

    public EmbedVaadinConfig getConfig() {
        return config;
    }

    public void stop() {
        try {
            doStop();
        } catch (LifecycleException e) {
            logger.warn("Failed to stop tomcat", e);
        }
    }

    /**
     * Returns the {@link Tomcat} instance.
     */
    protected Tomcat getTomcat() {
        return tomcat;
    }

    /**
     * Returns the {@link Context} to use for the webapp.
     */
    protected Context getContext() {
        if (context == null) {
            context = getTomcat().addContext(getConfig().getContextPath(),
                    getConfig().getContextRootDirectory().getAbsolutePath());
        }
        return context;
    }

    /**
     * Adds the basic and default configuration of the the current {@link Tomcat}
     * instance with the current {@link EmbedVaadinConfig config}.
     * <p/>
     * Does not map any servlet, though. Sub-classes are responsible to do this
     */
    protected void initConfiguration() {
        getTomcat().setBaseDir(baseDir.getAbsolutePath());

        // Setup HTTP port listening
        getTomcat().setPort(getConfig().getPort());

        // Setup vaadin production mode
        getContext().addParameter(PRODUCTION_MODE_PARAM, String.valueOf(getConfig().isProductionMode()));
    }

    /**
     * Initializes the vaadin servlet and maps it to <tt>/*</tt>.
     * <p/>
     * Returns the associated {@link Wrapper} for further customization.
     *
     * @param servlet the servlet to use to handle vaadin calls.
     * @param <T> the type of the servlet
     * @return the created wrapper for the servlet
     */
    protected <T extends AbstractApplicationServlet> Wrapper initializeVaadinServlet(T servlet) {
        // Setup vaadin servlet
        final Wrapper wrapper = Tomcat.addServlet(getContext(),
                "vaadin", servlet);
        if (getConfig().getWidgetSet() != null) {
            wrapper.addInitParameter("widgetset", getConfig().getWidgetSet());
        }

        wrapper.addMapping("/*");
        return wrapper;
    }

    // private helpers

    /**
     * Fires the embedded tomcat that is assumed to be fully configured.
     *
     * @throws LifecycleException if tomcat failed to start
     */
    private void doStart() throws LifecycleException {
        tomcat.getServer().addLifecycleListener(new TomcatLifecycleListener());
        logger.info("Deploying application to [" + getConfig().getDeployUrl() + "]");
        tomcat.start();

        // Let's set the port that was used to actually start the application if necessary
        if (getConfig().getPort() == EmbedVaadinConfig.DEFAULT_PORT) {
            getConfig().setPort(getTomcat().getConnector().getLocalPort());
        }

        logger.info("Application has been deployed to [" + getConfig().getDeployUrl() + "]");
        if (config.shouldOpenBrowser()) {
            BrowserUtils.openBrowser(getConfig().getOpenBrowserUrl());
        }
        if (isWaiting()) {
            tomcat.getServer().await();
        }
    }

    /**
     * Stops the embedded tomcat.
     *
     * @throws LifecycleException if tomcat failed to stop
     */
    private void doStop() throws LifecycleException {
        logger.info("Stopping tomcat.");
        long startTime = System.currentTimeMillis();
        tomcat.stop();
        long duration = System.currentTimeMillis() - startTime;
        logger.info("Tomcat shutdown finished in " + duration + " ms.");
    }

    /**
     * Adds a  shutdown hook to stop the server when the JVM is stopped.
     */
    private void addShutdownHook() {
        Runtime.getRuntime().addShutdownHook(shutdownThread);
    }

    /**
     * Removes the shutdown hook in case the server is stopped manually
     */
    private void removeShutdownHook() {
        Runtime.getRuntime().removeShutdownHook(shutdownThread);
    }

    private static final class TomcatShutdownHook extends Thread {

        private final Tomcat tomcat;

        private TomcatShutdownHook(Tomcat tomcat) {
            this.tomcat = tomcat;
        }

        /**
         * Stops the server when the VM exits.
         */
        public void run() {
            try {
                tomcat.stop();
                logger.info("Stopped Tomcat");
            } catch (LifecycleException e) {
                logger.warn("Failed to stop Tomcat", e);
            }
        }
    }

    private final class TomcatLifecycleListener implements LifecycleListener {

        /**
         * Listens for stop event only in order to remove the shutdown hook before the VM
         * actually shuts down.
         *
         * @param event the event to listen to.
         */
        public void lifecycleEvent(LifecycleEvent event) {
            if (event.getType().equals(Lifecycle.STOP_EVENT)) {
                removeShutdownHook();
            }
        }
    }
}
TOP

Related Classes of com.bsb.common.vaadin.embed.AbstractEmbedVaadinTomcat$TomcatLifecycleListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.