From b2998c2c4d4771eb01daae5d82d35872959551a7 Mon Sep 17 00:00:00 2001
From: Jan Bartel
Date: Mon, 14 May 2012 18:46:21 +0200
Subject: [PATCH 01/21] Refactoring
---
...gableWebAppRegistrationCustomizerImpl.java | 32 +-
.../WebappRegistrationCustomizerImpl.java | 13 +-
.../osgi/boot/jsp/FragmentActivator.java | 21 +-
.../boot/jsp/TagLibOSGiConfiguration.java | 3 +-
.../jettyhome/etc/jetty-deployer.xml | 13 +-
.../osgi/boot/BundleContextProvider.java | 78 ++
.../jetty/osgi/boot/BundleWebAppProvider.java | 763 +++++++++++++++
.../osgi/boot/JettyBootstrapActivator.java | 8 +-
.../osgi/boot/OSGiMetaInfConfiguration.java | 98 ++
.../osgi/boot/OSGiWebInfConfiguration.java | 255 +++++
.../jetty/osgi/boot/OSGiWebappConstants.java | 42 +-
.../DefaultJettyAtJettyHomeHelper.java | 3 +-
.../serverfactory/ServerInstanceWrapper.java | 61 +-
.../BundleFileLocatorHelperFactory.java | 41 +
.../JettyContextHandlerServiceTracker.java | 75 +-
.../webapp/OSGiWebappClassLoader.java | 5 +-
.../webapp/WebBundleDeployerHelper.java | 904 ------------------
.../webapp/WebBundleTrackerCustomizer.java | 162 +---
.../utils/BundleClassLoaderHelperFactory.java | 44 +
.../boot/utils/BundleFileLocatorHelper.java | 26 +
.../utils/WebappRegistrationCustomizer.java | 3 +-
.../internal/DefaultFileLocatorHelper.java | 4 +-
jetty-osgi/pom.xml | 1 +
jetty-osgi/test-jetty-osgi-webapp/pom.xml | 129 +++
.../main/java/com/acme/osgi/Activator.java | 60 ++
.../src/main/resources/index.html | 6 +
jetty-osgi/test-jetty-osgi/pom.xml | 15 +
.../src/test/config/etc/jetty-deployer.xml | 43 +
.../src/test/config/etc/jetty-selector.xml | 26 +
.../src/test/config/etc/jetty.xml | 72 ++
.../osgi/boot/TestJettyOSGiBootCore.java | 2 +-
.../TestJettyOSGiBootWebAppAsService.java | 166 ++++
.../osgi/boot/TestJettyOSGiBootWithJsp.java | 15 +-
33 files changed, 2078 insertions(+), 1111 deletions(-)
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleFileLocatorHelperFactory.java
delete mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java
create mode 100644 jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
create mode 100644 jetty-osgi/test-jetty-osgi-webapp/pom.xml
create mode 100644 jetty-osgi/test-jetty-osgi-webapp/src/main/java/com/acme/osgi/Activator.java
create mode 100644 jetty-osgi/test-jetty-osgi-webapp/src/main/resources/index.html
create mode 100644 jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-deployer.xml
create mode 100644 jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-selector.xml
create mode 100644 jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
create mode 100644 jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java
index 79854f2c99f..6ba3d1c5bd5 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java
@@ -19,9 +19,13 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.OSGiAppProvider;
+import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.osgi.framework.Bundle;
@@ -56,10 +60,10 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
* @param provider
* @return
*/
- private static Collection getTldBundles(OSGiAppProvider provider)
+ private static Collection getTldBundles(DeploymentManager deploymentManager)
{
String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
- String att = (String) provider.getTldBundles();
+ String att = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN);
if (sysprop == null && att == null) { return Collections.emptySet(); }
if (att == null)
{
@@ -83,9 +87,8 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
* @return The location of the jars that contain tld files. Jasper will
* discover them.
*/
- public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
+ public URL[] getJarsWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
{
- List urls = new ArrayList();
// naive way of finding those bundles.
// lots of assumptions: for example we assume a single version of each
// bundle that would contain tld files.
@@ -96,13 +99,24 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
// and mirroring those in the MANIFEST.MF
Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
- Collection tldbundles = getTldBundles(provider);
+ HashSet urls = new HashSet();
+ String tmp = System.getProperty(SYS_PROP_TLD_BUNDLES); //comma separated exact names
+ List sysNames = new ArrayList();
+ if (tmp != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
+ while (tokenizer.hasMoreTokens())
+ sysNames.add(tokenizer.nextToken());
+ }
+ tmp = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN); //bundle name patterns
+ Pattern pattern = (tmp==null? null : Pattern.compile(tmp));
for (Bundle bundle : bundles)
{
- if (tldbundles.contains(bundle.getSymbolicName()))
- {
+ if (sysNames.contains(bundle.getSymbolicName()))
+ registerTldBundle(locatorHelper, bundle, urls);
+
+ if (pattern != null && pattern.matcher(bundle.getSymbolicName()).matches())
registerTldBundle(locatorHelper, bundle, urls);
- }
}
return urls.toArray(new URL[urls.size()]);
@@ -134,7 +148,7 @@ public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistra
* @param urls
* @throws Exception
*/
- private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, List urls) throws Exception
+ private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set urls) throws Exception
{
File jasperLocation = locatorHelper.getBundleInstallLocation(bundle);
if (jasperLocation.isDirectory())
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java
index 44718bb37e3..4fdf8379bc9 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java
@@ -25,10 +25,13 @@ import javax.servlet.jsp.JspFactory;
import org.apache.jasper.Constants;
import org.apache.jasper.compiler.Localizer;
import org.apache.jasper.xmlparser.ParserUtils;
+import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiAppProvider;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
+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.xml.sax.EntityResolver;
@@ -46,6 +49,8 @@ import org.xml.sax.SAXException;
*/
public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer
{
+ private static final Logger LOG = Log.getLogger(WebappRegistrationCustomizerImpl.class);
+
/**
* Default name of a class that belongs to the jstl bundle. From that class
@@ -85,8 +90,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
}
catch (Exception e)
{
- System.err.println("Unable to locate the JspServlet: jsp support unavailable.");
- e.printStackTrace();
+ LOG.warn("Unable to locate the JspServlet: jsp support unavailable.", e);
return;
}
try
@@ -106,8 +110,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
}
catch (Exception e)
{
- System.err.println("Unable to set the JspFactory: jsp support incomplete.");
- e.printStackTrace();
+ LOG.warn("Unable to set the JspFactory: jsp support incomplete.", e);
}
}
@@ -129,7 +132,7 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
* @return array of URLs
* @throws Exception
*/
- public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
+ public URL[] getJarsWithTlds(DeploymentManager deployer, BundleFileLocatorHelper locatorHelper) throws Exception
{
HashSet> classesToAddToTheTldBundles = new HashSet>();
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
index 3f8f2874e65..1b1da582efd 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
@@ -12,7 +12,9 @@
// ========================================================================
package org.eclipse.jetty.osgi.boot.jsp;
-import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper;
+
+import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
+import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.jasper.PluggableWebAppRegistrationCustomizerImpl;
import org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl;
import org.osgi.framework.BundleActivator;
@@ -24,7 +26,7 @@ import org.osgi.framework.BundleContext;
* called back by the host bundle.
*
* It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is
- * because org.eclipse.jetty.osgi.boot.jsp is the sympbolic-name of this
+ * because org.eclipse.jetty.osgi.boot.jsp is the symbolic-name of this
* fragment. From that name, the PackageadminTracker will call this class. IN a
* different package it won't be called.
*
@@ -37,8 +39,11 @@ public class FragmentActivator implements BundleActivator
public void start(BundleContext context) throws Exception
{
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
- WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
- WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
+ WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
+ WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
+ //Put in the support for the tag libs
+ addTagLibSupport();
+
}
/**
@@ -48,4 +53,12 @@ public class FragmentActivator implements BundleActivator
{
}
+
+ public void addTagLibSupport ()
+ {
+ String[] defaultConfigurations = new String[BundleWebAppProvider.getDefaultConfigurations().length+1];
+ System.arraycopy(BundleWebAppProvider.getDefaultConfigurations(), 0, defaultConfigurations, 0, BundleWebAppProvider.getDefaultConfigurations().length);
+ defaultConfigurations[defaultConfigurations.length-1] = "org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration";
+ BundleWebAppProvider.setDefaultConfigurations(defaultConfigurations);
+ }
}
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java
index ad31de22e7f..0859da3d214 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/TagLibOSGiConfiguration.java
@@ -19,6 +19,7 @@ import java.util.Enumeration;
import java.util.LinkedHashSet;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
+import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -108,7 +109,7 @@ public class TagLibOSGiConfiguration extends TagLibConfiguration
{
atLeastOneTldFound = true;
URL oriUrl = en.nextElement();
- URL url = DefaultFileLocatorHelper.getLocalURL(oriUrl);
+ URL url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(oriUrl);
Resource tldResource;
try
{
diff --git a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-deployer.xml b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-deployer.xml
index f05b31c8e16..ac352765627 100644
--- a/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-deployer.xml
+++ b/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-deployer.xml
@@ -17,22 +17,25 @@
.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$
-
-
-
+
+
+
+
-
+
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
new file mode 100644
index 00000000000..e5da466f731
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java
@@ -0,0 +1,78 @@
+package org.eclipse.jetty.osgi.boot;
+
+import java.util.HashMap;
+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.server.handler.ContextHandler;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.osgi.framework.Bundle;
+
+public class BundleContextProvider extends AbstractLifeCycle implements AppProvider
+{
+ private DeploymentManager _deploymentManager;
+
+ private Map _appMap = new HashMap();
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * BundleApp
+ *
+ *
+ */
+ public class BundleApp extends App
+ {
+ private String _contextFile;
+ private Bundle _bundle;
+
+ 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 void setDeploymentManager(DeploymentManager deploymentManager)
+ {
+ _deploymentManager = deploymentManager;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public ContextHandler createContextHandler(App app) throws Exception
+ {
+ //apply the contextFile, creating the ContextHandler, the DeploymentManager will register it in the ContextHandlerCollection
+ return null;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void bundleAdded (Bundle bundle, String contextFiles)
+ {
+ if (contextFiles == null)
+ return;
+
+ //bundle defines OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH header,
+ //a comma separated list of context xml files that each define a ContextHandler (could be WebAppContexts)
+ String[] tmp = contextFiles.split(",;");
+ for (String contextFile : tmp)
+ {
+ String originId = bundle.getSymbolicName() + "-" + bundle.getVersion().toString() + "-"+contextFile;
+ BundleApp app = new BundleApp(_deploymentManager, this, originId, bundle, contextFile);
+ _appMap.put(originId,app);
+ _deploymentManager.addApp(app);
+ }
+ }
+
+}
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
new file mode 100644
index 00000000000..5aeba514666
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java
@@ -0,0 +1,763 @@
+package org.eclipse.jetty.osgi.boot;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+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.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.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.webapp.WebAppContext;
+import org.eclipse.jetty.xml.XmlConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+
+
+/**
+ * BundleWebAppProvider
+ *
+ *
+ */
+public class BundleWebAppProvider extends AbstractLifeCycle implements AppProvider
+{
+ private static final Logger LOG = Log.getLogger(BundleWebAppProvider.class);
+
+ public static final String WATERMARK = "o.e.j.o.b.BWAP"; //indicates this class created the webapp
+
+ public static String __defaultConfigurations[] = {
+ "org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration",
+ "org.eclipse.jetty.webapp.WebXmlConfiguration",
+ "org.eclipse.jetty.osgi.boot.OSGiMetaInfConfiguration",
+ "org.eclipse.jetty.webapp.FragmentConfiguration",
+ "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"//,
+ //"org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration"
+ };
+
+ private DeploymentManager _deploymentManager;
+
+ private Map _appMap = new HashMap();
+
+ private Map _bundleMap = new HashMap();
+
+ private boolean _parentLoaderPriority;
+
+ private String _defaultsDescriptor;
+
+ private boolean _extractWars = true; //See WebAppContext.extractWars
+
+ private String _tldBundles;
+
+ private String[] _configurationClasses;
+
+ private ServerInstanceWrapper _serverWrapper;
+
+ private ServiceRegistration _serviceReg;
+
+
+ public static void setDefaultConfigurations (String[] defaultConfigs)
+ {
+ __defaultConfigurations = defaultConfigs;
+ }
+
+ public static String[] getDefaultConfigurations ()
+ {
+ return __defaultConfigurations;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * BundleApp
+ *
+ *
+ */
+ public class BundleApp extends App
+ {
+ private Bundle _bundle;
+ private String _contextPath;
+ private String _webAppPath;
+ private WebAppContext _webApp;
+ private Dictionary _properties;
+
+ public BundleApp(DeploymentManager manager, AppProvider provider, Bundle bundle, String originId)
+ {
+ super(manager, provider, originId);
+ _properties = bundle.getHeaders();
+ _bundle = bundle;
+ }
+
+ public BundleApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary properties, String originId)
+ {
+ super(manager, provider, originId);
+ _properties = properties;
+ _bundle = bundle;
+ }
+
+ public void setWebAppContext (WebAppContext webApp)
+ {
+ _webApp = webApp;
+ }
+
+
+ public Bundle getBundle()
+ {
+ return _bundle;
+ }
+
+ public String getContextPath()
+ {
+ return _contextPath;
+ }
+
+ public void setContextPath(String contextPath)
+ {
+ this._contextPath = contextPath;
+ }
+
+ public String getBundlePath()
+ {
+ return _webAppPath;
+ }
+
+ public void setWebAppPath(String path)
+ {
+ this._webAppPath = path;
+ }
+
+
+ public WebAppContext getWebAppContext()
+ throws Exception
+ {
+ if (_webApp != null)
+ {
+ configureWebApp();
+ return _webApp;
+ }
+
+ createWebApp();
+ return _webApp;
+ }
+
+
+ protected void createWebApp ()
+ throws Exception
+ {
+ _webApp = newWebApp();
+ configureWebApp();
+ }
+
+ protected WebAppContext newWebApp ()
+ {
+ WebAppContext webApp = new WebAppContext();
+ webApp.setAttribute(WATERMARK, WATERMARK);
+ return webApp;
+ }
+
+
+ public void configureWebApp()
+ throws Exception
+ {
+ _webApp.setContextPath(_contextPath);
+
+ String overrideBundleInstallLocation = (String)_properties.get(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE);
+ File bundleInstallLocation =
+ (overrideBundleInstallLocation == null
+ ? BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(_bundle)
+ : new File(overrideBundleInstallLocation));
+ URL url = null;
+
+ //if the path wasn't set or it was ., then it is the root of the bundle's installed location
+ if (_webAppPath == null || _webAppPath.length() == 0 || ".".equals(_webAppPath))
+ {
+ url = bundleInstallLocation.toURI().toURL();
+ }
+ else
+ {
+ //Get the location of the root of the webapp inside the installed bundle
+ if (_webAppPath.startsWith("/") || _webAppPath.startsWith("file:"))
+ {
+ url = new File(_webAppPath).toURI().toURL();
+ }
+ else if (bundleInstallLocation != null && bundleInstallLocation.isDirectory())
+ {
+ url = new File(bundleInstallLocation, _webAppPath).toURI().toURL();
+ }
+ else if (bundleInstallLocation != null)
+ {
+ Enumeration urls = BundleFileLocatorHelperFactory.getFactory().getHelper().findEntries(_bundle, _webAppPath);
+ if (urls != null && urls.hasMoreElements())
+ url = urls.nextElement();
+ }
+ }
+
+ if (url == null)
+ {
+ throw new IllegalArgumentException("Unable to locate " + _webAppPath
+ + " in "
+ + (bundleInstallLocation != null ? bundleInstallLocation.getAbsolutePath() : "unlocated bundle '" + _bundle.getSymbolicName()+ "'"));
+ }
+
+ // converts bundleentry: protocol if necessary
+ _webApp.setWar(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url).toString());
+
+ // Set up what has been configured on the provider
+ _webApp.setParentLoaderPriority(isParentLoaderPriority());
+ _webApp.setExtractWAR(isExtract());
+ if (getConfigurationClasses() != null)
+ _webApp.setConfigurationClasses(getConfigurationClasses());
+ else
+ _webApp.setConfigurationClasses(__defaultConfigurations);
+
+ for (int i=0;i<__defaultConfigurations.length;i++)
+ System.err.println(__defaultConfigurations[i]);
+
+ if (getDefaultsDescriptor() != null)
+ _webApp.setDefaultsDescriptor(getDefaultsDescriptor());
+
+ //Set up configuration from manifest headers
+ //extra classpath
+ String tmp = (String)_properties.get(OSGiWebappConstants.JETTY_EXTRA_CLASSPATH);
+ if (tmp != null)
+ _webApp.setExtraClasspath(tmp);
+
+ //web.xml
+ tmp = (String)_properties.get(OSGiWebappConstants.JETTY_WEB_XML_PATH);
+ if (tmp != null && tmp.trim().length() != 0)
+ {
+ File webXml = getFile (tmp, bundleInstallLocation);
+ if (webXml != null && webXml.exists())
+ _webApp.setDescriptor(webXml.getAbsolutePath());
+ }
+
+ //webdefault.xml
+ tmp = (String)_properties.get(OSGiWebappConstants.JETTY_DEFAULT_WEB_XML_PATH);
+ if (tmp != null)
+ {
+ File defaultWebXml = getFile (tmp, bundleInstallLocation);
+ if (defaultWebXml != null && defaultWebXml.exists())
+ _webApp.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
+ }
+
+ //Handle Require-TldBundle
+ //This is a comma separated list of names of bundles that contain tlds that this webapp uses.
+ //We add them to the webapp classloader.
+ String requireTldBundles = (String)_properties.get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
+ String pathsToTldBundles = getPathsToRequiredBundles(requireTldBundles);
+
+
+ // make sure we provide access to all the jetty bundles by going
+ // through this bundle.
+ OSGiWebappClassLoader webAppLoader = new OSGiWebappClassLoader(_serverWrapper.getParentClassLoaderForWebapps(), _webApp, _bundle);
+
+ if (pathsToTldBundles != null)
+ webAppLoader.addClassPath(pathsToTldBundles);
+ _webApp.setClassLoader(webAppLoader);
+
+
+ // apply any META-INF/context.xml file that is found to configure
+ // the webapp first
+ applyMetaInfContextXml();
+
+ // pass the value of the require tld bundle so that the TagLibOSGiConfiguration
+ // can pick it up.
+ _webApp.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundles);
+
+ //Set up some attributes
+ // rfc66
+ _webApp.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, _bundle.getBundleContext());
+
+ // spring-dm-1.2.1 looks for the BundleContext as a different attribute.
+ // not a spec... but if we want to support
+ // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
+ // then we need to do this to:
+ _webApp.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), _bundle.getBundleContext());
+
+ // also pass the bundle directly. sometimes a bundle does not have a
+ // bundlecontext.
+ // it is still useful to have access to the Bundle from the servlet
+ // context.
+ _webApp.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, _bundle);
+ }
+
+ protected String getPathsToRequiredBundles (String requireTldBundles)
+ throws Exception
+ {
+ if (requireTldBundles == null) return null;
+
+ ServiceReference ref = _bundle.getBundleContext().getServiceReference(org.osgi.service.packageadmin.PackageAdmin.class.getName());
+ PackageAdmin packageAdmin = (ref == null) ? null : (PackageAdmin)_bundle.getBundleContext().getService(ref);
+ if (packageAdmin == null)
+ throw new IllegalStateException("Unable to get PackageAdmin reference to locate required Tld bundles");
+
+ StringBuilder paths = new StringBuilder();
+ String[] symbNames = requireTldBundles.split(", ");
+
+ for (String symbName : symbNames)
+ {
+ Bundle[] bs = packageAdmin.getBundles(symbName, null);
+ if (bs == null || bs.length == 0)
+ {
+ throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
+ + "' specified by "
+ + OSGiWebappConstants.REQUIRE_TLD_BUNDLE
+ + " in manifest of "
+ + (_bundle == null ? "unknown" : _bundle.getSymbolicName()));
+ }
+
+ File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bs[0]);
+ if (paths.length() > 0) paths.append(", ");
+ paths.append(f.toURI().toURL().toString());
+ LOG.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI());
+ }
+
+ return paths.toString();
+ }
+
+
+ protected void applyMetaInfContextXml()
+ throws Exception
+ {
+ if (_bundle == null) return;
+ if (_webApp == null) return;
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ LOG.debug("Context classloader = " + cl);
+ try
+ {
+
+ Thread.currentThread().setContextClassLoader(_webApp.getClassLoader());
+
+ // find if there is a META-INF/context.xml file
+ URL contextXmlUrl = _bundle.getEntry("/META-INF/jetty-webapp-context.xml");
+ if (contextXmlUrl == null) return;
+
+ // Apply it just as the standard jetty ContextProvider would do
+ LOG.info("Applying " + contextXmlUrl + " to " + _webApp);
+
+ XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl);
+ HashMap properties = new HashMap();
+ properties.put("Server", getDeploymentManager().getServer());
+ xmlConfiguration.getProperties().putAll(properties);
+ xmlConfiguration.configure(_webApp);
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ }
+
+ private File getFile (String file, File bundleInstall)
+ {
+ if (file == null)
+ return null;
+
+ if (file.startsWith("/") || file.startsWith("file:/"))
+ return new File(file);
+ else
+ return new File(bundleInstall, file);
+ }
+ }
+
+
+ public BundleWebAppProvider (ServerInstanceWrapper wrapper)
+ {
+ _serverWrapper = wrapper;
+ }
+
+
+
+
+ /* ------------------------------------------------------------ */
+ protected void doStart() throws Exception
+ {
+ //register as an osgi service, advertising the name of the jetty Server instance we are related to
+ Dictionary properties = new Hashtable();
+ properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, _serverWrapper.getManagedServerName());
+ _serviceReg = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(this.getClass().getName(), this, properties);
+ super.doStart();
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ protected void doStop() throws Exception
+ {
+ //unregister ourselves
+ if (_serviceReg != null)
+ {
+ try
+ {
+ _serviceReg.unregister();
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ }
+ }
+ super.doStop();
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public DeploymentManager getDeploymentManager()
+ {
+ return _deploymentManager;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setDeploymentManager(DeploymentManager deploymentManager)
+ {
+ _deploymentManager = deploymentManager;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Get the parentLoaderPriority.
+ *
+ * @return the parentLoaderPriority
+ */
+ public boolean isParentLoaderPriority()
+ {
+ return _parentLoaderPriority;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the parentLoaderPriority.
+ *
+ * @param parentLoaderPriority the parentLoaderPriority to set
+ */
+ public void setParentLoaderPriority(boolean parentLoaderPriority)
+ {
+ _parentLoaderPriority = parentLoaderPriority;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Get the defaultsDescriptor.
+ *
+ * @return the defaultsDescriptor
+ */
+ public String getDefaultsDescriptor()
+ {
+ return _defaultsDescriptor;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the defaultsDescriptor.
+ *
+ * @param defaultsDescriptor the defaultsDescriptor to set
+ */
+ public void setDefaultsDescriptor(String defaultsDescriptor)
+ {
+ _defaultsDescriptor = defaultsDescriptor;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public boolean isExtract()
+ {
+ return _extractWars;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public void setExtract(boolean extract)
+ {
+ _extractWars = extract;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param tldBundles Comma separated list of bundles that contain tld jars
+ * that should be setup on the jetty instances created here.
+ */
+ public void setTldBundles(String tldBundles)
+ {
+ _tldBundles = tldBundles;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return The list of bundles that contain tld jars that should be setup on
+ * the jetty instances created here.
+ */
+ public String getTldBundles()
+ {
+ return _tldBundles;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param configurations The configuration class names.
+ */
+ public void setConfigurationClasses(String[] configurations)
+ {
+ _configurationClasses = configurations == null ? null : (String[]) configurations.clone();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ *
+ */
+ public String[] getConfigurationClasses()
+ {
+ return _configurationClasses;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void setServerInstanceWrapper(ServerInstanceWrapper wrapper)
+ {
+ _serverWrapper = wrapper;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ 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 WebAppContext suitable to deploy in OSGi
+ return ((BundleApp)app).getWebAppContext();
+ }
+
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * A bundle has been added that could be a webapp
+ * @param bundle
+ */
+ public boolean bundleAdded (Bundle bundle)
+ {
+ if (bundle == null)
+ return false;
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(_serverWrapper.getParentClassLoaderForWebapps());
+ try
+ {
+ Dictionary headers = bundle.getHeaders();
+
+ //does the bundle have a OSGiWebappConstants.JETTY_WAR_FOLDER_PATH
+ if (headers.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH) != null)
+ {
+ String base = (String)headers.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
+ String contextPath = getContextPath(bundle);
+ String originId = getOriginId(bundle, base);
+
+ BundleApp app = new BundleApp(_deploymentManager, this, bundle, originId);
+ app.setWebAppPath(base);
+ app.setContextPath(contextPath);
+ _appMap.put(originId,app);
+ _bundleMap.put(bundle, app);
+ _deploymentManager.addApp(app);
+
+ return true;
+ }
+
+
+ //does the bundle have a WEB-INF/web.xml
+ if (bundle.getEntry("/WEB-INF/web.xml") != null)
+ {
+ String base = ".";
+ String contextPath = getContextPath(bundle);
+ String originId = getOriginId(bundle, base);
+
+ BundleApp app = new BundleApp(_deploymentManager, this, bundle, originId);
+ app.setContextPath(contextPath);
+ app.setWebAppPath(base);
+ _appMap.put(originId,app);
+ _bundleMap.put(bundle, app);
+ _deploymentManager.addApp(app);
+ return true;
+ }
+
+ //does the bundle define a OSGiWebappConstants.RFC66_WEB_CONTEXTPATH
+ if (headers.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) != null)
+ {
+ //Could be a static webapp with no web.xml
+ String base = ".";
+ String contextPath = (String)headers.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
+ String originId = getOriginId(bundle,base);
+
+ BundleApp app = new BundleApp(_deploymentManager, this, bundle, originId);
+ app.setContextPath(contextPath);
+ app.setWebAppPath(base);
+ _appMap.put(originId,app);
+ _bundleMap.put(bundle, app);
+ _deploymentManager.addApp(app);
+ return true;
+ }
+
+ return false;
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Bundle has been removed. If it was a webapp we deployed, undeploy it.
+ * @param bundle
+ *
+ * @return true if this was a webapp we had deployed, false otherwise
+ */
+ public boolean bundleRemoved (Bundle bundle)
+ {
+ App app = _bundleMap.remove(bundle);
+ if (app != null)
+ {
+ _appMap.remove(app.getOriginId());
+ _deploymentManager.removeApp(app);
+ return true;
+ }
+ return false;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * A webapp that was deployed as an osgi service has been added,
+ * and we want to deploy it.
+ *
+ * @param webApp
+ */
+ public void serviceAdded (ServiceReference serviceRef, WebAppContext webApp)
+ {
+ Dictionary properties = new Hashtable();
+
+ String contextPath = (String)serviceRef.getProperty(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
+ if (contextPath == null)
+ contextPath = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
+
+ String base = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
+ if (base == null)
+ base = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_WAR);
+
+ String webdefaultXml = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_DEFAULT_WEB_XML_PATH);
+ if (webdefaultXml == null)
+ webdefaultXml = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
+ if (webdefaultXml != null)
+ properties.put(OSGiWebappConstants.JETTY_DEFAULT_WEB_XML_PATH, webdefaultXml);
+
+ String webXml = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_WEB_XML_PATH);
+ if (webXml == null)
+ webXml = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
+ if (webXml != null)
+ properties.put(OSGiWebappConstants.JETTY_WEB_XML_PATH, webXml);
+
+ String extraClassPath = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_EXTRA_CLASSPATH);
+ if (extraClassPath == null)
+ extraClassPath = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH);
+ if (extraClassPath != null)
+ properties.put(OSGiWebappConstants.JETTY_EXTRA_CLASSPATH, extraClassPath);
+
+ String bundleInstallOverride = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE);
+ if (bundleInstallOverride == null)
+ bundleInstallOverride = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE);
+ if (bundleInstallOverride != null)
+ properties.put(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE, bundleInstallOverride);
+
+ String requiredTlds = (String)serviceRef.getProperty(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
+ if (requiredTlds == null)
+ requiredTlds = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE);
+ if (requiredTlds != null)
+ properties.put(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requiredTlds);
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(_serverWrapper.getParentClassLoaderForWebapps());
+ try
+ {
+ String originId = getOriginId(serviceRef.getBundle(), base);
+ BundleApp app = new BundleApp(_deploymentManager, this, serviceRef.getBundle(), properties, originId);
+ app.setContextPath(contextPath);
+ app.setWebAppPath(base);
+ app.setWebAppContext(webApp); //set the pre=made webapp instance
+ _appMap.put(originId,app);
+ _bundleMap.put(serviceRef.getBundle(), app);
+ _deploymentManager.addApp(app);
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ }
+
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param webApp
+ */
+ public boolean serviceRemoved (ServiceReference serviceRef, WebAppContext webApp)
+ {
+ App app = _bundleMap.remove(serviceRef.getBundle());
+ if (app != null)
+ {
+ _appMap.remove(app.getOriginId());
+ _deploymentManager.removeApp(app);
+ return true;
+ }
+ return false;
+ }
+
+ /* ------------------------------------------------------------ */
+ private static String getContextPath(Bundle bundle)
+ {
+ Dictionary, ?> headers = bundle.getHeaders();
+ String contextPath = (String) headers.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
+ if (contextPath == null)
+ {
+ // extract from the last token of the bundle's location:
+ // (really ?could consider processing the symbolic name as an alternative
+ // the location will often reflect the version.
+ // maybe this is relevant when the file is a war)
+ String location = bundle.getLocation();
+ String toks[] = location.replace('\\', '/').split("/");
+ contextPath = toks[toks.length - 1];
+ // remove .jar, .war etc:
+ int lastDot = contextPath.lastIndexOf('.');
+ if (lastDot != -1)
+ contextPath = contextPath.substring(0, lastDot);
+ }
+ if (!contextPath.startsWith("/"))
+ contextPath = "/" + contextPath;
+
+ return contextPath;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ private static String getOriginId(Bundle contributor, String path)
+ {
+ return contributor.getSymbolicName() + "-" + contributor.getVersion().toString() + (path.startsWith("/") ? path : "/" + path);
+ }
+
+}
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 96b23dadc82..bf1d7176f5a 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
@@ -33,7 +33,7 @@ import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTracker;
-
+//mavenBundle().groupId( "org.eclipse.jetty.osgi" ).artifactId( "jetty-osgi-boot-jsp" ).versionAsInProject().start(),
/**
* Bootstrap jetty and publish a default Server instance as an OSGi service.
*
@@ -62,8 +62,6 @@ public class JettyBootstrapActivator implements BundleActivator
private ServiceRegistration _registeredServer;
- private Server _server;
-
private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
private PackageAdminServiceTracker _packageAdminServiceTracker;
@@ -159,10 +157,6 @@ public class JettyBootstrapActivator implements BundleActivator
}
finally
{
- if (_server != null)
- {
- _server.stop();
- }
INSTANCE = null;
}
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
new file mode 100644
index 00000000000..4fe8e63050e
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
@@ -0,0 +1,98 @@
+package org.eclipse.jetty.osgi.boot;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
+import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
+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.MetaInfConfiguration;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.osgi.framework.Bundle;
+
+public class OSGiMetaInfConfiguration extends MetaInfConfiguration
+{
+ private static final Logger LOG = Log.getLogger(OSGiMetaInfConfiguration.class);
+
+
+ /**
+ * Inspect bundle fragments associated with the bundle of the webapp for web-fragment, resources, tlds.
+ *
+ * @see org.eclipse.jetty.webapp.MetaInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void preConfigure(final WebAppContext context) throws Exception
+ {
+ List frags = (List) context.getAttribute(METAINF_FRAGMENTS);
+ List resfrags = (List) context.getAttribute(METAINF_RESOURCES);
+ List tldfrags = (List) context.getAttribute(METAINF_TLDS);
+
+ Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
+ //TODO not convinced we need to do this, as we added any fragment jars to the MetaData.webInfJars in OSGiWebInfConfiguration,
+ //so surely the web-fragments and resources tlds etc can be discovered normally?
+ for (Bundle frag : fragments)
+ {
+ URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
+ Enumeration resEnum = frag.findEntries("/META-INF/resources", "*", true);
+ Enumeration tldEnum = frag.findEntries("/META-INF", "*.tld", false);
+ if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements()))
+ {
+ try
+ {
+ if (webFrag != null)
+ {
+ if (frags == null)
+ {
+ frags = new ArrayList();
+ context.setAttribute(METAINF_FRAGMENTS, frags);
+ }
+ frags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()));
+ }
+ if (resEnum != null && resEnum.hasMoreElements())
+ {
+ URL resourcesEntry = frag.getEntry("/META-INF/resources/");
+ if (resourcesEntry == null)
+ {
+ // probably we found some fragments to a
+ // bundle.
+ // those are already contributed.
+ // so we skip this.
+ }
+ else
+ {
+ if (resfrags == null)
+ {
+ resfrags = new ArrayList();
+ context.setAttribute(METAINF_RESOURCES, resfrags);
+ }
+ resfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(resourcesEntry)));
+ }
+ }
+ if (tldEnum != null && tldEnum.hasMoreElements())
+ {
+ if (tldfrags == null)
+ {
+ tldfrags = new ArrayList();
+ context.setAttribute(METAINF_TLDS, tldfrags);
+ }
+ while (tldEnum.hasMoreElements())
+ {
+ URL tldUrl = tldEnum.nextElement();
+ tldfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(tldUrl)));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Unable to locate the bundle " + frag.getBundleId(), e);
+ }
+ }
+ }
+
+ super.preConfigure(context);
+ }
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
new file mode 100644
index 00000000000..7505e5a2e11
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
@@ -0,0 +1,255 @@
+package org.eclipse.jetty.osgi.boot;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
+import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
+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.util.resource.ResourceCollection;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.WebInfConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+
+
+/**
+ * OSGiWebInfConfiguration
+ *
+ * Handle adding resources found in bundle fragments, and add them into the
+ */
+public class OSGiWebInfConfiguration extends WebInfConfiguration
+{
+ private static final Logger LOG = Log.getLogger(WebInfConfiguration.class);
+
+
+ public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
+
+
+ /**
+ * Check to see if there have been any bundle symbolic names added of bundles that should be
+ * regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
+ * This can be defined in:
+ *
+ *
+ *
+ *
+ * We also allow individual bundles to specify particular bundles that might include TLDs via the Require-Tlds
+ * MANIFEST.MF header. This is processed in the TagLibOSGiConfiguration class.
+ *
+ * @see org.eclipse.jetty.webapp.WebInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void preConfigure(final WebAppContext context) throws Exception
+ {
+ super.preConfigure(context);
+
+ //Check to see if there have been any bundle symbolic names added of bundles that should be
+ //regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
+ //This can be defined in:
+ // 1. SystemProperty SYS_PROP_TLD_BUNDLES
+ // 2. DeployerManager.setContextAttribute CONTAINER_BUNDLE_PATTERN
+ String tmp = (String)context.getAttribute(CONTAINER_BUNDLE_PATTERN);
+ Pattern pattern = (tmp==null?null:Pattern.compile(tmp));
+ List names = new ArrayList();
+ tmp = System.getProperty("org.eclipse.jetty.osgi.tldbundles");
+ if (tmp != null)
+ {
+ StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
+ while (tokenizer.hasMoreTokens())
+ names.add(tokenizer.nextToken());
+ }
+
+ HashSet matchingResources = new HashSet();
+ if ( !names.isEmpty() || pattern != null)
+ {
+ Bundle[] bundles = FrameworkUtil.getBundle(OSGiWebInfConfiguration.class).getBundleContext().getBundles();
+
+ for (Bundle bundle : bundles)
+ {
+ if (pattern != null)
+ {
+ // if bundle symbolic name matches the pattern
+ if (pattern.matcher(bundle.getSymbolicName()).matches())
+ {
+ //get the file location of the jar and put it into the list of container jars that will be scanned for stuff (including tlds)
+ matchingResources.addAll(getBundleAsResource(bundle));
+ }
+ }
+ if (names != null)
+ {
+ //if there is an explicit bundle name, then check if it matches
+ if (names.contains(bundle.getSymbolicName()))
+ matchingResources.addAll(getBundleAsResource(bundle));
+ }
+ }
+ }
+
+ for (Resource r:matchingResources)
+ {
+ context.getMetaData().addContainerJar(r);
+ }
+ }
+
+
+
+ /**
+ * Consider the fragment bundles associated with the bundle of the webapp being deployed.
+ *
+ *
+ * @see org.eclipse.jetty.webapp.WebInfConfiguration#findJars(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ protected List findJars (WebAppContext context)
+ throws Exception
+ {
+ List mergedResources = new ArrayList();
+ //get jars from WEB-INF/lib if there are any
+ List webInfJars = super.findJars(context);
+ if (webInfJars != null)
+ mergedResources.addAll(webInfJars);
+
+ //add fragment jars as if in WEB-INF/lib of the associated webapp
+ Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
+ for (Bundle frag : fragments)
+ {
+ File fragFile = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag);
+ mergedResources.add(Resource.newResource(fragFile.toURI()));
+ }
+
+ return mergedResources;
+ }
+
+
+ /**
+ * Allow fragments to supply some resources that are added to the baseResource of the webapp.
+ *
+ * The resources can be either prepended or appended to the baseResource.
+ *
+ * @see org.eclipse.jetty.webapp.WebInfConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void configure(WebAppContext context) throws Exception
+ {
+ TreeMap patchResourcesPath = new TreeMap();
+ TreeMap appendedResourcesPath = new TreeMap();
+
+ Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
+ if (bundle != null)
+ {
+ //TODO anything we need to do to improve PackageAdminServiceTracker?
+ Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(bundle);
+ if (fragments != null && fragments.length != 0)
+ {
+ // sorted extra resource base found in the fragments.
+ // the resources are either overriding the resourcebase found in the
+ // web-bundle
+ // or appended.
+ // amongst each resource we sort them according to the alphabetical
+ // order
+ // of the name of the internal folder and the symbolic name of the
+ // fragment.
+ // this is useful to make sure that the lookup path of those
+ // resource base defined by fragments is always the same.
+ // This natural order could be abused to define the order in which
+ // the base resources are
+ // looked up.
+ for (Bundle frag : fragments)
+ {
+ String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
+ String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
+ if (fragFolder != null)
+ {
+ URL fragUrl = frag.getEntry(fragFolder);
+ if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder
+ + " inside "
+ + " the fragment '"
+ + frag.getSymbolicName()
+ + "'"); }
+ fragUrl = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(fragUrl);
+ String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder;
+ appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl));
+ }
+ if (patchFragFolder != null)
+ {
+ URL patchFragUrl = frag.getEntry(patchFragFolder);
+ if (patchFragUrl == null)
+ {
+ throw new IllegalArgumentException("Unable to locate " + patchFragUrl
+ + " inside fragment '"+frag.getSymbolicName()+ "'");
+ }
+ patchFragUrl = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(patchFragUrl);
+ String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder;
+ patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl));
+ }
+ }
+ if (!appendedResourcesPath.isEmpty())
+ context.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList(appendedResourcesPath.values()));
+ }
+ }
+
+ super.configure(context);
+
+ // place the patch resources at the beginning of the contexts's resource base
+ if (!patchResourcesPath.isEmpty())
+ {
+ Resource[] resources = new Resource[1+patchResourcesPath.size()];
+ ResourceCollection mergedResources = new ResourceCollection (patchResourcesPath.values().toArray(new Resource[patchResourcesPath.size()]));
+ System.arraycopy(patchResourcesPath.values().toArray(new Resource[patchResourcesPath.size()]), 0, resources, 0, patchResourcesPath.size());
+ resources[resources.length-1] = context.getBaseResource();
+ context.setBaseResource(new ResourceCollection(resources));
+ }
+
+ }
+
+
+
+ /**
+ * Resolves the bundle. Usually that would be a single URL per bundle. But we do some more work if there are jars
+ * embedded in the bundle.
+ */
+ private List getBundleAsResource(Bundle bundle)
+ throws Exception
+ {
+ List resources = new ArrayList();
+
+ File file = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
+ if (file.isDirectory())
+ {
+ for (File f : file.listFiles())
+ {
+ if (f.getName().endsWith(".jar") && f.isFile())
+ {
+ resources.add(Resource.newResource(f));
+ }
+ else if (f.isDirectory() && f.getName().equals("lib"))
+ {
+ for (File f2 : file.listFiles())
+ {
+ if (f2.getName().endsWith(".jar") && f2.isFile())
+ {
+ resources.add(Resource.newResource(f));
+ }
+ }
+ }
+ }
+ resources.add(Resource.newResource(file)); //TODO really???
+ }
+ else
+ {
+ resources.add(Resource.newResource(file));
+ }
+
+ return resources;
+ }
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
index 1ba8746605a..1bd0030117d 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
@@ -55,32 +55,60 @@ public class OSGiWebappConstants
* this will override static resources with the same name in the web-bundle. */
public static final String JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH = "Jetty-WarPatchFragmentFolderPath";
- // OSGi ContextHandler service properties.
- /** web app context path */
+
+ /**
+ * web app context path
+ * @deprecated see RFC66_WEB_CONTEXTPATH
+ */
public static final String SERVICE_PROP_CONTEXT_PATH = "contextPath";
- /** Path to the web application base folder */
+
+ /**
+ * Path to the web application base folder
+ * @deprecated see JETTY_WAR_FOLDER_PATH
+ */
public static final String SERVICE_PROP_WAR = "war";
- /** Extra classpath */
+ /**
+ * Extra classpath
+ * @deprecated see JETTY_EXTRA_CLASSPATH
+ */
public static final String SERVICE_PROP_EXTRA_CLASSPATH = "extraClasspath";
+
+ public static final String JETTY_EXTRA_CLASSPATH = "Jetty-extraClasspath";
- /** jetty context file path */
+ /**
+ * jetty context file path
+ * @deprecated see JETTY_CONTEXT_FILE_PATH
+ */
public static final String SERVICE_PROP_CONTEXT_FILE_PATH = "contextFilePath";
- /** web.xml file path */
+ /**
+ * web.xml file path
+ * @deprecated see JETTY_WEB_XML_PATH
+ */
public static final String SERVICE_PROP_WEB_XML_PATH = "webXmlFilePath";
+
+ public static final String JETTY_WEB_XML_PATH = "Jetty-WebXmlFilePath";
- /** defaultweb.xml file path */
+ /**
+ * defaultweb.xml file path
+ * @deprecated see JETTY_DEFAULT_WEB_XML_PATH
+ */
public static final String SERVICE_PROP_DEFAULT_WEB_XML_PATH = "defaultWebXmlFilePath";
+
+ public static final String JETTY_DEFAULT_WEB_XML_PATH = "Jetty-defaultWebXmlFilePath";
/**
* path to the base folder that overrides the computed bundle installation
* location if not null useful to install webapps or jetty context files
* that are in fact not embedded in a bundle
+ * @deprecated see JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE
*/
public static final String SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE = "thisBundleInstall";
+ public static final String JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE = "Jetty-bundleInstall";
+
/**
* Comma separated list of bundles that contain tld file used by the webapp.
*/
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 a9d2ce59667..0aea68c2b2e 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
@@ -177,8 +177,6 @@ public class DefaultJettyAtJettyHomeHelper
//register the Server instance as an OSGi service.
bundleContext.registerService(Server.class.getName(), server, properties);
- // hookNestedConnectorToBridgeServlet(server);
-
}
/**
@@ -226,6 +224,7 @@ public class DefaultJettyAtJettyHomeHelper
*/
private static String getJettyConfigurationURLs(Bundle configurationBundle)
{
+ System.err.println("GETTING JETTY PROPS FROM BUNDLE: "+configurationBundle.getSymbolicName());
String files = System.getProperty(SYS_PROP_JETTY_ETC_FILES, DEFAULT_JETTY_ETC_FILES);
StringTokenizer tokenizer = new StringTokenizer(files, ";,", false);
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 952a768a995..eb0051a8de3 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
@@ -26,14 +26,14 @@ import java.util.StringTokenizer;
import org.eclipse.jetty.deploy.AppProvider;
import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
-import org.eclipse.jetty.osgi.boot.OSGiAppProvider;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader;
+import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
-import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper;
+import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
-import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.IO;
@@ -78,9 +78,7 @@ public class ServerInstanceWrapper
private DeploymentManager _deploymentManager;
- private OSGiAppProvider _provider;
-
- private WebBundleDeployerHelper _webBundleDeployerHelper;
+ private BundleWebAppProvider _provider;
public ServerInstanceWrapper(String managedServerName)
{
@@ -114,20 +112,11 @@ public class ServerInstanceWrapper
/**
* @return The app provider registered on this server.
*/
- public OSGiAppProvider getOSGiAppProvider()
- {
- return _provider;
- }
-
public Server getServer()
{
return _server;
}
- public WebBundleDeployerHelper getWebBundleDeployerHelp()
- {
- return _webBundleDeployerHelper;
- }
/**
* @return The collection of context handlers
@@ -151,6 +140,8 @@ public class ServerInstanceWrapper
List shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
+ System.err.println("LibExtClassLoader = "+libExtClassLoader);
+
Thread.currentThread().setContextClassLoader(libExtClassLoader);
configure(server, props);
@@ -162,9 +153,11 @@ public class ServerInstanceWrapper
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
+
+ System.err.println("common classloader = "+_commonParentClassLoaderForWebapps);
server.start();
- _webBundleDeployerHelper = new WebBundleDeployerHelper(this);
+ //_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
}
catch (Exception e)
{
@@ -226,11 +219,19 @@ public class ServerInstanceWrapper
*/
private URL[] getJarsWithTlds() throws Exception
{
+
+ //Jars that are added onto the equivalent of the container classpath are:
+ // jstl jars: identified by the class WhenTag (and the boot-bundle manifest imports the jstl packages
+ // bundles identified by System property org.eclipse.jetty.osgi.tldbundles
+ // bundle symbolic name patterns defined in the DeploymentManager
+ //
+ // Any bundles mentioned in the Require-TldBundle manifest header of the webapp bundle MUST ALSO HAVE Import-Bundle
+ // in order to get them onto the classpath of the webapp.
+
ArrayList res = new ArrayList();
- WebBundleDeployerHelper.staticInit();// that is not looking great.
- for (WebappRegistrationCustomizer regCustomizer : WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS)
+ for (WebappRegistrationCustomizer regCustomizer : WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS)
{
- URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER);
+ URL[] urls = regCustomizer.getJarsWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
for (URL url : urls)
{
if (!res.contains(url)) res.add(url);
@@ -324,9 +325,11 @@ public class ServerInstanceWrapper
for (AppProvider provider : _deploymentManager.getAppProviders())
{
- if (provider instanceof OSGiAppProvider)
+ //if (provider instanceof OSGiAppProvider)
+ if (provider instanceof BundleWebAppProvider)
{
- _provider = (OSGiAppProvider) provider;
+ //_provider = (OSGiAppProvider) provider;
+ _provider = (BundleWebAppProvider)provider;
break;
}
}
@@ -335,10 +338,12 @@ public class ServerInstanceWrapper
// create it on the fly with reasonable default values.
try
{
- _provider = new OSGiAppProvider();
- _provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
+ //_provider = new OSGiAppProvider();
+ //_provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
+ _provider = new BundleWebAppProvider(this);
+ System.err.println("ADDED NEW BUNDLE WEBAPP PROVIDER");
}
- catch (IOException e)
+ catch (Exception e)
{
LOG.warn(e);
}
@@ -374,10 +379,6 @@ public class ServerInstanceWrapper
return new File(jettyHome, "/contexts");
}
- File getOSGiContextsHome()
- {
- return _provider.getContextXmlDirAsFile();
- }
/**
* @return the urls in this string.
@@ -391,7 +392,7 @@ public class ServerInstanceWrapper
String tok = tokenizer.nextToken();
try
{
- urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
+ urls.add(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(new URL(tok)));
}
catch (Throwable mfe)
{
@@ -415,7 +416,7 @@ public class ServerInstanceWrapper
try
{
URL url = new URL(tok);
- url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
+ url = BundleFileLocatorHelperFactory.getFactory().getHelper().getFileURL(url);
if (url.getProtocol().equals("file"))
{
Resource res = Resource.newResource(url);
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleFileLocatorHelperFactory.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleFileLocatorHelperFactory.java
new file mode 100644
index 00000000000..c5d4a8e9eec
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleFileLocatorHelperFactory.java
@@ -0,0 +1,41 @@
+package org.eclipse.jetty.osgi.boot.internal.webapp;
+
+
+import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * BundleFileLocatorHelperFactory
+ *
+ * Obtain a helper for locating files based on the bundle.
+ */
+public class BundleFileLocatorHelperFactory
+{
+ private static final Logger LOG = Log.getLogger(BundleFileLocatorHelperFactory.class);
+
+ private static BundleFileLocatorHelperFactory _instance = new BundleFileLocatorHelperFactory();
+
+ private BundleFileLocatorHelperFactory() {}
+
+ public static BundleFileLocatorHelperFactory getFactory()
+ {
+ return _instance;
+ }
+
+ public BundleFileLocatorHelper getHelper()
+ {
+ BundleFileLocatorHelper helper = BundleFileLocatorHelper.DEFAULT;
+ try
+ {
+ //see if a fragment has supplied an alternative
+ helper = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
+ }
+ catch (Throwable t)
+ {
+ LOG.ignore(t);
+ }
+ return helper;
+ }
+
+}
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 5edbfce6c5d..e1d5d8e65ec 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
@@ -17,6 +17,7 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
+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.OSGiWebappConstants;
@@ -34,6 +35,7 @@ import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
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
@@ -54,7 +56,11 @@ import org.osgi.framework.ServiceReference;
*/
public class JettyContextHandlerServiceTracker implements ServiceListener
{
- private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName());
+ private static Logger __logger = Log.getLogger(JettyContextHandlerServiceTracker.class.getName());
+
+ public static final String FILTER = "(objectclass=" + BundleWebAppProvider.class.getName() + ")";
+
+
/** New style: ability to manage multiple jetty instances */
private final IManagedJettyServerRegistry _registry;
@@ -71,12 +77,21 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
/** 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
*/
public JettyContextHandlerServiceTracker(IManagedJettyServerRegistry registry) throws Exception
{
_registry = registry;
+
+ //track all instances of deployers of webapps
+ Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
+ _serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
+ _serviceTracker.open();
}
public void stop() throws Exception
@@ -127,7 +142,29 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
reloadJettyContextHandler(filename, osgiContextHomeFolderCanonicalPath);
}
});
-
+ }
+
+ public BundleWebAppProvider getDeployer(String managedServerName)
+ {
+ if (managedServerName == null)
+ managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
+
+ ServiceReference sr = null;
+ ServiceReference[] references = _serviceTracker.getServiceReferences();
+ if (references != null)
+ {
+ for (ServiceReference ref:references)
+ {
+ String name = (String)ref.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
+ if (managedServerName.equalsIgnoreCase(name))
+ sr = ref;
+ }
+ }
+
+ if (sr != null)
+ return (BundleWebAppProvider)_serviceTracker.getService(sr);
+
+ return null;
}
/**
@@ -135,6 +172,9 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
*
* @param ev The ServiceEvent object.
*/
+ /**
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
public void serviceChanged(ServiceEvent ev)
{
ServiceReference sr = ev.getServiceReference();
@@ -143,7 +183,9 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
case ServiceEvent.MODIFIED:
case ServiceEvent.UNREGISTERING:
{
- ContextHandler ctxtHandler = unregisterInIndex(ev.getServiceReference());
+ //TODO unregister a ContextHandler, either with the BundleWebAppDeployer or with a BundleContextAppDeployer
+
+ /* ContextHandler ctxtHandler = unregisterInIndex(ev.getServiceReference());
if (ctxtHandler != null && !ctxtHandler.isStopped())
{
try
@@ -154,7 +196,7 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
{
__logger.warn(e);
}
- }
+ }*/
}
if (ev.getType() == ServiceEvent.UNREGISTERING)
{
@@ -175,7 +217,23 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
// is configured elsewhere.
return;
}
- String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
+
+ //Get a jetty deployer targetted to the named server instance, or the default one if not named
+ if (contextHandler instanceof WebAppContext)
+ {
+ WebAppContext webApp = (WebAppContext)contextHandler;
+
+ String whichServer = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
+ BundleWebAppProvider deployer = getDeployer(whichServer);
+ deployer.serviceAdded(sr, webApp);
+ }
+ else
+ {
+ //TODO get a reference to a jetty deployer that is happy to deploy plain ContextHandlers
+ }
+
+
+ /* String contextFilePath = (String) sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
if (contextHandler instanceof WebAppContext && contextFilePath == null)
// it could be a web-application that will in fact be configured
// via a context file.
@@ -274,8 +332,8 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
{
__logger.warn(e);
}
+ */
}
- }
break;
}
}
@@ -375,10 +433,11 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
private IWebBundleDeployerHelper getWebBundleDeployerHelp(ServiceReference sr)
{
- if (_registry == null) { return null; }
+ return null;
+ /* if (_registry == null) { return null; }
String managedServerName = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
ServerInstanceWrapper wrapper = getServerInstanceWrapper(managedServerName);
- return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;
+ return wrapper != null ? wrapper.getWebBundleDeployerHelp() : null;*/
}
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
index a4052085ed1..5c4cc383996 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
@@ -30,6 +30,7 @@ import java.util.jar.JarFile;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
+import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelperFactory;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@@ -82,12 +83,12 @@ public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleRe
* @param contributor The bundle that defines this web-application.
* @throws IOException
*/
- public OSGiWebappClassLoader(ClassLoader parent, WebAppContext context, Bundle contributor, BundleClassLoaderHelper bundleClassLoaderHelper)
+ public OSGiWebappClassLoader(ClassLoader parent, WebAppContext context, Bundle contributor)
throws IOException
{
super(parent, context);
_contributor = contributor;
- _osgiBundleClassLoader = bundleClassLoaderHelper.getBundleClassLoader(contributor);
+ _osgiBundleClassLoader = BundleClassLoaderHelperFactory.getFactory().getHelper().getBundleClassLoader(contributor);
}
/**
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java
deleted file mode 100644
index 2d8cc330eda..00000000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleDeployerHelper.java
+++ /dev/null
@@ -1,904 +0,0 @@
-// ========================================================================
-// Copyright (c) 2009 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
-// 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.internal.webapp;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TreeMap;
-
-import org.eclipse.jetty.deploy.ContextDeployer;
-import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
-import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
-import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
-import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
-import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
-import org.eclipse.jetty.osgi.boot.utils.internal.DefaultBundleClassLoaderHelper;
-import org.eclipse.jetty.osgi.boot.utils.internal.DefaultFileLocatorHelper;
-import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.util.IO;
-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.util.resource.ResourceCollection;
-import org.eclipse.jetty.webapp.FragmentConfiguration;
-import org.eclipse.jetty.webapp.TagLibConfiguration;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.eclipse.jetty.webapp.WebInfConfiguration;
-import org.eclipse.jetty.xml.XmlConfiguration;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleReference;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-import org.xml.sax.SAXException;
-
-/**
- * Bridges the jetty deployers with the OSGi lifecycle where applications are
- * managed inside OSGi-bundles.
- *
- * This class should be called as a consequence of the activation of a new
- * service that is a ContextHandler.
- * This way the new webapps are exposed as OSGi services.
- *
- *
- * Helper methods to register a bundle that is a web-application or a context.
- *
- * Limitations:
- *
- *
support for jarred webapps is somewhat limited.
- *
- */
-public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
-{
-
- private static Logger __logger = Log.getLogger(WebBundleDeployerHelper.class.getName());
-
- private static boolean INITIALIZED = false;
-
- /**
- * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
- * equinox and apache-felix fragment bundles that are specific to an OSGi
- * implementation should set a different implementation.
- */
- public static BundleClassLoaderHelper BUNDLE_CLASS_LOADER_HELPER = null;
-
- /**
- * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
- * equinox and apache-felix fragment bundles that are specific to an OSGi
- * implementation should set a different implementation.
- */
- public static BundleFileLocatorHelper BUNDLE_FILE_LOCATOR_HELPER = null;
-
- /**
- * By default set to: {@link DefaultBundleClassLoaderHelper}. It supports
- * equinox and apache-felix fragment bundles that are specific to an OSGi
- * implementation should set a different implementation.
- *
- * Several of those objects can be added here: For example we could have an
- * optional fragment that setups a specific implementation of JSF for the
- * whole of jetty-osgi.
- *
- */
- public static Collection JSP_REGISTRATION_HELPERS = new ArrayList();
-
- /**
- * this class loader loads the jars inside {$jetty.home}/lib/ext it is meant
- * as a migration path and for jars that are not OSGi ready. also gives
- * access to the jsp jars.
- */
- // private URLClassLoader _libExtClassLoader;
-
- private ServerInstanceWrapper _wrapper;
-
- public WebBundleDeployerHelper(ServerInstanceWrapper wrapper)
- {
- staticInit();
- _wrapper = wrapper;
- }
-
- // Inject the customizing classes that might be defined in fragment bundles.
- public static synchronized void staticInit()
- {
- if (!INITIALIZED)
- {
- INITIALIZED = true;
- // setup the custom BundleClassLoaderHelper
- try
- {
- BUNDLE_CLASS_LOADER_HELPER = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
- }
- catch (Throwable t)
- {
- // System.err.println("support for equinox and felix");
- BUNDLE_CLASS_LOADER_HELPER = new DefaultBundleClassLoaderHelper();
- }
- // setup the custom FileLocatorHelper
- try
- {
- BUNDLE_FILE_LOCATOR_HELPER = (BundleFileLocatorHelper) Class.forName(BundleFileLocatorHelper.CLASS_NAME).newInstance();
- }
- catch (Throwable t)
- {
- // System.err.println("no jsp/jasper support");
- BUNDLE_FILE_LOCATOR_HELPER = new DefaultFileLocatorHelper();
- }
- }
- }
-
- /**
- * Deploy a new web application on the jetty server.
- *
- * @param bundle The bundle
- * @param webappFolderPath The path to the root of the webapp. Must be a
- * path relative to bundle; either an absolute path.
- * @param contextPath The context path. Must start with "/"
- * @param extraClasspath
- * @param overrideBundleInstallLocation
- * @param requireTldBundle The list of bundles's symbolic names that contain
- * tld files that are required by this WAB.
- * @param webXmlPath
- * @param defaultWebXmlPath TODO: parameter description
- * @return The contexthandler created and started
- * @throws Exception
- */
- public WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath,
- String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath, String defaultWebXmlPath,
- WebAppContext webAppContext)
- throws Exception
- {
- File bundleInstall = overrideBundleInstallLocation == null ? BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle) : new File(overrideBundleInstallLocation);
- File webapp = null;
- URL baseWebappInstallURL = null;
-
- if (webappFolderPath != null && webappFolderPath.length() != 0 && !webappFolderPath.equals("."))
- {
- if (webappFolderPath.startsWith("/") || webappFolderPath.startsWith("file:"))
- {
- webapp = new File(webappFolderPath);
- }
- else if (bundleInstall != null && bundleInstall.isDirectory())
- {
- webapp = new File(bundleInstall, webappFolderPath);
- }
- else if (bundleInstall != null)
- {
- Enumeration urls = BUNDLE_FILE_LOCATOR_HELPER.findEntries(bundle, webappFolderPath);
- if (urls != null && urls.hasMoreElements())
- {
- baseWebappInstallURL = urls.nextElement();
- }
- }
- }
- else
- {
- webapp = bundleInstall;
- }
- if (baseWebappInstallURL == null && (webapp == null || !webapp.exists()))
- {
- throw new IllegalArgumentException("Unable to locate " + webappFolderPath
- + " inside "
- + (bundleInstall != null ? bundleInstall.getAbsolutePath() : "unlocated bundle '" + bundle.getSymbolicName()+ "'"));
- }
- if (baseWebappInstallURL == null && webapp != null)
- {
- baseWebappInstallURL = webapp.toURI().toURL();
- }
- return registerWebapplication(bundle, webappFolderPath, baseWebappInstallURL, contextPath, extraClasspath, bundleInstall, requireTldBundle, webXmlPath,
- defaultWebXmlPath, webAppContext);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
- * registerWebapplication(org.osgi.framework.Bundle, java.lang.String,
- * java.io.File, java.lang.String, java.lang.String, java.io.File,
- * java.lang.String, java.lang.String)
- */
- private WebAppContext registerWebapplication(Bundle contributor, String pathInBundleToWebApp, URL baseWebappInstallURL, String contextPath,
- String extraClasspath, File bundleInstall, String requireTldBundle, String webXmlPath,
- String defaultWebXmlPath, WebAppContext context)
- throws Exception
- {
- ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
- String[] oldServerClasses = null;
-
- try
- {
-
- // apply any META-INF/context.xml file that is found to configure
- // the webapp first
- applyMetaInfContextXml(contributor, context);
-
- // make sure we provide access to all the jetty bundles by going
- // through this bundle.
- OSGiWebappClassLoader composite = createWebappClassLoader(contributor);
- // configure with access to all jetty classes and also all the
- // classes
- // that the contributor gives access to.
- Thread.currentThread().setContextClassLoader(composite);
-
- // converts bundleentry: protocol
- baseWebappInstallURL = DefaultFileLocatorHelper.getLocalURL(baseWebappInstallURL);
-
- context.setWar(baseWebappInstallURL.toString());
- context.setContextPath(contextPath);
- context.setExtraClasspath(extraClasspath);
-
- if (webXmlPath != null && webXmlPath.length() != 0)
- {
- File webXml = null;
- if (webXmlPath.startsWith("/") || webXmlPath.startsWith("file:/"))
- {
- webXml = new File(webXmlPath);
- }
- else
- {
- webXml = new File(bundleInstall, webXmlPath);
- }
- if (webXml.exists())
- {
- context.setDescriptor(webXml.getAbsolutePath());
- }
- }
-
- if (defaultWebXmlPath == null || defaultWebXmlPath.length() == 0)
- {
- // use the one defined by the OSGiAppProvider.
- defaultWebXmlPath = _wrapper.getOSGiAppProvider().getDefaultsDescriptor();
- }
- if (defaultWebXmlPath != null && defaultWebXmlPath.length() != 0)
- {
- File defaultWebXml = null;
- if (defaultWebXmlPath.startsWith("/") || defaultWebXmlPath.startsWith("file:/"))
- {
- defaultWebXml = new File(defaultWebXmlPath);
- }
- else
- {
- defaultWebXml = new File(bundleInstall, defaultWebXmlPath);
- }
- if (defaultWebXml.exists())
- {
- context.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
- }
- }
-
- // other parameters that might be defines on the OSGiAppProvider:
- context.setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
-
- configureWebappClassLoader(contributor, context, composite, requireTldBundle);
- configureWebAppContext(context, contributor, requireTldBundle);
-
- // @see
- // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
- // during initialization of the webapp all the jetty packages are
- // visible
- // through the webapp classloader.
- oldServerClasses = context.getServerClasses();
- context.setServerClasses(null);
-
- _wrapper.getOSGiAppProvider().addContext(contributor, pathInBundleToWebApp, context);
-
- // support for patch resources. ideally this should be done inside a
- // configurator.
- List patchResources = (List) context.getAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch");
- if (patchResources != null)
- {
- LinkedList resourcesPath = new LinkedList();
- // place the patch resources at the beginning of the lookup
- // path.
- resourcesPath.addAll(patchResources);
- // then place the ones from the host web bundle.
- Resource hostResources = context.getBaseResource();
- if (hostResources instanceof ResourceCollection)
- {
- for (Resource re : ((ResourceCollection) hostResources).getResources())
- {
- resourcesPath.add(re);
- }
- }
- else
- {
- resourcesPath.add(hostResources);
- }
-
- ResourceCollection rc = new ResourceCollection(resourcesPath.toArray(new Resource[resourcesPath.size()]));
- context.setBaseResource(rc);
- }
-
- return context;
- }
- finally
- {
- if (context != null && oldServerClasses != null)
- {
- context.setServerClasses(oldServerClasses);
- }
- Thread.currentThread().setContextClassLoader(contextCl);
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
- * unregister(org.eclipse.jetty.server.handler.ContextHandler)
- */
- public void unregister(ContextHandler contextHandler)
- throws Exception
- {
- _wrapper.getOSGiAppProvider().removeContext(contextHandler);
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper#
- * registerContext(org.osgi.framework.Bundle, java.lang.String,
- * java.lang.String, java.lang.String)
- */
- public ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath, String overrideBundleInstallLocation,
- String requireTldBundle, ContextHandler handler)
- throws Exception
- {
- File contextsHome = _wrapper.getOSGiAppProvider().getContextXmlDirAsFile();
- if (contextsHome != null)
- {
- File prodContextFile = new File(contextsHome, contributor.getSymbolicName() + "/" + contextFileRelativePath);
- if (prodContextFile.exists()) { return registerContext(contributor, contextFileRelativePath, prodContextFile, extraClasspath,
- overrideBundleInstallLocation, requireTldBundle, handler); }
- }
- File rootFolder = overrideBundleInstallLocation != null ? Resource.newResource(overrideBundleInstallLocation).getFile() : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(contributor);
- File contextFile = rootFolder != null ? new File(rootFolder, contextFileRelativePath) : null;
- if (contextFile != null && contextFile.exists())
- {
- return registerContext(contributor, contextFileRelativePath, contextFile, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
- }
- else
- {
- if (contextFileRelativePath.startsWith("./"))
- {
- contextFileRelativePath = contextFileRelativePath.substring(1);
- }
- if (!contextFileRelativePath.startsWith("/"))
- {
- contextFileRelativePath = "/" + contextFileRelativePath;
- }
-
- URL contextURL = contributor.getEntry(contextFileRelativePath);
- if (contextURL != null)
- {
- Resource r = Resource.newResource(contextURL);
- return registerContext(contributor, contextFileRelativePath, r.getInputStream(), extraClasspath, overrideBundleInstallLocation,
- requireTldBundle, handler);
- }
- throw new IllegalArgumentException("Could not find the context " + "file "
- + contextFileRelativePath
- + " for the bundle "
- + contributor.getSymbolicName()
- + (overrideBundleInstallLocation != null ? " using the install location " + overrideBundleInstallLocation : ""));
- }
- }
-
- /**
- * This type of registration relies on jetty's complete context xml file.
- * Context encompasses jndi and all other things. This makes the definition
- * of the webapp a lot more self-contained.
- *
- * @param webapp
- * @param contextPath
- * @param classInBundle
- * @throws Exception
- */
- private ContextHandler registerContext(Bundle contributor, String pathInBundle, File contextFile, String extraClasspath,
- String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler)
- throws Exception
- {
- InputStream contextFileInputStream = null;
- try
- {
- contextFileInputStream = new BufferedInputStream(new FileInputStream(contextFile));
- return registerContext(contributor, pathInBundle, contextFileInputStream, extraClasspath, overrideBundleInstallLocation, requireTldBundle, handler);
- }
- finally
- {
- IO.close(contextFileInputStream);
- }
- }
-
- /**
- * @param contributor
- * @param contextFileInputStream
- * @return The ContextHandler created and registered or null if it did not
- * happen.
- * @throws Exception
- */
- private ContextHandler registerContext(Bundle contributor, String pathInsideBundle, InputStream contextFileInputStream, String extraClasspath,
- String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler)
- throws Exception
- {
- ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
- String[] oldServerClasses = null;
- WebAppContext webAppContext = null;
- try
- {
- // make sure we provide access to all the jetty bundles by going
- // through this bundle.
- OSGiWebappClassLoader composite = createWebappClassLoader(contributor);
- // configure with access to all jetty classes and also all the
- // classes
- // that the contributor gives access to.
- Thread.currentThread().setContextClassLoader(composite);
- ContextHandler context = createContextHandler(handler, contributor, contextFileInputStream, extraClasspath, overrideBundleInstallLocation,
- requireTldBundle);
- if (context == null) { return null;// did not happen
- }
-
- // ok now register this webapp. we checked when we started jetty
- // that there
- // was at least one such handler for webapps.
- // the actual registration must happen via the new Deployment API.
- // _ctxtHandler.addHandler(context);
-
- configureWebappClassLoader(contributor, context, composite, requireTldBundle);
- if (context instanceof WebAppContext)
- {
- webAppContext = (WebAppContext) context;
- // @see
- // org.eclipse.jetty.webapp.JettyWebXmlConfiguration#configure(WebAppContext)
- oldServerClasses = webAppContext.getServerClasses();
- webAppContext.setServerClasses(null);
- }
- _wrapper.getOSGiAppProvider().addContext(contributor, pathInsideBundle, context);
- return context;
- }
- finally
- {
- if (webAppContext != null)
- {
- webAppContext.setServerClasses(oldServerClasses);
- }
- Thread.currentThread().setContextClassLoader(contextCl);
- }
-
- }
-
- /**
- * Applies the properties of WebAppDeployer as defined in jetty.xml.
- *
- * @see {WebAppDeployer#scan} around the comment
- * // configure it
- */
- protected void configureWebAppContext(ContextHandler wah, Bundle contributor, String requireTldBundle)
- throws IOException
- {
- // rfc66
- wah.setAttribute(OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, contributor.getBundleContext());
-
- // spring-dm-1.2.1 looks for the BundleContext as a different attribute.
- // not a spec... but if we want to support
- // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
- // then we need to do this to:
- wah.setAttribute("org.springframework.osgi.web." + BundleContext.class.getName(), contributor.getBundleContext());
-
- // also pass the bundle directly. sometimes a bundle does not have a
- // bundlecontext.
- // it is still useful to have access to the Bundle from the servlet
- // context.
- wah.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, contributor);
-
- // pass the value of the require tld bundle so that the
- // TagLibOSGiConfiguration
- // can pick it up.
- wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle);
-
- Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor);
- if (fragments != null && fragments.length != 0)
- {
- // sorted extra resource base found in the fragments.
- // the resources are either overriding the resourcebase found in the
- // web-bundle
- // or appended.
- // amongst each resource we sort them according to the alphabetical
- // order
- // of the name of the internal folder and the symbolic name of the
- // fragment.
- // this is useful to make sure that the lookup path of those
- // resource base defined by fragments is always the same.
- // This natural order could be abused to define the order in which
- // the base resources are
- // looked up.
- TreeMap patchResourcesPath = new TreeMap();
- TreeMap appendedResourcesPath = new TreeMap();
- for (Bundle frag : fragments)
- {
- String fragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH);
- String patchFragFolder = (String) frag.getHeaders().get(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH);
- if (fragFolder != null)
- {
- URL fragUrl = frag.getEntry(fragFolder);
- if (fragUrl == null) { throw new IllegalArgumentException("Unable to locate " + fragFolder
- + " inside "
- + " the fragment '"
- + frag.getSymbolicName()
- + "'"); }
- fragUrl = DefaultFileLocatorHelper.getLocalURL(fragUrl);
- String key = fragFolder.startsWith("/") ? fragFolder.substring(1) : fragFolder;
- appendedResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(fragUrl));
- }
- if (patchFragFolder != null)
- {
- URL patchFragUrl = frag.getEntry(patchFragFolder);
- if (patchFragUrl == null) { throw new IllegalArgumentException("Unable to locate " + patchFragUrl
- + " inside "
- + " the fragment '"
- + frag.getSymbolicName()
- + "'"); }
- patchFragUrl = DefaultFileLocatorHelper.getLocalURL(patchFragUrl);
- String key = patchFragFolder.startsWith("/") ? patchFragFolder.substring(1) : patchFragFolder;
- patchResourcesPath.put(key + ";" + frag.getSymbolicName(), Resource.newResource(patchFragUrl));
- }
- }
- if (!appendedResourcesPath.isEmpty())
- {
- wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, new ArrayList(appendedResourcesPath.values()));
- }
- if (!patchResourcesPath.isEmpty())
- {
- wah.setAttribute(WebInfConfiguration.RESOURCE_URLS + ".patch", new ArrayList(patchResourcesPath.values()));
- }
-
- if (wah instanceof WebAppContext)
- {
- // This is the equivalent of what MetaInfConfiguration does. For
- // OSGi bundles without the JarScanner
- WebAppContext webappCtxt = (WebAppContext) wah;
- // take care of the web-fragments, meta-inf resources and tld
- // resources:
- // similar to what MetaInfConfiguration does.
- List frags = (List) wah.getAttribute(FragmentConfiguration.FRAGMENT_RESOURCES);
- List resfrags = (List) wah.getAttribute(WebInfConfiguration.RESOURCE_URLS);
- List tldfrags = (List) wah.getAttribute(TagLibConfiguration.TLD_RESOURCES);
- for (Bundle frag : fragments)
- {
- URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
- Enumeration resEnum = frag.findEntries("/META-INF/resources", "*", true);
- Enumeration tldEnum = frag.findEntries("/META-INF", "*.tld", false);
- if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements()))
- {
- try
- {
- File fragFile = BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(frag);
- // add it to the webinf jars collection:
- // no need to check that it was not there yet: it
- // was not there yet for sure.
- Resource fragFileAsResource = Resource.newResource(fragFile.toURI());
- webappCtxt.getMetaData().addWebInfJar(fragFileAsResource);
-
- if (webFrag != null)
- {
- if (frags == null)
- {
- frags = new ArrayList();
- wah.setAttribute(FragmentConfiguration.FRAGMENT_RESOURCES, frags);
- }
- frags.add(fragFileAsResource);
- }
- if (resEnum != null && resEnum.hasMoreElements())
- {
- URL resourcesEntry = frag.getEntry("/META-INF/resources/");
- if (resourcesEntry == null)
- {
- // probably we found some fragments to a
- // bundle.
- // those are already contributed.
- // so we skip this.
- }
- else
- {
- if (resfrags == null)
- {
- resfrags = new ArrayList();
- wah.setAttribute(WebInfConfiguration.RESOURCE_URLS, resfrags);
- }
- resfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(resourcesEntry)));
- }
- }
- if (tldEnum != null && tldEnum.hasMoreElements())
- {
- if (tldfrags == null)
- {
- tldfrags = new ArrayList();
- wah.setAttribute(TagLibConfiguration.TLD_RESOURCES, tldfrags);
- }
- while (tldEnum.hasMoreElements())
- {
- URL tldUrl = tldEnum.nextElement();
- tldfrags.add(Resource.newResource(DefaultFileLocatorHelper.getLocalURL(tldUrl)));
- }
- }
- }
- catch (Exception e)
- {
- __logger.warn("Unable to locate the bundle " + frag.getBundleId(), e);
- }
- }
- }
- }
- }
- }
-
- /**
- * @See {@link ContextDeployer#scan}
- * @param contextFile
- * @return
- */
- protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, File contextFile, String extraClasspath,
- String overrideBundleInstallLocation, String requireTldBundle)
- {
- try
- {
- return createContextHandler(handlerToConfigure, bundle, new BufferedInputStream(new FileInputStream(contextFile)), extraClasspath,
- overrideBundleInstallLocation, requireTldBundle);
- }
- catch (FileNotFoundException e)
- {
- __logger.warn(e);
- }
- return null;
- }
-
- /**
- * @See {@link ContextDeployer#scan}
- * @param contextFile
- * @return
- */
- @SuppressWarnings("unchecked")
- protected ContextHandler createContextHandler(ContextHandler handlerToConfigure, Bundle bundle, InputStream contextInputStream, String extraClasspath,
- String overrideBundleInstallLocation, String requireTldBundle)
- {
- /*
- * Do something identical to what the ContextProvider would have done:
- * XmlConfiguration xmlConfiguration=new
- * XmlConfiguration(resource.getURL()); HashMap properties = new
- * HashMap(); properties.put("Server", _contexts.getServer()); if
- * (_configMgr!=null) properties.putAll(_configMgr.getProperties());
- *
- * xmlConfiguration.setProperties(properties); ContextHandler
- * context=(ContextHandler)xmlConfiguration.configure();
- * context.setAttributes(new AttributesMap(_contextAttributes));
- */
- try
- {
- XmlConfiguration xmlConfiguration = new XmlConfiguration(contextInputStream);
- 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);
-
- ContextHandler context = null;
- if (handlerToConfigure == null)
- {
- context = (ContextHandler) xmlConfiguration.configure();
- }
- else
- {
- xmlConfiguration.configure(handlerToConfigure);
- context = handlerToConfigure;
- }
-
- if (context instanceof WebAppContext)
- {
- ((WebAppContext) context).setExtraClasspath(extraClasspath);
- ((WebAppContext) context).setParentLoaderPriority(_wrapper.getOSGiAppProvider().isParentLoaderPriority());
- if (_wrapper.getOSGiAppProvider().getDefaultsDescriptor() != null && _wrapper.getOSGiAppProvider().getDefaultsDescriptor().length() != 0)
- {
- ((WebAppContext) context).setDefaultsDescriptor(_wrapper.getOSGiAppProvider().getDefaultsDescriptor());
- }
- }
-
- configureWebAppContext(context, bundle, requireTldBundle);
- return context;
- }
- catch (FileNotFoundException e)
- {
- return null;
- }
- catch (SAXException e)
- {
- __logger.warn(e);
- }
- catch (IOException e)
- {
- __logger.warn(e);
- }
- catch (Throwable e)
- {
- __logger.warn(e);
- }
- finally
- {
- IO.close(contextInputStream);
- }
- return null;
- }
-
- /**
- * Configure a classloader onto the context. If the context is a
- * WebAppContext, build a WebAppClassLoader that has access to all the jetty
- * classes thanks to the classloader of the JettyBootStrapper bundle and
- * also has access to the classloader of the bundle that defines this
- * context.
- *
- * If the context is not a WebAppContext, same but with a simpler
- * URLClassLoader. Note that the URLClassLoader is pretty much fake: it
- * delegate all actual classloading to the parent classloaders.
- *
- *
- * The URL[] returned by the URLClassLoader create contained specifically
- * the jars that some j2ee tools expect and look into. For example the jars
- * that contain tld files for jasper's jstl support.
- *
- *
- * Also as the jars in the lib folder and the classes in the classes folder
- * might already be in the OSGi classloader we filter them out of the
- * WebAppClassLoader
- *
- *
- * @param context
- * @param contributor
- * @param webapp
- * @param contextPath
- * @param classInBundle
- * @throws Exception
- */
- protected void configureWebappClassLoader(Bundle contributor, ContextHandler context, OSGiWebappClassLoader webappClassLoader, String requireTldBundle)
- throws Exception
- {
- if (context instanceof WebAppContext)
- {
- WebAppContext webappCtxt = (WebAppContext) context;
- context.setClassLoader(webappClassLoader);
- webappClassLoader.setWebappContext(webappCtxt);
-
- String pathsToRequiredBundles = getPathsToRequiredBundles(context, contributor, requireTldBundle);
- if (pathsToRequiredBundles != null) webappClassLoader.addClassPath(pathsToRequiredBundles);
- }
- else
- {
- context.setClassLoader(webappClassLoader);
- }
- }
-
- /**
- * No matter what the type of webapp, we create a WebappClassLoader.
- */
- protected OSGiWebappClassLoader createWebappClassLoader(Bundle contributor)
- throws Exception
- {
- // we use a temporary WebAppContext object.
- // if this is a real webapp we will set it on it a bit later: once we
- // know.
- OSGiWebappClassLoader webappClassLoader = new OSGiWebappClassLoader(_wrapper.getParentClassLoaderForWebapps(), new WebAppContext(), contributor,
- BUNDLE_CLASS_LOADER_HELPER);
- return webappClassLoader;
- }
-
- protected void applyMetaInfContextXml(Bundle bundle, ContextHandler contextHandler)
- throws Exception
- {
- if (bundle == null) return;
- if (contextHandler == null) return;
-
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- __logger.info("Context classloader = " + cl);
- try
- {
- Thread.currentThread().setContextClassLoader(_wrapper.getParentClassLoaderForWebapps());
-
- // find if there is a META-INF/context.xml file
- URL contextXmlUrl = bundle.getEntry("/META-INF/jetty-webapp-context.xml");
- if (contextXmlUrl == null) return;
-
- // Apply it just as the standard jetty ContextProvider would do
- __logger.info("Applying " + contextXmlUrl + " to " + contextHandler);
-
- XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXmlUrl);
- HashMap properties = new HashMap();
- properties.put("Server", _wrapper.getServer());
- xmlConfiguration.getProperties().putAll(properties);
- xmlConfiguration.configure(contextHandler);
- }
- 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) : BUNDLE_FILE_LOCATOR_HELPER.getBundleInstallLocation(bundle);
- properties.put("this.bundle.install", location.getCanonicalPath());
- properties.put("this.bundle.install.url", bundle.getEntry("/").toString());
- }
- catch (Throwable t)
- {
- __logger.warn("Unable to set 'this.bundle.install' " + " for the bundle " + bundle.getSymbolicName(), t);
- }
- }
-
- private String getPathsToRequiredBundles(ContextHandler context, Bundle bundle, String requireTldBundle)
- throws Exception
- {
- if (requireTldBundle == null) return null;
-
- StringBuilder paths = new StringBuilder();
- PackageAdmin packAdmin = getBundleAdmin();
- DefaultFileLocatorHelper fileLocatorHelper = new DefaultFileLocatorHelper();
-
- String[] symbNames = requireTldBundle.split(", ");
-
- for (String symbName : symbNames)
- {
- Bundle[] bs = packAdmin.getBundles(symbName, null);
- if (bs == null || bs.length == 0) { throw new IllegalArgumentException("Unable to locate the bundle '" + symbName
- + "' specified in the "
- + OSGiWebappConstants.REQUIRE_TLD_BUNDLE
- + " of the manifest of "
- + (bundle == null ? "unknown" : bundle.getSymbolicName())); }
-
- File f = fileLocatorHelper.getBundleInstallLocation(bs[0]);
- if (paths.length() > 0) paths.append(", ");
- __logger.debug("getPathsToRequiredBundles: bundle path=" + bs[0].getLocation() + " uri=" + f.toURI());
- paths.append(f.toURI().toURL().toString());
- }
-
- return paths.toString();
- }
-
- private PackageAdmin getBundleAdmin()
- {
- Bundle bootBundle = ((BundleReference) OSGiWebappConstants.class.getClassLoader()).getBundle();
- ServiceTracker serviceTracker = new ServiceTracker(bootBundle.getBundleContext(), PackageAdmin.class.getName(), null);
- serviceTracker.open();
-
- return (PackageAdmin) serviceTracker.getService();
- }
-}
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 134b890135a..3a6a42f6f39 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
@@ -13,16 +13,25 @@
package org.eclipse.jetty.osgi.boot.internal.webapp;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Dictionary;
+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.OSGiWebappConstants;
+import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry;
+import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
+import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.osgi.util.tracker.ServiceTracker;
/**
* Support bundles that declare the webapp directly through headers in their
@@ -41,16 +50,28 @@ import org.osgi.util.tracker.BundleTrackerCustomizer;
*
Jetty-ContextFilePath
*
*
- * And generate a jetty WebAppContext or another ContextHandler then registers
- * it as service. Kind of simpler than declarative services and their xml files.
- * Also avoid having the contributing bundle depend on jetty's package for
- * WebApp.
*
* @author hmalphettes
*/
public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
{
private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
+
+ public static Collection JSP_REGISTRATION_HELPERS = new ArrayList();
+ public static final String FILTER = "(&(objectclass=" + BundleWebAppProvider.class.getName() + ")"+
+ "("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
+
+ private ServiceTracker _serviceTracker;
+
+ public WebBundleTrackerCustomizer ()
+ throws Exception
+ {
+ Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
+
+ //track all instances of deployers of webapps as bundles
+ _serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
+ _serviceTracker.open();
+ }
/**
* A bundle is being added to the BundleTracker.
@@ -76,8 +97,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
{
if (bundle.getState() == Bundle.ACTIVE)
{
- boolean isWebBundle = register(bundle);
- return isWebBundle ? bundle : null;
+ register(bundle);
}
else if (bundle.getState() == Bundle.STOPPING)
{
@@ -142,123 +162,25 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
*/
private boolean register(Bundle bundle)
{
- Dictionary, ?> dic = bundle.getHeaders();
- String warFolderRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
- if (warFolderRelativePath != null)
- {
- String contextPath = getWebContextPath(bundle, dic, false);
- if (contextPath == null || !contextPath.startsWith("/"))
- {
- LOG.warn("The manifest header '" + OSGiWebappConstants.JETTY_WAR_FOLDER_PATH
- + ": "
- + warFolderRelativePath
- + "' in the bundle "
- + bundle.getSymbolicName()
- + " is not valid: there is no Web-ContextPath defined in the manifest.");
- return false;
- }
- // create the corresponding service and publish it in the context of
- // the contributor bundle.
- try
- {
- JettyBootstrapActivator.registerWebapplication(bundle, warFolderRelativePath, contextPath);
- return true;
- }
- catch (Throwable e)
- {
- LOG.warn("Starting the web-bundle " + bundle.getSymbolicName() + " threw an exception.", e);
- return true;// maybe it did not work maybe it did. safer to track this bundle.
- }
- }
- else if (dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH) != null)
- {
- String contextFileRelativePath = (String) dic.get(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
- if (contextFileRelativePath == null)
- {
- // nothing to register here.
- return false;
- }
- // support for multiple webapps in the same bundle:
- String[] pathes = contextFileRelativePath.split(",;");
- for (String path : pathes)
- {
- try
- {
- JettyBootstrapActivator.registerContext(bundle, path.trim());
- }
- catch (Throwable e)
- {
- LOG.warn(e);
- }
- }
- return true;
- }
- else
- {
- // support for OSGi-RFC66; disclaimer, no access to the actual
- // (draft) of the spec: just a couple of posts on the
- // world-wide-web.
- URL rfc66Webxml = bundle.getEntry("/WEB-INF/web.xml");
- if (rfc66Webxml == null && dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH) == null)
- {
- return false;// no webapp in here
- }
- // this is risky: should we make sure that there is no classes and
- // jars directly available
- // at the root of the of the bundle: otherwise they are accessible
- // through the browser. we should enforce that the whole classpath
- // is
- // pointing to files and folders inside WEB-INF. We should
- // filter-out
- // META-INF too
- String rfc66ContextPath = getWebContextPath(bundle, dic, rfc66Webxml == null);
- try
- {
- JettyBootstrapActivator.registerWebapplication(bundle, ".", rfc66ContextPath);
- return true;
- }
- catch (Throwable e)
- {
- LOG.warn(e);
- return true;// maybe it did not work maybe it did. safer to track this bundle.
- }
- }
- }
+ if (bundle == null)
+ return false;
+
+ //It might be a webapp bundle
+ //If it is, it will be deployed to our default jetty Server instance.
+ //Get a reference to a jetty BundleWebAppProvider as an osgi service that can do the deployment
- private String getWebContextPath(Bundle bundle, Dictionary, ?> dic, boolean webinfWebxmlExists)
- {
- String rfc66ContextPath = (String) dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
- if (rfc66ContextPath == null)
- {
- if (!webinfWebxmlExists) { return null; }
- // extract from the last token of the bundle's location:
- // (really ?
- // could consider processing the symbolic name as an alternative
- // the location will often reflect the version.
- // maybe this is relevant when the file is a war)
- String location = bundle.getLocation();
- String toks[] = location.replace('\\', '/').split("/");
- rfc66ContextPath = toks[toks.length - 1];
- // remove .jar, .war etc:
- int lastDot = rfc66ContextPath.lastIndexOf('.');
- if (lastDot != -1)
- {
- rfc66ContextPath = rfc66ContextPath.substring(0, lastDot);
- }
- }
- if (!rfc66ContextPath.startsWith("/"))
- {
- rfc66ContextPath = "/" + rfc66ContextPath;
- }
- return rfc66ContextPath;
- }
+ BundleWebAppProvider deployer = (BundleWebAppProvider)_serviceTracker.getService();
+ if (deployer != null)
+ return deployer.bundleAdded(bundle);
+ return false;
+ }
+
+
private void unregister(Bundle bundle)
{
- // nothing to do: when the bundle is stopped, each one of its service
- // reference is also stopped and that is what we use to stop the
- // corresponding
- // webapps registered in that bundle.
+ BundleWebAppProvider deployer = (BundleWebAppProvider)_serviceTracker.getService();
+ if (deployer != null)
+ deployer.bundleRemoved(bundle);
}
-
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
new file mode 100644
index 00000000000..cc1a2871e38
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
@@ -0,0 +1,44 @@
+package org.eclipse.jetty.osgi.boot.utils;
+
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * BundleClassLoaderHelperFactory
+ *
+ * Get a class loader helper adapted for the particular osgi environment.
+ */
+public class BundleClassLoaderHelperFactory
+{
+ private static final Logger LOG = Log.getLogger(BundleClassLoaderHelperFactory.class);
+
+ private static BundleClassLoaderHelperFactory _instance = new BundleClassLoaderHelperFactory();
+
+ public static BundleClassLoaderHelperFactory getFactory()
+ {
+ return _instance;
+ }
+
+ private BundleClassLoaderHelperFactory()
+ {
+ }
+
+ public BundleClassLoaderHelper getHelper()
+ {
+ //use the default
+ BundleClassLoaderHelper helper = BundleClassLoaderHelper.DEFAULT;
+ try
+ {
+ //if a fragment has not provided their own impl
+ helper = (BundleClassLoaderHelper) Class.forName(BundleClassLoaderHelper.CLASS_NAME).newInstance();
+ }
+ catch (Throwable t)
+ {
+ LOG.ignore(t);
+ }
+
+ return helper;
+ }
+
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
index 44b7d8769af..f37178a6146 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
@@ -83,5 +83,31 @@ public interface BundleFileLocatorHelper
* @return null or all the entries found for that path.
*/
public Enumeration findEntries(Bundle bundle, String entryPath);
+
+ /**
+ * Only useful for equinox: on felix we get the file:// or jar:// url
+ * already. Other OSGi implementations have not been tested
+ *
+ * Get a URL to the bundle entry that uses a common protocol (i.e. file:
+ * jar: or http: etc.).
+ *
+ *
+ * @return a URL to the bundle entry that uses a common protocol
+ */
+ public URL getLocalURL(URL url);
+
+ /**
+ * Only useful for equinox: on felix we get the file:// url already. Other
+ * OSGi implementations have not been tested
+ *
+ * Get a URL to the content of the bundle entry that uses the file:
+ * protocol. The content of the bundle entry may be downloaded or extracted
+ * to the local file system in order to create a file: URL.
+ *
+ * @return a URL to the content of the bundle entry that uses the file:
+ * protocol
+ *
+ */
+ public URL getFileURL(URL url);
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java
index 1a37a046c62..3eae16f5104 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java
@@ -14,6 +14,7 @@ package org.eclipse.jetty.osgi.boot.utils;
import java.net.URL;
+import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.osgi.boot.OSGiAppProvider;
/**
@@ -49,6 +50,6 @@ public interface WebappRegistrationCustomizer
* @return array of URLs
* @throws Exception
*/
- URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper fileLocator) throws Exception;
+ URL[] getJarsWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
index 94008f633f5..5a733768fa8 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
@@ -292,7 +292,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
*
* @return a URL to the bundle entry that uses a common protocol
*/
- public static URL getLocalURL(URL url)
+ public URL getLocalURL(URL url)
{
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
{
@@ -328,7 +328,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
* protocol
*
*/
- public static URL getFileURL(URL url)
+ public URL getFileURL(URL url)
{
if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
{
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 9f0ce598089..877c6c37382 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -25,6 +25,7 @@
jetty-osgi-boot-warurljetty-osgi-httpservicejetty-osgi-equinoxtools
+ test-jetty-osgi-webapptest-jetty-osgi
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
new file mode 100644
index 00000000000..0b6cfe088cc
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -0,0 +1,129 @@
+
+
+ org.eclipse.jetty.osgi
+ jetty-osgi-project
+ 7.6.4-SNAPSHOT
+ ../pom.xml
+
+ 4.0.0
+ test-jetty-osgi-webapp
+ Jetty :: OSGi :: WebApp
+ Test Jetty OSGi Webapp bundle
+
+ ${project.groupId}.webapp
+
+
+
+ org.eclipse.jetty
+ jetty-webapp
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi
+
+
+ org.eclipse.osgi
+ org.eclipse.osgi.services
+
+
+
+
+
+
+ src/main/resources
+
+
+
+
+
+
+ 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.testapp;singleton:=true
+ Jetty OSGi Test WebApp
+ 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-webapp/src/main/java/com/acme/osgi/Activator.java b/jetty-osgi/test-jetty-osgi-webapp/src/main/java/com/acme/osgi/Activator.java
new file mode 100644
index 00000000000..b1a95f07843
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi-webapp/src/main/java/com/acme/osgi/Activator.java
@@ -0,0 +1,60 @@
+// ========================================================================
+// 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.eclipse.jetty.webapp.WebAppContext;
+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 webapp
+ *
+ *
+ */
+public class Activator implements BundleActivator
+{
+
+ /**
+ *
+ * @param context
+ */
+ public void start(BundleContext context) throws Exception
+ {
+ WebAppContext webapp = new WebAppContext();
+ Dictionary props = new Hashtable();
+ props.put("war",".");
+ props.put("contextPath","/acme");
+ //uiProps.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, serverName);
+ context.registerService(ContextHandler.class.getName(),webapp,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-webapp/src/main/resources/index.html b/jetty-osgi/test-jetty-osgi-webapp/src/main/resources/index.html
new file mode 100644
index 00000000000..9e62c04bb91
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi-webapp/src/main/resources/index.html
@@ -0,0 +1,6 @@
+
+
+
Test OSGi WebApp
+
Webapp registered by bundle as service successfully deployed.
+
+
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 1e792c14633..ba2d2771f39 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -134,6 +134,15 @@
test
+
+
+ org.eclipse.jetty.osgi
+ test-jetty-osgi-webapp
+ ${project.version}
+ runtime
+
+
+
org.ops4j.pax.exampax-exam
@@ -157,6 +166,12 @@
junittest
+
+ org.eclipse.jetty.toolchain
+ jetty-test-helper
+ test
+
+
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-deployer.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-deployer.xml
new file mode 100644
index 00000000000..ac352765627
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-deployer.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern
+ .*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-selector.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-selector.xml
new file mode 100644
index 00000000000..46ccc85f525
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty-selector.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 300000
+ 2
+ false
+ 8443
+ 20000
+ 5000
+
+
+
+
+
diff --git a/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
new file mode 100644
index 00000000000..30f8ea9d186
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi/src/test/config/etc/jetty.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+ 200
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ 1000
+ false
+ false
+
+
+
+
+
+
+ java.naming.factory.initial
+
+
+
+ java.naming.factory.url.pkgs
+
+
+
+
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java
index 1cd0c65e1f8..f773ef9c6d2 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootCore.java
@@ -121,7 +121,7 @@ public class TestJettyOSGiBootCore
* You will get a list of bundles installed by default
* plus your testcase, wrapped into a bundle called pax-exam-probe
*/
- @Test
+ //@Test
public void testHttpService() throws Exception
{
// ServletContextHandler sch = null;
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
new file mode 100644
index 00000000000..0398a508ecd
--- /dev/null
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
@@ -0,0 +1,166 @@
+// ========================================================================
+// 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;
+
+/**
+ * Pax-Exam to make sure the jetty-osgi-boot can be started along with the httpservice web-bundle.
+ * Then make sure we can deploy an OSGi service on the top of this.
+ */
+@RunWith( JUnit4TestRunner.class )
+public class TestJettyOSGiBootWebAppAsService
+{
+ private static final boolean LOGGING_ENABLED = false;
+ private static final boolean REMOTE_DEBUGGING = false;
+
+ @Inject
+ BundleContext bundleContext = null;
+
+ @Configuration
+ public static Option[] configure()
+ {
+ ArrayList