diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java new file mode 100644 index 00000000000..586513776f5 --- /dev/null +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java @@ -0,0 +1,336 @@ +// ======================================================================== +// Copyright (c) 2012 Intalio, Inc. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package org.eclipse.jetty.osgi.boot; + + +import java.io.File; +import java.net.URL; +import java.util.Dictionary; +import java.util.HashMap; + +import org.eclipse.jetty.deploy.App; +import org.eclipse.jetty.deploy.AppProvider; +import org.eclipse.jetty.deploy.DeploymentManager; +import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; +import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory; +import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.component.AbstractLifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.JarResource; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.xml.XmlConfiguration; +import org.osgi.framework.Bundle; + + + + +/** + * AbstractContextProvider + * + * + */ +public abstract class AbstractContextProvider extends AbstractLifeCycle implements AppProvider +{ + private static final Logger LOG = Log.getLogger(AbstractContextProvider.class); + + private DeploymentManager _deploymentManager; + + + private ServerInstanceWrapper _serverWrapper; + + + + + /* ------------------------------------------------------------ */ + /** + * BundleApp + * + * + */ + public class BundleApp extends App + { + private String _contextFile; + private Bundle _bundle; + private ContextHandler _contextHandler; + private Dictionary _properties; + private boolean _configured = false; + + public BundleApp(DeploymentManager manager, AppProvider provider, String originId, Bundle bundle, String contextFile) + { + super(manager, provider, originId); + _bundle = bundle; + _contextFile = contextFile; + _properties = bundle.getHeaders(); + } + + public BundleApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary properties, String contextFile, String originId) + { + super(manager, provider, originId); + _contextFile = contextFile; + _properties = properties; + _bundle = bundle; + } + + public String getContextFile () + { + return _contextFile; + } + + public void setContextHandler(ContextHandler h) + { + _contextHandler = h; + } + + public ContextHandler getContextHandler() + throws Exception + { + configureContextHandler(); + return _contextHandler; + } + + + public void configureContextHandler() + throws Exception + { + if (_configured) + return; + + _configured = true; + + //Override for bundle root may have been set + String bundleOverrideLocation = (String)_properties.get(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE); + if (bundleOverrideLocation == null) + bundleOverrideLocation = (String)_properties.get(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE); + + //Location on filesystem of bundle or the bundle override location + File bundleLocation = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(_bundle); + File root = (bundleOverrideLocation==null?bundleLocation:new File(bundleOverrideLocation)); + Resource rootResource = Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(root.toURI().toURL())); + + //try and make sure the rootResource is useable - if its a jar then make it a jar file url + if (rootResource.exists()&& !rootResource.isDirectory() && !rootResource.toString().startsWith("jar:")) + { + Resource jarResource = JarResource.newJarResource(rootResource); + if (jarResource.exists() && jarResource.isDirectory()) + rootResource = jarResource; + } + + //Set the base resource of the ContextHandler, if not already set, can also be overridden by the context xml file + if (_contextHandler.getBaseResource() == null) + { + _contextHandler.setBaseResource(rootResource); + } + + //Use a classloader that knows about the common jetty parent loader, and also the bundle + OSGiClassLoader classLoader = new OSGiClassLoader(getServerInstanceWrapper().getParentClassLoaderForWebapps(), _bundle); + + //if there is a context file, find it and apply it + if (_contextFile == null && _contextHandler == null) + throw new IllegalStateException("No context file or ContextHandler"); + + if (_contextFile != null) + { + //apply the contextFile, creating the ContextHandler, the DeploymentManager will register it in the ContextHandlerCollection + Resource res = null; + + //try to find the context file in the filesystem + if (_contextFile.startsWith("/")) + res = getFileAsResource(_contextFile); + + //try to find it relative to jetty home + if (res == null) + { + //See if the specific server we are related to has jetty.home set + String jettyHome = (String)getServerInstanceWrapper().getServer().getAttribute(OSGiServerConstants.JETTY_HOME); + if (jettyHome != null) + res = getFileAsResource(jettyHome, _contextFile); + + //try to see if a SystemProperty for jetty.home is set + if (res == null) + { + jettyHome = System.getProperty(OSGiServerConstants.JETTY_HOME); + + if (jettyHome != null) + { + if (jettyHome.startsWith("\"") || jettyHome.startsWith("'")) + jettyHome = jettyHome.substring(1); + if (jettyHome.endsWith("\"") || (jettyHome.endsWith("'"))) + jettyHome = jettyHome.substring(0,jettyHome.length()-1); + + res = getFileAsResource(jettyHome, _contextFile); + if (LOG.isDebugEnabled()) LOG.debug("jetty home context file:"+res); + } + } + } + + //try to find it relative to an override location that has been specified + if (res == null) + { + if (bundleOverrideLocation != null) + { + res = getFileAsResource(Resource.newResource(bundleOverrideLocation).getFile(), _contextFile); + if (LOG.isDebugEnabled()) LOG.debug("Bundle override location context file:"+res); + } + } + + //try to find it relative to the bundle in which it is being deployed + if (res == null) + { + if (_contextFile.startsWith("./")) + _contextFile = _contextFile.substring(1); + + if (!_contextFile.startsWith("/")) + _contextFile = "/" + _contextFile; + + URL contextURL = _bundle.getEntry(_contextFile); + if (contextURL != null) + res = Resource.newResource(contextURL); + } + + //apply the context xml file, either to an existing ContextHandler, or letting the + //it create the ContextHandler as necessary + if (res != null) + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + + LOG.debug("Context classloader = " + cl); + try + { + Thread.currentThread().setContextClassLoader(classLoader); + + XmlConfiguration xmlConfiguration = new XmlConfiguration(res.getInputStream()); + HashMap properties = new HashMap(); + //put the server instance in + properties.put("Server", getServerInstanceWrapper().getServer()); + //put in the location of the bundle root + properties.put("bundle.root", rootResource.toString()); + + // insert the bundle's location as a property. + xmlConfiguration.getProperties().putAll(properties); + + if (_contextHandler == null) + _contextHandler = (ContextHandler) xmlConfiguration.configure(); + else + xmlConfiguration.configure(_contextHandler); + } + finally + { + Thread.currentThread().setContextClassLoader(cl); + } + } + } + + //Set up the class loader we created + _contextHandler.setClassLoader(classLoader); + + + //If a bundle/service property specifies context path, let it override the context xml + String contextPath = (String)_properties.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); + if (contextPath == null) + contextPath = (String)_properties.get(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH); + if (contextPath != null) + _contextHandler.setContextPath(contextPath); + } + + + private Resource getFileAsResource (String dir, String file) + { + Resource r = null; + try + { + File asFile = new File (dir, file); + if (asFile.exists()) + r = Resource.newResource(asFile); + } + catch (Exception e) + { + r = null; + } + return r; + } + + private Resource getFileAsResource (String file) + { + Resource r = null; + try + { + File asFile = new File (file); + if (asFile.exists()) + r = Resource.newResource(asFile); + } + catch (Exception e) + { + r = null; + } + return r; + } + + private Resource getFileAsResource (File dir, String file) + { + Resource r = null; + try + { + File asFile = new File (dir, file); + if (asFile.exists()) + r = Resource.newResource(asFile); + } + catch (Exception e) + { + r = null; + } + return r; + } + } + + /* ------------------------------------------------------------ */ + public AbstractContextProvider(ServerInstanceWrapper wrapper) + { + _serverWrapper = wrapper; + } + + + /* ------------------------------------------------------------ */ + public ServerInstanceWrapper getServerInstanceWrapper() + { + return _serverWrapper; + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.deploy.AppProvider#createContextHandler(org.eclipse.jetty.deploy.App) + */ + public ContextHandler createContextHandler(App app) throws Exception + { + if (app == null) + return null; + if (!(app instanceof BundleApp)) + throw new IllegalStateException(app+" is not a BundleApp"); + + //Create a ContextHandler suitable to deploy in OSGi + return ((BundleApp)app).getContextHandler(); + } + + /* ------------------------------------------------------------ */ + public void setDeploymentManager(DeploymentManager deploymentManager) + { + _deploymentManager = deploymentManager; + } + + /* ------------------------------------------------------------ */ + public DeploymentManager getDeploymentManager() + { + return _deploymentManager; + } +} diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java index ad471f41704..e492db518c9 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java @@ -1,3 +1,15 @@ +// ======================================================================== +// Copyright (c) 2012 Intalio, Inc. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== package org.eclipse.jetty.osgi.boot; @@ -33,6 +45,11 @@ import org.osgi.service.packageadmin.PackageAdmin; +/** + * AbstractWebAppProvider + * + * + */ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implements AppProvider { private static final Logger LOG = Log.getLogger(AbstractWebAppProvider.class); @@ -165,6 +182,8 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement public void configureWebApp() throws Exception { + + //TODO turn this around and let any context.xml file get applied first, and have the properties override _webApp.setContextPath(_contextPath); String overrideBundleInstallLocation = (String)_properties.get(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE); @@ -332,6 +351,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement Thread.currentThread().setContextClassLoader(_webApp.getClassLoader()); + //TODO replace this with getting the InputStream so we don't cache in URL // find if there is a META-INF/context.xml file URL contextXmlUrl = _bundle.getEntry("/META-INF/jetty-webapp-context.xml"); if (contextXmlUrl == null) return; @@ -363,7 +383,7 @@ public abstract class AbstractWebAppProvider extends AbstractLifeCycle implement } } - + /* ------------------------------------------------------------ */ public AbstractWebAppProvider (ServerInstanceWrapper wrapper) { _serverWrapper = wrapper; diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java index deb35042a4a..a4ef622ceaa 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java @@ -12,8 +12,6 @@ // ======================================================================== package org.eclipse.jetty.osgi.boot; -import java.io.File; -import java.net.URL; import java.util.ArrayList; import java.util.Dictionary; import java.util.HashMap; @@ -22,20 +20,11 @@ import java.util.List; import java.util.Map; import org.eclipse.jetty.deploy.App; -import org.eclipse.jetty.deploy.AppProvider; import org.eclipse.jetty.deploy.DeploymentManager; -import org.eclipse.jetty.deploy.util.FileID; import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; -import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory; -import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader; -import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader; import org.eclipse.jetty.server.handler.ContextHandler; -import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.webapp.WebAppContext; -import org.eclipse.jetty.xml.XmlConfiguration; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; @@ -48,211 +37,26 @@ import org.osgi.framework.ServiceRegistration; * * Handles deploying bundles that define a context xml file for configuring them. * - * Also able to deploy non-webapp, generic ContextHandlers that have been registered as an osgi service. + * */ -public class BundleContextProvider extends AbstractLifeCycle implements AppProvider, BundleProvider, ServiceProvider +public class BundleContextProvider extends AbstractContextProvider implements BundleProvider { - private static final Logger LOG = Log.getLogger(BundleContextProvider.class); + private static final Logger LOG = Log.getLogger(AbstractContextProvider.class); - - private DeploymentManager _deploymentManager; private Map _appMap = new HashMap(); private Map> _bundleMap = new HashMap>(); - private ServerInstanceWrapper _wrapper; - private ServiceRegistration _serviceRegForBundles; - private ServiceRegistration _serviceRegForServices; - - - - /* ------------------------------------------------------------ */ - /** - * BundleApp - * - * - */ - public class BundleApp extends App - { - private String _contextFile; - private Bundle _bundle; - private ContextHandler _contextHandler; - private OSGiClassLoader _classloader; - - public BundleApp(DeploymentManager manager, AppProvider provider, String originId, Bundle bundle, String contextFile) - { - super(manager, provider, originId); - _bundle = bundle; - _contextFile = contextFile; - } - - - public String getContextFile () - { - return _contextFile; - } - - - public ContextHandler getContextHandler() - throws Exception - { - if (_contextHandler != null) - return _contextHandler; - - createContextHandler(); - return _contextHandler; - } - - public void createContextHandler() - throws Exception - { - if (_contextFile == null) - throw new IllegalStateException ("No contextFile"); - - //apply the contextFile, creating the ContextHandler, the DeploymentManager will register it in the ContextHandlerCollection - Resource res = null; - - //try to find the context file in the filesystem - if (_contextFile.startsWith("/")) - res = getFileAsResource(_contextFile); - - //try to find it relative to jetty home - if (res == null) - { - //See if the specific server we are related to has jetty.home set - String jettyHome = (String)_wrapper.getServer().getAttribute(OSGiServerConstants.JETTY_HOME); - if (jettyHome != null) - res = getFileAsResource(jettyHome, _contextFile); - - //try to see if a SystemProperty for jetty.home is set - if (res == null) - { - jettyHome = System.getProperty(OSGiServerConstants.JETTY_HOME); - - if (jettyHome.startsWith("\"") || jettyHome.startsWith("'")) - jettyHome = jettyHome.substring(1); - if (jettyHome.endsWith("\"") || (jettyHome.endsWith("'"))) - jettyHome = jettyHome.substring(0,jettyHome.length()-1); - - res = getFileAsResource(jettyHome, _contextFile); - } - } - - //try to find it relative to the bundle in which it is being deployed - if (res == null) - { - if (_contextFile.startsWith("./")) - _contextFile = _contextFile.substring(1); - - if (!_contextFile.startsWith("/")) - _contextFile = "/" + _contextFile; - - URL contextURL = _bundle.getEntry(_contextFile); - if (contextURL != null) - res = Resource.newResource(contextURL); - } - - if (res != null) - { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - - LOG.debug("Context classloader = " + cl); - try - { - //Use a classloader that knows about the common jetty parent loader, and also the bundle - - OSGiClassLoader classLoader = new OSGiClassLoader(_wrapper.getParentClassLoaderForWebapps(), - _bundle); - Thread.currentThread().setContextClassLoader(classLoader); - XmlConfiguration xmlConfiguration = new XmlConfiguration(res.getInputStream()); - HashMap properties = new HashMap(); - properties.put("Server", _wrapper.getServer()); - - // insert the bundle's location as a property. - //setThisBundleHomeProperty(_bundle, properties, overrideBundleInstallLocation); - xmlConfiguration.getProperties().putAll(properties); - - if (_contextHandler == null) - _contextHandler = (ContextHandler) xmlConfiguration.configure(); - else - xmlConfiguration.configure(_contextHandler); - - _contextHandler.setClassLoader(classLoader); - } - finally - { - Thread.currentThread().setContextClassLoader(cl); - } - } - } - - - - - /** - * Set the property "this.bundle.install" to point to the location - * of the bundle. Useful when is - * used. - */ - private void setThisBundleHomeProperty(Bundle bundle, HashMap properties, String overrideBundleInstallLocation) - { - try - { - File location = - overrideBundleInstallLocation != null ? - new File(overrideBundleInstallLocation) : - BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle); - properties.put("this.bundle.install", location.getCanonicalPath()); - properties.put("this.bundle.install.url", bundle.getEntry("/").toString()); - } - catch (Throwable t) - { - LOG.warn("Unable to set 'this.bundle.install' " + " for the bundle " + bundle.getSymbolicName(), t); - } - } - - - private Resource getFileAsResource (String dir, String file) - { - Resource r = null; - try - { - File asFile = new File (dir, file); - if (asFile.exists()) - r = Resource.newResource(asFile); - } - catch (Exception e) - { - r = null; - } - return r; - } - - private Resource getFileAsResource (String file) - { - Resource r = null; - try - { - File asFile = new File (file); - if (asFile.exists()) - r = Resource.newResource(asFile); - } - catch (Exception e) - { - r = null; - } - return r; - } - } - + + /* ------------------------------------------------------------ */ public BundleContextProvider(ServerInstanceWrapper wrapper) { - _wrapper = wrapper; + super(wrapper); } @@ -262,10 +66,8 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi { //register as an osgi service for deploying contexts defined in a bundle, advertising the name of the jetty Server instance we are related to Dictionary properties = new Hashtable(); - properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, _wrapper.getManagedServerName()); + properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, getServerInstanceWrapper().getManagedServerName()); _serviceRegForBundles = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(BundleProvider.class.getName(), this, properties); - //register as an osgi service for deploying contexts, advertising the name of the jetty Server instance we are related to - _serviceRegForServices = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(ServiceProvider.class.getName(), this, properties); super.doStart(); } @@ -285,43 +87,10 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi LOG.warn(e); } } - - if (_serviceRegForServices != null) - { - try - { - _serviceRegForServices.unregister(); - } - catch (Exception e) - { - LOG.warn(e); - } - } - super.doStop(); } - /* ------------------------------------------------------------ */ - public void setDeploymentManager(DeploymentManager deploymentManager) - { - _deploymentManager = deploymentManager; - } - - - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.deploy.AppProvider#createContextHandler(org.eclipse.jetty.deploy.App) - */ - public ContextHandler createContextHandler(App app) throws Exception - { - if (app == null) - return null; - if (!(app instanceof BundleApp)) - throw new IllegalStateException(app+" is not a BundleApp"); - - //Create a ContextHandler suitable to deploy in OSGi - return ((BundleApp)app).getContextHandler(); - } + /* ------------------------------------------------------------ */ /** @@ -335,6 +104,9 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi return false; String contextFiles = (String)bundle.getHeaders().get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH); + if (contextFiles == null) + contextFiles = (String)bundle.getHeaders().get(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); + if (contextFiles == null) return false; @@ -346,7 +118,7 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi for (String contextFile : tmp) { String originId = bundle.getSymbolicName() + "-" + bundle.getVersion().toString() + "-"+contextFile; - BundleApp app = new BundleApp(_deploymentManager, this, originId, bundle, contextFile); + BundleApp app = new BundleApp(getDeploymentManager(), this, originId, bundle, contextFile); _appMap.put(originId,app); List apps = _bundleMap.get(bundle); if (apps == null) @@ -355,7 +127,7 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi _bundleMap.put(bundle, apps); } apps.add(app); - _deploymentManager.addApp(app); + getDeploymentManager().addApp(app); } return added; //true if even 1 context from this bundle was added @@ -378,32 +150,12 @@ public class BundleContextProvider extends AbstractLifeCycle implements AppProvi for (App app:apps) { _appMap.remove(app.getOriginId()); - _deploymentManager.removeApp(app); + getDeploymentManager().removeApp(app); removed = true; } } return removed; //true if even 1 context was removed associated with this bundle } - - public boolean serviceAdded (ServiceReference serviceRef, ContextHandler context) - { - //TODO deploy a contexthandler that some other package has created as a service - if (context == null || serviceRef == null) - return false; - - return false; - } - - - public boolean serviceRemoved (ServiceReference serviceRef, ContextHandler context) - { - //TODO remove a contexthandler that was a service - if (context == null || serviceRef == null) - return false; - - - - return false; - } + } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java index fe83395581f..c6aae36a2be 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java @@ -35,7 +35,7 @@ import org.osgi.framework.ServiceRegistration; */ public class BundleWebAppProvider extends AbstractWebAppProvider implements BundleProvider { - private static final Logger LOG = Log.getLogger(BundleWebAppProvider.class); + private static final Logger LOG = Log.getLogger(AbstractWebAppProvider.class); /** * Map of Bundle to App. Used when a Bundle contains a webapp. diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java index 94d1f8fe4a8..846c9245a53 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java @@ -123,7 +123,6 @@ public class JettyBootstrapActivator implements BundleActivator } if (_jettyContextHandlerTracker != null) { - _jettyContextHandlerTracker.stop(); context.removeServiceListener(_jettyContextHandlerTracker); _jettyContextHandlerTracker = null; } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java new file mode 100644 index 00000000000..595d84ea13a --- /dev/null +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java @@ -0,0 +1,128 @@ +package org.eclipse.jetty.osgi.boot; + +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.jetty.deploy.App; +import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.osgi.framework.Bundle; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; + +/** + * ServiceContextProvider + * + * + */ +public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider +{ + private static final Logger LOG = Log.getLogger(AbstractContextProvider.class); + + private Map _serviceMap = new HashMap(); + + private ServiceRegistration _serviceRegForServices; + + + + /* ------------------------------------------------------------ */ + public ServiceContextProvider(ServerInstanceWrapper wrapper) + { + super(wrapper); + } + + + /* ------------------------------------------------------------ */ + public boolean serviceAdded (ServiceReference serviceRef, ContextHandler context) + { + //TODO deploy a contexthandler that some other package has created as a service + if (context == null || serviceRef == null) + return false; + + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getServerInstanceWrapper().getParentClassLoaderForWebapps()); + try + { + //See if there is a context file to apply to this pre-made context + String contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH); + if (contextFile == null) + contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); + + String[] keys = serviceRef.getPropertyKeys(); + Dictionary properties = new Hashtable(); + if (keys != null) + { + for (String key:keys) + properties.put(key, serviceRef.getProperty(key)); + } + Bundle bundle = serviceRef.getBundle(); + String originId = bundle.getSymbolicName() + "-" + bundle.getVersion().toString() + "-"+contextFile; + BundleApp app = new BundleApp(getDeploymentManager(), this, bundle, properties, contextFile, originId); + app.setContextHandler(context); //set the pre=made ContextHandler instance + _serviceMap.put(serviceRef, app); + getDeploymentManager().addApp(app); + return true; + } + finally + { + Thread.currentThread().setContextClassLoader(cl); + } + } + + + /* ------------------------------------------------------------ */ + public boolean serviceRemoved (ServiceReference serviceRef, ContextHandler context) + { + + if (context == null || serviceRef == null) + return false; + + App app = _serviceMap.remove(serviceRef); + if (app != null) + { + getDeploymentManager().removeApp(app); + return true; + } + + return false; + } + + + + /* ------------------------------------------------------------ */ + @Override + protected void doStart() throws Exception + { + //register as an osgi service for deploying contexts defined in a bundle, advertising the name of the jetty Server instance we are related to + Dictionary properties = new Hashtable(); + properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, getServerInstanceWrapper().getManagedServerName()); + + //register as an osgi service for deploying contexts, advertising the name of the jetty Server instance we are related to + _serviceRegForServices = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(ServiceProvider.class.getName(), this, properties); + super.doStart(); + } + + /* ------------------------------------------------------------ */ + @Override + protected void doStop() throws Exception + { + //unregister ourselves + if (_serviceRegForServices != null) + { + try + { + _serviceRegForServices.unregister(); + } + catch (Exception e) + { + LOG.warn(e); + } + } + super.doStop(); + } +} diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java index e75917483c1..835fc851625 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java @@ -60,7 +60,6 @@ public class ServiceWebAppProvider extends AbstractWebAppProvider implements Ser WebAppContext webApp = (WebAppContext)context; - System.err.println("Casting to webapp"); Dictionary properties = new Hashtable(); String contextPath = (String)serviceRef.getProperty(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH); diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java index 39f384e75d1..6f059b7dfe4 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java @@ -33,6 +33,9 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; /** + * DefaultJettyAtJettyHomeHelper + * + * * Called by the {@link JettyBootstrapActivator} during the starting of the * bundle. If the system property 'jetty.home' is defined and points to a * folder, then setup the corresponding jetty server. @@ -48,8 +51,6 @@ public class DefaultJettyAtJettyHomeHelper */ public static final String JETTY_ETC_FILES = OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS; - - /** * Set of config files to apply to a jetty Server instance if none are supplied by SYS_PROP_JETTY_ETC_FILES */ @@ -59,7 +60,9 @@ public class DefaultJettyAtJettyHomeHelper * Default location within bundle of a jetty home dir. */ public static final String DEFAULT_JETTYHOME = "/jettyhome"; - + + + /* ------------------------------------------------------------ */ /** * Called by the JettyBootStrapActivator. If the system property jetty.home * is defined and points to a folder, creates a corresponding jetty @@ -110,7 +113,6 @@ public class DefaultJettyAtJettyHomeHelper else if (jettyHomeBundleSysProp != null) { jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp); - System.err.println("jetty home bundle sysprop = "+jettyHomeBundleSysProp); for (Bundle b : bundleContext.getBundles()) { if (b.getSymbolicName().equals(jettyHomeBundleSysProp)) @@ -151,7 +153,10 @@ public class DefaultJettyAtJettyHomeHelper //register the Server instance as an OSGi service. bundleContext.registerService(Server.class.getName(), server, properties); } - + + + + /* ------------------------------------------------------------ */ /** * Minimum setup for the location of the configuration files given a * jettyhome folder. Reads the system property jetty.etc.config.urls and @@ -185,7 +190,9 @@ public class DefaultJettyAtJettyHomeHelper } return res.toString(); } - + + + /* ------------------------------------------------------------ */ /** * Minimum setup for the location of the configuration files given a * configuration embedded inside a bundle. Reads the system property @@ -197,7 +204,6 @@ public class DefaultJettyAtJettyHomeHelper */ private static String getJettyConfigurationURLs(Bundle configurationBundle) { - System.err.println("GETTING JETTY PROPS FROM BUNDLE: "+configurationBundle.getSymbolicName()); String files = System.getProperty(JETTY_ETC_FILES, DEFAULT_JETTY_ETC_FILES); StringTokenizer tokenizer = new StringTokenizer(files, ";,", false); @@ -214,10 +220,8 @@ public class DefaultJettyAtJettyHomeHelper else { //relative file path - System.err.println("Finding "+etcFile+" in bundle "+configurationBundle); Enumeration enUrls = BundleFileLocatorHelperFactory.getFactory().getHelper().findEntries(configurationBundle, etcFile); - - + // default for org.eclipse.osgi.boot where we look inside // jettyhome for the default embedded configuration. // default inside jettyhome. this way fragments to the bundle @@ -229,8 +233,6 @@ public class DefaultJettyAtJettyHomeHelper LOG.info("Configuring jetty from bundle: " + configurationBundle.getSymbolicName() + " with "+tmp); - - System.err.println(configurationBundle.getEntry(tmp)); } if (enUrls == null || !enUrls.hasMoreElements()) { @@ -241,7 +243,6 @@ public class DefaultJettyAtJettyHomeHelper while (enUrls.hasMoreElements()) { URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getFileURL(enUrls.nextElement()); - System.err.println("Got url: "+url +" from "+url.getClass().getName()); appendToCommaSeparatedList(res, url.toString()); } } @@ -249,7 +250,9 @@ public class DefaultJettyAtJettyHomeHelper } return res.toString(); } - + + + /* ------------------------------------------------------------ */ private static void appendToCommaSeparatedList(StringBuilder buffer, String value) { if (buffer.length() != 0) @@ -258,7 +261,9 @@ public class DefaultJettyAtJettyHomeHelper } buffer.append(value); } - + + + /* ------------------------------------------------------------ */ private static void setProperty(Dictionary properties, String key, String value) { if (value != null) @@ -266,7 +271,9 @@ public class DefaultJettyAtJettyHomeHelper properties.put(key, value); } } - + + + /* ------------------------------------------------------------ */ /** * recursively substitute the ${sysprop} by their actual system property. * ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java index d464f5178a7..8282720620e 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java @@ -30,6 +30,7 @@ import org.eclipse.jetty.osgi.boot.BundleContextProvider; import org.eclipse.jetty.osgi.boot.BundleWebAppProvider; import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; +import org.eclipse.jetty.osgi.boot.ServiceContextProvider; import org.eclipse.jetty.osgi.boot.ServiceWebAppProvider; import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader; import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory; @@ -79,17 +80,22 @@ public class ServerInstanceWrapper private ClassLoader _commonParentClassLoaderForWebapps; private DeploymentManager _deploymentManager; - + + + /* ------------------------------------------------------------ */ public ServerInstanceWrapper(String managedServerName) { _managedServerName = managedServerName; } + /* ------------------------------------------------------------ */ public String getManagedServerName() { return _managedServerName; } - + + + /* ------------------------------------------------------------ */ /** * The classloader that should be the parent classloader for each webapp * deployed on this server. @@ -100,7 +106,9 @@ public class ServerInstanceWrapper { return _commonParentClassLoaderForWebapps; } - + + + /* ------------------------------------------------------------ */ /** * @return The deployment manager registered on this server. */ @@ -108,7 +116,9 @@ public class ServerInstanceWrapper { return _deploymentManager; } - + + + /* ------------------------------------------------------------ */ /** * @return The app provider registered on this server. */ @@ -117,7 +127,7 @@ public class ServerInstanceWrapper return _server; } - + /* ------------------------------------------------------------ */ /** * @return The collection of context handlers */ @@ -125,7 +135,9 @@ public class ServerInstanceWrapper { return _ctxtCollection; } - + + + /* ------------------------------------------------------------ */ public void start(Server server, Dictionary props) throws Exception { _server = server; @@ -140,7 +152,7 @@ public class ServerInstanceWrapper List shared = sharedURLs != null ? extractFiles(sharedURLs) : null; libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader()); - System.err.println("LibExtClassLoader = "+libExtClassLoader); + if (LOG.isDebugEnabled()) LOG.debug("LibExtClassLoader = "+libExtClassLoader); Thread.currentThread().setContextClassLoader(libExtClassLoader); @@ -148,16 +160,12 @@ public class ServerInstanceWrapper init(); - // now that we have an app provider we can call the registration - // customizer. - URL[] jarsWithTlds = getJarsWithTlds(); _commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds); - System.err.println("common classloader = "+_commonParentClassLoaderForWebapps); + if (LOG.isDebugEnabled()) LOG.debug("common classloader = "+_commonParentClassLoaderForWebapps); server.start(); - //_webBundleDeployerHelper = new WebBundleDeployerHelper(this); } catch (Exception e) { @@ -180,7 +188,7 @@ public class ServerInstanceWrapper } } - + /* ------------------------------------------------------------ */ public void stop() { try @@ -195,7 +203,9 @@ public class ServerInstanceWrapper LOG.warn(e); } } - + + + /* ------------------------------------------------------------ */ /** * TODO: right now only the jetty-jsp bundle is scanned for common taglibs. * Should support a way to plug more bundles that contain taglibs. @@ -242,7 +252,9 @@ public class ServerInstanceWrapper else return null; } - + + + /* ------------------------------------------------------------ */ private void configure(Server server, Dictionary props) throws Exception { String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS); @@ -250,8 +262,10 @@ public class ServerInstanceWrapper if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; } Map id_map = new HashMap(); - //TODO need to put in the id of the server being configured + //Put in a mapping for the id "Server" and the name of the server as the instance being configured id_map.put("Server", server); + id_map.put((String)props.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME), server); + Map properties = new HashMap(); Enumeration en = props.keys(); while (en.hasMoreElements()) @@ -383,10 +397,20 @@ public class ServerInstanceWrapper { LOG.warn(e); } - } - //TODO add ServiceContextProvider + if (!providerClassNames.contains(ServiceContextProvider.class.getName())) + { + try + { + ServiceContextProvider contextProvider = new ServiceContextProvider(this); + _deploymentManager.addAppProvider(contextProvider); + } + catch (Exception e) + { + LOG.warn(e); + } + } } /** diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java index 00f852c9dfb..5cb4a41eb4b 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java @@ -43,42 +43,29 @@ import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; /** - * When a {@link ContextHandler} service is activated we look into it and if the - * corresponding webapp is actually not configured then we go and register it. - *

- * The idea is to always go through this class when we deploy a new webapp on - * jetty. - *

- *

- * We are exposing each web-application as an OSGi service. This lets us update - * the webapps and stop/start them directly at the OSGi layer. It also give us - * many ways to declare those services: Declarative Services for example.
- * It is a bit different from the way the HttpService works where we would have - * a WebappService and we woud register a webapp onto it.
- * It does not go against RFC-66 nor does it prevent us from supporting the - * WebappContainer semantics. - *

+ * JettyContextHandlerServiceTracker + * + * When a {@link ContextHandler} is activated as an osgi service we find a jetty deployer + * for it. The ContextHandler could be either a WebAppContext or any other derivative of + * ContextHandler. + * + * ContextHandlers and WebApps can also be deployed into jetty without creating them as + * osgi services. Instead, they can be deployed via manifest headers inside bundles. See + * {@link WebBundleTrackerCustomizer}. */ public class JettyContextHandlerServiceTracker implements ServiceListener { - private static Logger __logger = Log.getLogger(JettyContextHandlerServiceTracker.class.getName()); + private static Logger LOG = Log.getLogger(JettyContextHandlerServiceTracker.class); public static final String FILTER = "(objectclass=" + ServiceProvider.class.getName() + ")"; - - - /** - * The index is the bundle-symbolic-name/path/to/context/file when there is - * such thing - */ - private Map _indexByContextFile = new HashMap(); - - /** in charge of detecting changes in the osgi contexts home folder. */ - private Scanner _scanner; //track all instances of deployers of webapps as bundles ServiceTracker _serviceTracker; - + + + + /* ------------------------------------------------------------ */ /** * @param registry */ @@ -90,56 +77,13 @@ public class JettyContextHandlerServiceTracker implements ServiceListener _serviceTracker.open(); } - public void stop() throws Exception - { - if (_scanner != null) - { - _scanner.stop(); - } - // the class that created the server is also in charge of stopping it. - // nothing to stop in the WebappRegistrationHelper - - } + + /* ------------------------------------------------------------ */ /** - * @param contextHome Parent folder where the context files can override the - * context files defined in the web bundles: equivalent to the - * contexts folder in a traditional jetty installation. when - * null, just do nothing. + * @param managedServerName + * @return */ - protected void setupContextHomeScanner(File contextHome) throws IOException - { - if (contextHome == null) { return; } - final String osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath(); - _scanner = new Scanner(); - _scanner.setRecursive(true); - _scanner.setReportExistingFilesOnStartup(false); - _scanner.addListener(new Scanner.DiscreteListener() - { - public void fileAdded(String filename) throws Exception - { - // adding a file does not create a new app, - // it just reloads it with the new custom file. - // well, if the file does not define a context handler, - // then in fact it does remove it. - reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); - } - - public void fileChanged(String filename) throws Exception - { - reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); - } - - public void fileRemoved(String filename) throws Exception - { - // removing a file does not remove the app: - // it just goes back to the default embedded in the bundle. - // well, if there was no default then it does remove it. - reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath); - } - }); - } - public Map getDeployers(String managedServerName) { if (managedServerName == null) @@ -164,6 +108,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener return candidates; } + /* ------------------------------------------------------------ */ /** * Receives notification that a service has had a lifecycle change. * @@ -209,85 +154,32 @@ public class JettyContextHandlerServiceTracker implements ServiceListener } case ServiceEvent.REGISTERED: { - System.err.println("New Service registered that could be webapp/context"); Bundle contributor = sr.getBundle(); BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext(); ContextHandler contextHandler = (ContextHandler) context.getService(sr); if (contextHandler.getServer() != null) { // is configured elsewhere. - System.err.println("Already configured"); return; } - - System.err.println("Service registered from bundle: "+contributor.getSymbolicName()); - System.err.println("war="+sr.getProperty("war")); //Get a jetty deployer targetted to the named server instance, or the default one if not named String serverName = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME); Map candidates = getDeployers(serverName); if (candidates != null) { - System.err.println("Got some candidates"); boolean added = false; Iterator> itor = candidates.entrySet().iterator(); while (!added && itor.hasNext()) { Entry e = itor.next(); - System.err.println("Trying ServiceProvider "+e.getValue()); added = e.getValue().serviceAdded(sr, contextHandler); + if (added && LOG.isDebugEnabled()) + LOG.debug("Provider "+e.getValue()+" deployed "+contextHandler); } } break; } } } - - - - - /** - * @param sr - * @return The key for a context file within the osgi contexts home folder. - */ - private String getSymbolicNameAndContextFileKey(ServiceReference sr) - { - String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); - if (contextFilePath != null) { return sr.getBundle().getSymbolicName() + "/" + contextFilePath; } - return null; - } - - /** - * Called by the scanner when one of the context files is changed. - * - * @param contextFileFully - */ - public void reloadJettyContextHandler(String canonicalNameOfFileChanged, String osgiContextHomeFolderCanonicalPath) - { - String key = getNormalizedRelativePath(canonicalNameOfFileChanged, osgiContextHomeFolderCanonicalPath); - if (key == null) { return; } - ServiceReference sr = _indexByContextFile.get(key); - if (sr == null) - { - // nothing to do? - return; - } - serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED, sr)); - } - - /** - * @param canFilename - * @return - */ - private String getNormalizedRelativePath(String canFilename, String osgiContextHomeFolderCanonicalPath) - { - if (!canFilename.startsWith(osgiContextHomeFolderCanonicalPath)) - { - // why are we here: this does not look like a child of the osgi - // contexts home. - // warning? - return null; - } - return canFilename.substring(osgiContextHomeFolderCanonicalPath.length()).replace('\\', '/'); - } } diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java index 7ce5909bda5..597893c70fe 100644 --- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java +++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java @@ -16,7 +16,6 @@ import java.util.ArrayList; import java.util.Collection; import org.eclipse.jetty.osgi.boot.BundleProvider; -import org.eclipse.jetty.osgi.boot.BundleWebAppProvider; import org.eclipse.jetty.osgi.boot.OSGiServerConstants; import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer; import org.eclipse.jetty.util.log.Log; @@ -29,8 +28,15 @@ import org.osgi.util.tracker.BundleTrackerCustomizer; import org.osgi.util.tracker.ServiceTracker; /** + * WebBundleTrackerCustomizer + * + * * Support bundles that declare a webpp or context directly through headers in their - * manifest. + * manifest. They will be deployed to the default jetty Server instance. + * + * If you wish to deploy a context or webapp to a different jetty Server instance, + * register your context/webapp as an osgi service, and set the property OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + * with the name of the Server instance you wish to depoy to. * * @author hmalphettes */ @@ -164,20 +170,15 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer Object[] deployers = _serviceTracker.getServices(); if (deployers != null) { - System.err.println("FOUND "+deployers.length+" FOR "+bundle.getSymbolicName()); int i=0; while (!deployed && ijetty-osgi-httpservice jetty-osgi-equinoxtools test-jetty-osgi-webapp + test-jetty-osgi-context test-jetty-osgi @@ -73,6 +74,11 @@ + + org.eclipse.jetty + jetty-server + ${project.version} + org.eclipse.jetty jetty-continuation diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml new file mode 100644 index 00000000000..663893dba48 --- /dev/null +++ b/jetty-osgi/test-jetty-osgi-context/pom.xml @@ -0,0 +1,132 @@ + + + org.eclipse.jetty.osgi + jetty-osgi-project + 7.6.4-SNAPSHOT + ../pom.xml + + 4.0.0 + test-jetty-osgi-context + Jetty :: OSGi :: Context + Test Jetty OSGi bundle with a ContextHandler + + ${project.groupId}.testcontext + + + + org.eclipse.jetty + jetty-server + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + + + + + src/main/resources + + + src/main/context + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + artifact-jar + + jar + + + + test-jar + + test-jar + + + + + + target/classes/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + org.eclipse.jetty.osgi.testcontext;singleton:=true + Jetty OSGi Test Context + com.acme.osgi.Activator + J2SE-1.5 + + <_nouses>true + + org.osgi.framework, + org.osgi.service.cm;version="1.2.0", + org.osgi.service.packageadmin, + org.osgi.service.startlevel;version="1.0.o", + org.osgi.service.url;version="1.0.0", + org.osgi.util.tracker;version="1.3.0", + org.slf4j;resolution:=optional, + org.slf4j.spi;resolution:=optional, + org.slf4j.helpers;resolution:=optional, + org.xml.sax, + org.xml.sax.helpers, + * + + org.eclipse.jetty.*;version="[7.6,8)" + + + + + + + + + diff --git a/jetty-osgi/test-jetty-osgi-context/src/main/context/acme.xml b/jetty-osgi/test-jetty-osgi-context/src/main/context/acme.xml new file mode 100644 index 00000000000..53bbbdb3afb --- /dev/null +++ b/jetty-osgi/test-jetty-osgi-context/src/main/context/acme.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + /static/ + + + + /unset + + + + + + + + + + + index.html + + + max-age=3600,public + + + + + diff --git a/jetty-osgi/test-jetty-osgi-context/src/main/java/com/acme/osgi/Activator.java b/jetty-osgi/test-jetty-osgi-context/src/main/java/com/acme/osgi/Activator.java new file mode 100644 index 00000000000..77013e17a81 --- /dev/null +++ b/jetty-osgi/test-jetty-osgi-context/src/main/java/com/acme/osgi/Activator.java @@ -0,0 +1,58 @@ +// ======================================================================== +// Copyright (c) 2012 Intalio, Inc. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +package com.acme.osgi; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.BundleTracker; + +/** + * Bootstrap a ContextHandler + * + * + */ +public class Activator implements BundleActivator +{ + + /** + * + * @param context + */ + public void start(BundleContext context) throws Exception + { + ContextHandler ch = new ContextHandler(); + Dictionary props = new Hashtable(); + props.put("contextPath","/acme"); + props.put("Jetty-ContextFilePath", "acme.xml"); + context.registerService(ContextHandler.class.getName(),ch,props); + } + + /** + * Stop the activator. + * + * @see + * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception + { + } +} diff --git a/jetty-osgi/test-jetty-osgi-context/src/main/resources/static/index.html b/jetty-osgi/test-jetty-osgi-context/src/main/resources/static/index.html new file mode 100644 index 00000000000..3189646adce --- /dev/null +++ b/jetty-osgi/test-jetty-osgi-context/src/main/resources/static/index.html @@ -0,0 +1,6 @@ + + +

Test OSGi Context

+

ContextHandler registered as a service successfully deployed.

+ + diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml index ba2d2771f39..1b6613ade01 100644 --- a/jetty-osgi/test-jetty-osgi/pom.xml +++ b/jetty-osgi/test-jetty-osgi/pom.xml @@ -142,6 +142,15 @@ runtime
+ + + org.eclipse.jetty.osgi + test-jetty-osgi-context + ${project.version} + runtime + + + org.ops4j.pax.exam diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/JettyOSGiBootContextAsService.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/JettyOSGiBootContextAsService.java new file mode 100644 index 00000000000..02801d1c823 --- /dev/null +++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/JettyOSGiBootContextAsService.java @@ -0,0 +1,170 @@ +// ======================================================================== +// Copyright (c) 2010 Intalio, Inc. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// You may elect to redistribute this code under either of these licenses. +// Contributors: +// Hugues Malphettes - initial API and implementation +// ======================================================================== +package org.eclipse.jetty.osgi.boot; + +import static org.ops4j.pax.exam.CoreOptions.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; + +import org.eclipse.jetty.client.ContentExchange; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpExchange; +import org.eclipse.jetty.http.HttpMethods; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Inject; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.container.def.PaxRunnerOptions; +import org.ops4j.pax.exam.junit.Configuration; +import org.ops4j.pax.exam.junit.JUnit4TestRunner; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/** + * TestJettyOSGiBootContextAsService + * + * Tests deployment of a ContextHandler as an osgi Service. + * + * Tests the ServiceContextProvider. + * + */ +@RunWith( JUnit4TestRunner.class ) +public class JettyOSGiBootContextAsService +{ + private static final boolean LOGGING_ENABLED = false; + private static final boolean REMOTE_DEBUGGING = false; + + @Inject + BundleContext bundleContext = null; + + @Configuration + public static Option[] configure() + { + ArrayList