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