/* * (C) Copyright 2006-2011 Nuxeo SAS (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Contributors: * bstefanescu * * $Id$ */ package org.nuxeo.runtime.jetty; import java.io.File; import java.util.Dictionary; import java.util.Hashtable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiWebappConstants; import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.webapp.WebAppContext; import org.nuxeo.common.Environment; import org.nuxeo.common.server.WebApplication; import org.nuxeo.runtime.deployment.preprocessor.DeploymentPreprocessor; import org.nuxeo.runtime.model.ComponentContext; import org.nuxeo.runtime.model.ComponentInstance; import org.nuxeo.runtime.model.ComponentName; import org.nuxeo.runtime.model.DefaultComponent; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; /** * @author hmalphettes */ public class JettyComponent extends DefaultComponent { public static final ComponentName NAME = new ComponentName("org.nuxeo.runtime.server"); public static final String XP_WEB_APP = "webapp"; public static final String XP_SERVLET = "servlet"; public static final String XP_FILTER = "filter"; public static final String P_SCAN_WEBDIR = "org.nuxeo.runtime.jetty.scanWebDir"; // protected Server server; // protected ContextHandlerCollection contexts = new ContextHandlerCollection(); protected ContextManager ctxMgr; private static final Log logger = LogFactory.getLog(JettyComponent.class); // public Server getServer() { //for now return null; //we could access the default jetty server which is registered as an OSGi service. //return server; // } /** * The jetty server is started by making sure that the jetty.osgi.boot bundle is also started. * * @param context * @throws Exception */ @Override public void activate(ComponentContext context) throws Exception { Bundle jettyBoot = FrameworkUtil.getBundle(JettyBootstrapActivator.class); jettyBoot.start();//won't make a difference if it is already started /* // apply bundled configuration URL cfg = null; String cfgName = Framework.getProperty("org.nuxeo.jetty.config"); if (cfgName != null) { if (cfgName.contains(":/")) { cfg = new URL(cfgName); } else { // assume a file File file = new File(cfgName); if (file.isFile()) { cfg = file.toURI().toURL(); } } } else { File file = new File(Environment.getDefault().getConfig(), "jetty.xml"); if (file.isFile()) { cfg = file.toURI().toURL(); } else { //[Hugues] look for jetty.xml directly inside the bundle: //currently not necessary. avoid for now. try { // cfg = context.getRuntimeContext().getBundle().getEntry("jetty-home/etc/jetty.xml"); // if (cfg.openConnection() == null) { // cfg = null;//does not exist // } else { // File installLocation = getBundleInstallLocation( // context.getRuntimeContext().getBundle()); // // String jettyHome = System.getProperty("jetty.home"); // if (jettyHome == null || jettyHome.length() == 0) { // System.setProperty("jetty.home", installLocation.getAbsolutePath() + File.separatorChar + "jetty-home"); // } // String jettyLogs = System.getProperty("jetty.logs"); // if (jettyLogs == null || jettyLogs.length() == 0) { // System.setProperty("jetty.logs", System.getProperty("jetty.home") + "/logs"); // } // } } catch (Throwable t) { t.printStackTrace(); } } } if (cfg != null) { XmlConfiguration configuration = new XmlConfiguration(cfg); server = (Server)configuration.configure(); } else { int p = 8080; String port = Environment.getDefault().getProperty("http_port"); if (port != null) { try { p = Integer.parseInt(port); } catch (NumberFormatException e) { // do noting } } server = new Server(p); } Handler[] handlers = server.getHandlers(); if (handlers != null && handlers.length > 0 && handlers[0] instanceof ContextHandlerCollection) { contexts = (ContextHandlerCollection)handlers[0]; } else if (handlers == null || handlers.length == 0) { // dynamic configuration contexts = new ContextHandlerCollection(); RequestLogHandler requestLogHandler = new RequestLogHandler(); File logDir = Environment.getDefault().getLog(); logDir.mkdirs(); File logFile = new File(logDir, "jetty.log"); NCSARequestLog requestLog = new NCSARequestLog(logFile.getAbsolutePath()); requestLogHandler.setRequestLog(requestLog); //handlers = new Handler[] {contexts, new DefaultHandler(), requestLogHandler}; handlers = new Handler[] {contexts, requestLogHandler}; server.setHandlers(handlers); server.setSendServerVersion(true); server.setStopAtShutdown(true); } else { // add only the contexts handler contexts = new ContextHandlerCollection(); Handler[] newHandlers = new Handler[handlers.length+1]; newHandlers[0] = contexts; System.arraycopy(handlers, 0, newHandlers, 0, handlers.length); server.setHandlers(newHandlers); } server.start(); */ } /** * Nothing to do. Unless we decide that we must be in charge of stopping the jetty server. */ @Override public void deactivate(ComponentContext context) throws Exception { // server.stop(); // server = null; } @Override public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) throws Exception { if (XP_WEB_APP.equals(extensionPoint)) { File home = Environment.getDefault().getHome(); WebApplication app = (WebApplication)contribution; if (app.needsWarPreprocessing()) { logger.info("Starting deployment preprocessing"); DeploymentPreprocessor dp = new DeploymentPreprocessor(home); dp.init(); dp.predeploy(); logger.info("Deployment preprocessing terminated"); } Dictionary<String, String> props = new Hashtable<String, String>(); String root = app.getWebRoot(); String webappFolderPath = null; if (root != null) { File file = null; //[Hugues] look for paths that start with ./ //and in that case consider that it is inside the bundle itself. if (!root.startsWith("./")) { file = new File(home, root); } if (file == null || !file.exists()) { File bundle = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation( contributor.getContext().getBundle()); if (root.startsWith("./")) { root = root.substring(2); } file = new File(bundle, root); } webappFolderPath = file.getAbsolutePath(); // ctx.setWar(file.getAbsolutePath()); } String webXml = app.getConfigurationFile(); if (webXml != null) { File file = new File(home, webXml); File file1 = null; if (!file.exists()) { if (webXml.startsWith("./")) { webXml = webXml.substring(2); } File bundle = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation( contributor.getContext().getBundle()); file1 = new File(bundle, webXml); if (!file1.exists()) { throw new IllegalArgumentException("Unable to locate " + file.getAbsolutePath() + " and unable to locate " + file1.getAbsolutePath()); } props.put(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH, file1.getAbsolutePath()); } else { props.put(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH, file.getAbsolutePath()); } // ctx.setDescriptor(file.getAbsolutePath()); } File defWebXml = new File(Environment.getDefault().getConfig(), "default-web.xml"); if (defWebXml.isFile()) { // ctx.setDefaultsDescriptor(defWebXml.getAbsolutePath()); props.put(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH, defWebXml.getAbsolutePath()); } //make sure that the contributor is started otherwise jettybootstrap crashes with an ugly NPE. //this issue is probably fixed in a later version of jetty. contributor.getContext().getBundle().start(); JettyBootstrapActivator.registerWebapplication(contributor.getContext().getBundle(), webappFolderPath, app.getContextPath(), props); // org.eclipse.jetty.util.log.Log.setLog(new Log4JLogger(logger)); } else if (XP_FILTER.equals(extensionPoint)) { ctxMgr.addFilter((FilterDescriptor)contribution); } else if (XP_SERVLET.equals(extensionPoint)) { ctxMgr.addServlet((ServletDescriptor)contribution); } } @Override public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) throws Exception { if (XP_WEB_APP.equals(extensionPoint)) { JettyBootstrapActivator.unregister(((WebApplication)contribution).getContextPath()); } else if (XP_FILTER.equals(extensionPoint)) { ctxMgr.removeFilter((FilterDescriptor)contribution); } else if (XP_SERVLET.equals(extensionPoint)) { ctxMgr.removeServlet((ServletDescriptor)contribution); } } @Override public <T> T getAdapter(Class<T> adapter) { if (adapter == org.eclipse.jetty.server.Server.class) { return null; //return adapter.cast(server); } return null; } private static String SLASH_ESCAPED_FOR_LDAP = "\2f"; protected void addFilter(FilterDescriptor contribution, ComponentInstance contributor) { String contextPath = contribution.getContext(); if (contextPath.startsWith("/")) { if (contextPath.length() > 1) { contextPath = contextPath.substring(1); } else { contextPath = ""; } } //search for the webapp with that context path. BundleContext bc = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext(); String filter = OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH + "=" + SLASH_ESCAPED_FOR_LDAP + contextPath; try { ServiceReference[] refs = bc.getServiceReferences(ContextHandler.class.getName(), filter); for (ServiceReference r : refs) { } } catch (InvalidSyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } WebAppContext webAppContext = null; // webAppContext.addFilter ... } protected void addServlet(ServletDescriptor contribution, ComponentInstance contributor) { } }