001/* 002 * (C) Copyright 2011-2014 Nuxeo SA (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-2.1.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 * Florent Guillaume 016 * Julien Carsique 017 */ 018package org.nuxeo.runtime.deployment; 019 020import static org.nuxeo.common.Environment.JBOSS_HOST; 021import static org.nuxeo.common.Environment.NUXEO_CONFIG_DIR; 022import static org.nuxeo.common.Environment.NUXEO_DATA_DIR; 023import static org.nuxeo.common.Environment.NUXEO_LOG_DIR; 024import static org.nuxeo.common.Environment.NUXEO_RUNTIME_HOME; 025import static org.nuxeo.common.Environment.NUXEO_TMP_DIR; 026import static org.nuxeo.common.Environment.NUXEO_WEB_DIR; 027import static org.nuxeo.common.Environment.TOMCAT_HOST; 028 029import java.io.BufferedReader; 030import java.io.File; 031import java.io.IOException; 032import java.io.InputStream; 033import java.io.InputStreamReader; 034import java.sql.Driver; 035import java.sql.DriverManager; 036import java.sql.SQLException; 037import java.util.ArrayList; 038import java.util.Arrays; 039import java.util.Enumeration; 040import java.util.HashMap; 041import java.util.List; 042import java.util.Map; 043import java.util.Set; 044 045import javax.servlet.ServletContext; 046import javax.servlet.ServletContextEvent; 047import javax.servlet.ServletContextListener; 048 049import org.apache.commons.logging.Log; 050import org.apache.commons.logging.LogFactory; 051import org.nuxeo.osgi.application.loader.FrameworkLoader; 052import org.osgi.framework.BundleException; 053 054/** 055 * This is called at WAR startup and starts the Nuxeo OSGi runtime and registers the Nuxeo bundles with it. 056 * <p> 057 * This class must be configured as a {@code <listener>/<listener-class>} in {@code META-INF/web.xml}. 058 * <p> 059 * It uses servlet init parameters defined through {@code <context-param>/<param-name>/<param-value>} in web.xml. 060 * Allowable parameter names come from {@link org.nuxeo.common.Environment}, mainly 061 * {@link org.nuxeo.common.Environment#NUXEO_RUNTIME_HOME NUXEO_RUNTIME_HOME} and 062 * {@link org.nuxeo.common.Environment#NUXEO_CONFIG_DIR NUXEO_CONFIG_DIR}, but also 063 * {@link org.nuxeo.common.Environment#NUXEO_DATA_DIR NUXEO_DATA_DIR}, 064 * {@link org.nuxeo.common.Environment#NUXEO_LOG_DIR NUXEO_LOG_DIR}, {@link org.nuxeo.common.Environment#NUXEO_TMP_DIR 065 * NUXEO_TMP_DIR} and {@link org.nuxeo.common.Environment#NUXEO_WEB_DIR NUXEO_WEB_DIR}. 066 */ 067public class NuxeoStarter implements ServletContextListener { 068 069 private static final Log log = LogFactory.getLog(NuxeoStarter.class); 070 071 /** Default location of the home in the server current directory. */ 072 private static final String DEFAULT_HOME = "nuxeo"; 073 074 /** 075 * Name of the file listing Nuxeo bundles. If existing, this file will be used at start, else 076 * {@code "/WEB-INF/lib/"} will be scanned. 077 * 078 * @since 5.9.3 079 * @see #findBundles(ServletContext) 080 */ 081 public static final String NUXEO_BUNDLES_LIST = ".nuxeo-bundles"; 082 083 protected final Map<String, Object> env = new HashMap<>(); 084 085 protected List<File> bundleFiles = new ArrayList<>(); 086 087 @Override 088 public void contextInitialized(ServletContextEvent event) { 089 try { 090 long startTime = System.currentTimeMillis(); 091 start(event); 092 long finishedTime = System.currentTimeMillis(); 093 @SuppressWarnings("boxing") 094 Double duration = (finishedTime - startTime) / 1000.0; 095 log.info(String.format("Nuxeo framework started in %.1f sec.", duration)); 096 } catch (IOException | BundleException e) { 097 throw new RuntimeException(e); 098 } 099 } 100 101 @Override 102 public void contextDestroyed(ServletContextEvent event) { 103 try { 104 stop(); 105 } catch (BundleException e) { 106 throw new RuntimeException(e); 107 } 108 } 109 110 protected void start(ServletContextEvent event) throws IOException, BundleException { 111 ServletContext servletContext = event.getServletContext(); 112 findBundles(servletContext); 113 findEnv(servletContext); 114 115 ClassLoader cl = getClass().getClassLoader(); 116 File home = new File((String) env.get(NUXEO_RUNTIME_HOME)); 117 FrameworkLoader.initialize(cl, home, bundleFiles, env); 118 FrameworkLoader.start(); 119 } 120 121 protected void stop() throws BundleException { 122 FrameworkLoader.stop(); 123 Enumeration<Driver> drivers = DriverManager.getDrivers(); 124 while (drivers.hasMoreElements()) { 125 Driver driver = drivers.nextElement(); 126 try { 127 DriverManager.deregisterDriver(driver); 128 log.warn(String.format("Deregister JDBC driver: %s", driver)); 129 } catch (SQLException e) { 130 log.error(String.format("Error deregistering JDBC driver %s", driver), e); 131 } 132 } 133 } 134 135 protected void findBundles(ServletContext servletContext) throws IOException { 136 InputStream bundlesListStream = servletContext.getResourceAsStream("/WEB-INF/" + NUXEO_BUNDLES_LIST); 137 if (bundlesListStream != null) { 138 File lib = new File(servletContext.getRealPath("/WEB-INF/lib/")); 139 try (BufferedReader reader = new BufferedReader(new InputStreamReader(bundlesListStream))) { 140 String bundleName; 141 while ((bundleName = reader.readLine()) != null) { 142 bundleFiles.add(new File(lib, bundleName)); 143 } 144 } 145 } 146 if (bundleFiles.isEmpty()) { // Fallback on directory scan 147 File root = new File(servletContext.getRealPath("/")); 148 Set<String> ctxpaths = servletContext.getResourcePaths("/WEB-INF/lib/"); 149 if (ctxpaths != null) { 150 for (String ctxpath : ctxpaths) { 151 if (!ctxpath.endsWith(".jar")) { 152 continue; 153 } 154 bundleFiles.add(new File(root, ctxpath)); 155 } 156 } 157 } 158 } 159 160 protected void findEnv(ServletContext servletContext) { 161 for (String param : Arrays.asList( // 162 NUXEO_RUNTIME_HOME, // 163 NUXEO_CONFIG_DIR, // 164 NUXEO_DATA_DIR, // 165 NUXEO_LOG_DIR, // 166 NUXEO_TMP_DIR, // 167 NUXEO_WEB_DIR)) { 168 String value = servletContext.getInitParameter(param); 169 if (value != null && !"".equals(value.trim())) { 170 env.put(param, value); 171 } 172 } 173 // default env values 174 if (!env.containsKey(NUXEO_CONFIG_DIR)) { 175 String webinf = servletContext.getRealPath("/WEB-INF"); 176 env.put(NUXEO_CONFIG_DIR, webinf); 177 } 178 if (!env.containsKey(NUXEO_RUNTIME_HOME)) { 179 File home = new File(DEFAULT_HOME); 180 env.put(NUXEO_RUNTIME_HOME, home.getAbsolutePath()); 181 } 182 // host 183 if (getClass().getClassLoader().getClass().getName().startsWith("org.jboss.classloader")) { 184 env.put(FrameworkLoader.HOST_NAME, JBOSS_HOST); 185 } else if (servletContext.getClass().getName().startsWith("org.apache.catalina")) { 186 env.put(FrameworkLoader.HOST_NAME, TOMCAT_HOST); 187 } 188 } 189 190}