001/*
002 * (C) Copyright 2006-2011 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     bstefanescu, jcarsique
016 */
017package org.nuxeo.runtime.tomcat;
018
019import java.io.File;
020import java.io.IOException;
021import java.lang.management.ManagementFactory;
022
023import javax.management.JMException;
024import javax.management.MBeanServer;
025import javax.management.ObjectName;
026
027import org.apache.catalina.Container;
028import org.apache.catalina.Lifecycle;
029import org.apache.catalina.LifecycleEvent;
030import org.apache.catalina.LifecycleListener;
031import org.apache.catalina.Loader;
032import org.apache.catalina.core.ContainerBase;
033import org.apache.catalina.util.ServerInfo;
034import org.apache.commons.logging.Log;
035import org.apache.commons.logging.LogFactory;
036import org.nuxeo.osgi.application.FrameworkBootstrap;
037import org.nuxeo.osgi.application.MutableClassLoader;
038import org.nuxeo.runtime.tomcat.dev.DevFrameworkBootstrap;
039import org.nuxeo.runtime.tomcat.dev.NuxeoDevWebappClassLoader;
040
041/**
042 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
043 */
044public class NuxeoLauncher implements LifecycleListener {
045
046    public static final String DEV_BUNDLES_NAME = "org.nuxeo:type=sdk,name=dev-bundles";
047
048    public static final String WEB_RESOURCES_NAME = "org.nuxeo:type=sdk,name=web-resources";
049
050    static final Log log = LogFactory.getLog(NuxeoLauncher.class);
051
052    protected boolean shared; // TODO
053
054    protected String home = "nxserver";
055
056    protected boolean automaticReload = true;
057
058    protected FrameworkBootstrap bootstrap;
059
060    public void setShared(boolean shared) {
061        this.shared = shared;
062    }
063
064    public boolean isShared() {
065        return shared;
066    }
067
068    public void setHome(String home) {
069        this.home = home;
070    }
071
072    public String getHome() {
073        return home;
074    }
075
076    public void setAutomaticReload(boolean value) {
077        automaticReload = value;
078    }
079
080    public boolean getAutomaticReload() {
081        return automaticReload;
082    }
083
084    @Override
085    public void lifecycleEvent(LifecycleEvent event) {
086        Lifecycle lf = event.getLifecycle();
087        if (lf instanceof ContainerBase) {
088            Loader loader = ((Container) lf).getLoader();
089            if (loader instanceof NuxeoWebappLoader) {
090                handleEvent((NuxeoWebappLoader) loader, event);
091            }
092        }
093    }
094
095    protected void handleEvent(NuxeoWebappLoader loader, LifecycleEvent event) {
096        String type = event.getType();
097        try {
098            MutableClassLoader cl = (MutableClassLoader) loader.getClassLoader();
099            boolean devMode = cl instanceof NuxeoDevWebappClassLoader;
100            if (type == Lifecycle.CONFIGURE_START_EVENT) {
101                File homeDir = resolveHomeDirectory(loader);
102                if (devMode) {
103                    bootstrap = new DevFrameworkBootstrap(cl, homeDir);
104                    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
105                    server.registerMBean(bootstrap, new ObjectName(DEV_BUNDLES_NAME));
106                    server.registerMBean(cl, new ObjectName(WEB_RESOURCES_NAME));
107                    ((NuxeoDevWebappClassLoader) cl).setBootstrap((DevFrameworkBootstrap) bootstrap);
108                } else {
109                    bootstrap = new FrameworkBootstrap(cl, homeDir);
110                }
111                bootstrap.setHostName("Tomcat");
112                bootstrap.setHostVersion(ServerInfo.getServerNumber());
113                bootstrap.initialize();
114            } else if (type == Lifecycle.START_EVENT) {
115                bootstrap.start();
116            } else if (type == Lifecycle.STOP_EVENT) {
117                bootstrap.stop();
118                if (devMode) {
119                    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
120                    server.unregisterMBean(new ObjectName(DEV_BUNDLES_NAME));
121                    server.unregisterMBean(new ObjectName(WEB_RESOURCES_NAME));
122                }
123            }
124        } catch (IOException | JMException | ReflectiveOperationException e) {
125            log.error("Failed to handle event: " + type, e);
126        }
127    }
128
129    protected File resolveHomeDirectory(NuxeoWebappLoader loader) {
130        String path = null;
131        if (home.startsWith("/") || home.startsWith("\\") || home.contains(":/") || home.contains(":\\")) {
132            // absolute
133            path = home;
134        } else if (home.startsWith("${catalina.base}")) {
135            path = getTomcatHome() + home.substring("${catalina.base}".length());
136        } else {
137            try {
138                File baseDir = loader.getBaseDir();
139                return new File(baseDir, home);
140            } catch (ReflectiveOperationException e) {
141                return null;
142            }
143        }
144        return new File(path);
145    }
146
147    public String getTomcatHome() {
148        String tomcatHome = System.getProperty("catalina.base");
149        if (tomcatHome == null) {
150            tomcatHome = System.getProperty("catalina.home");
151        }
152        return tomcatHome;
153    }
154
155}