Bug 510949: Ensure bundle can be scanned even if it is in exploded form.
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Activator.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Activator.java index 7838925..b1b3e57 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Activator.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Activator.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2015 VMware Inc. + * Copyright (c) 2009, 2017 VMware Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -24,18 +24,24 @@ import org.eclipse.gemini.web.core.WebContainerProperties; import org.eclipse.gemini.web.core.spi.ServletContainer; import org.eclipse.gemini.web.tomcat.internal.bundleresources.BundleURLStreamHandlerService; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; +import org.osgi.framework.Filter; import org.osgi.framework.ServiceRegistration; import org.osgi.service.url.URLConstants; import org.osgi.service.url.URLStreamHandlerService; +import org.osgi.util.tracker.ServiceTracker; public class Activator implements BundleActivator { private static final String WAR_PROTOCOL = "war"; + private static final String FILTER = "(&(objectClass=" + URLConverter.class.getName() + + ")(protocol=bundleentry))"; + private static final String EXPRESSION_FACTORY = "javax.el.ExpressionFactory"; private static final String EXPRESSION_FACTORY_IMPL = "org.apache.el.ExpressionFactoryImpl"; @@ -46,6 +52,8 @@ private TomcatServletContainer container; + private ServiceTracker<URLConverter, URLConverter> urlConverterTracker; + private String oldExpressionFactory; @Override @@ -55,6 +63,10 @@ registerURLStreamHandler(context); registerConnectorDescriptors(context); + Filter filter = context.createFilter(FILTER); + this.urlConverterTracker = new ServiceTracker<>(context, filter, null); + this.urlConverterTracker.open(); + TomcatServletContainer container = createContainer(context); container.start(); @@ -98,6 +110,8 @@ if (this.oldExpressionFactory != null) { System.setProperty(EXPRESSION_FACTORY, this.oldExpressionFactory); } + + this.urlConverterTracker.close(); } private TomcatServletContainer createContainer(BundleContext context) throws BundleException { @@ -105,7 +119,7 @@ InputStream configFile = null; try { configFile = resolveConfigFile(context); - return factory.createContainer(configFile, context); + return factory.createContainer(configFile, context, this.urlConverterTracker); } finally { if (configFile != null) { try {
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScanner.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScanner.java index 7cdf636..43c8bfd 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScanner.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScanner.java
@@ -35,9 +35,11 @@ import org.eclipse.gemini.web.tomcat.internal.loader.BundleWebappClassLoader; import org.eclipse.gemini.web.tomcat.internal.support.BundleDependencyDeterminer; import org.eclipse.gemini.web.tomcat.internal.support.BundleFileResolver; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; +import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,13 +66,16 @@ private final BundleFileResolver bundleFileResolver; + private final ServiceTracker<URLConverter, URLConverter> urlConverterTracker; + private JarScanFilter jarScanFilter; BundleDependenciesJarScanner(BundleDependencyDeterminer bundleDependencyDeterminer, BundleFileResolver bundleFileResolver, - BundleContext bundleContext) { + BundleContext bundleContext, ServiceTracker<URLConverter, URLConverter> urlConverterTracker) { this.bundleDependencyDeterminer = bundleDependencyDeterminer; this.bundleFileResolver = bundleFileResolver; this.jarScanFilter = new BundleDependenciesJarScanFilter(bundleContext); + this.urlConverterTracker = urlConverterTracker; } @Override @@ -117,23 +122,27 @@ if (bundleFile != null) { scanBundleFile(bundleFile, callback, isWebapp); } else { - scanJarUrlConnection(bundle, callback, isWebapp); + URL root = bundle.getEntry("/"); + try { + URLConverter converter = this.urlConverterTracker.getService(); + if (converter != null) { + root = converter.resolve(root); + } + if ("file".equals(root.getProtocol())) { + scanBundleFile(new File(root.getPath()), callback, isWebapp); + } else if ("jar".equals(root.getProtocol())) { + scanBundleUrl(root, callback, isWebapp); + } else { + URL bundleUrl = new URL(JAR_URL_PREFIX + root.toExternalForm() + JAR_URL_SUFFIX); + scanBundleUrl(bundleUrl, callback, isWebapp); + } + } catch (IOException e) { + LOGGER.warn("Failed to scan the bundle location [" + root + "]."); + return; + } } } - private void scanJarUrlConnection(Bundle bundle, JarScannerCallback callback, boolean isWebapp) { - URL bundleUrl; - URL root = bundle.getEntry("/"); - try { - bundleUrl = new URL(JAR_URL_PREFIX + root.toExternalForm() + JAR_URL_SUFFIX); - } catch (MalformedURLException e) { - LOGGER.warn("Failed to create jar: url for bundle location [" + root + "]."); - return; - } - - scanBundleUrl(bundleUrl, callback, isWebapp); - } - private void scanBundleFile(File bundleFile, JarScannerCallback callback, boolean isWebapp) { if (bundleFile.isDirectory()) { try {
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcat.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcat.java index f1c69b8..db5081a 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcat.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcat.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2016 VMware Inc. + * Copyright (c) 2009, 2017 VMware Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -56,10 +56,12 @@ import org.eclipse.gemini.web.tomcat.internal.loader.ChainedClassLoader; import org.eclipse.gemini.web.tomcat.internal.support.BundleFileResolverFactory; import org.eclipse.gemini.web.tomcat.internal.support.PackageAdminBundleDependencyDeterminer; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; +import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -119,10 +121,11 @@ private String hostConfigDir; - OsgiAwareEmbeddedTomcat(BundleContext context) { + OsgiAwareEmbeddedTomcat(BundleContext context, + ServiceTracker<URLConverter, URLConverter> urlConverterTracker) { this.bundleContext = context; this.bundleDependenciesJarScanner = new BundleDependenciesJarScanner(new PackageAdminBundleDependencyDeterminer(), - BundleFileResolverFactory.createBundleFileResolver(), context); + BundleFileResolverFactory.createBundleFileResolver(), context, urlConverterTracker); this.defaultJarScanner = new StandardJarScanner(); this.jarScannerCustomizer = new DelegatingJarScannerCustomizer(context); }
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactory.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactory.java index 531fc69..c3eba2e 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactory.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactory.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2012 VMware Inc. + * Copyright (c) 2009, 2017 VMware Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -18,12 +18,15 @@ import java.io.InputStream; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.osgi.framework.BundleContext; +import org.osgi.util.tracker.ServiceTracker; final class TomcatServletContainerFactory { - public TomcatServletContainer createContainer(InputStream configuration, BundleContext context) { - OsgiAwareEmbeddedTomcat catalina = new OsgiAwareEmbeddedTomcat(context); + public TomcatServletContainer createContainer(InputStream configuration, BundleContext context, + ServiceTracker<URLConverter, URLConverter> urlConverterTracker) { + OsgiAwareEmbeddedTomcat catalina = new OsgiAwareEmbeddedTomcat(context, urlConverterTracker); catalina.configure(configuration); return new TomcatServletContainer(catalina, context);
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/support/EquinoxBundleFileResolver.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/support/EquinoxBundleFileResolver.java index 2911ab5..0996d8e 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/support/EquinoxBundleFileResolver.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/support/EquinoxBundleFileResolver.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2015 VMware Inc. + * Copyright (c) 2009, 2017 VMware Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -59,7 +59,7 @@ try { EquinoxBundleFileResolver.class.getClassLoader().loadClass(EquinoxBundle.class.getName()); return true; - } catch (Exception | LinkageError _) { + } catch (Exception | LinkageError e) { return false; } }
diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScannerTests.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScannerTests.java index 9344832..376298c 100644 --- a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScannerTests.java +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/BundleDependenciesJarScannerTests.java
@@ -41,10 +41,13 @@ import org.eclipse.gemini.web.tomcat.internal.support.BundleDependencyDeterminer; import org.eclipse.gemini.web.tomcat.internal.support.BundleFileResolver; import org.eclipse.gemini.web.tomcat.spi.ClassLoaderCustomizer; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.eclipse.virgo.test.stubs.framework.StubBundle; import org.eclipse.virgo.test.stubs.framework.StubBundleContext; +import org.eclipse.virgo.test.stubs.framework.StubFilter; import org.junit.Test; import org.osgi.framework.Bundle; +import org.osgi.util.tracker.ServiceTracker; public class BundleDependenciesJarScannerTests { @@ -54,8 +57,11 @@ private final StubBundleContext bundleContext = new StubBundleContext(); + private ServiceTracker<URLConverter, URLConverter> converter = + new ServiceTracker<>(this.bundleContext, createMock(StubFilter.class), null); + private final BundleDependenciesJarScanner scanner = new BundleDependenciesJarScanner(this.dependencyDeterminer, this.bundleFileResolver, - this.bundleContext); + this.bundleContext, this.converter); private final Bundle bundle = new StubBundle();
diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcatTests.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcatTests.java index 6309216..5d4406f 100755 --- a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcatTests.java +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/OsgiAwareEmbeddedTomcatTests.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 SAP AG + * Copyright (c) 2011, 2017 SAP AG * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -29,6 +29,7 @@ import javax.naming.spi.ObjectFactoryBuilder; import org.apache.catalina.LifecycleException; +import org.eclipse.osgi.service.urlconversion.URLConverter; import org.eclipse.virgo.test.stubs.framework.StubBundleContext; import org.eclipse.virgo.test.stubs.framework.StubFilter; import org.eclipse.virgo.test.stubs.framework.StubServiceRegistration; @@ -36,6 +37,7 @@ import org.junit.Before; import org.junit.Test; import org.osgi.framework.Constants; +import org.osgi.util.tracker.ServiceTracker; public class OsgiAwareEmbeddedTomcatTests { @@ -43,11 +45,14 @@ private StubFilter filter; + private ServiceTracker<URLConverter, URLConverter> converter; + @Before public void setUp() { this.bundleContext = new StubBundleContext(); this.filter = createMock(StubFilter.class); this.bundleContext.addFilter("(objectClass=org.eclipse.gemini.web.tomcat.spi.JarScannerCustomizer)", this.filter); + this.converter = new ServiceTracker<>(this.bundleContext, createMock(StubFilter.class), null); } @After @@ -116,7 +121,7 @@ } private OsgiAwareEmbeddedTomcat createTomcat() { - return new OsgiAwareEmbeddedTomcat(this.bundleContext); + return new OsgiAwareEmbeddedTomcat(this.bundleContext, this.converter); } private void initTomcat() {
diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactoryTests.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactoryTests.java index 78bb80c..1548074 100644 --- a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactoryTests.java +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerFactoryTests.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2015 VMware Inc. + * Copyright (c) 2009, 2017 VMware Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -26,17 +26,23 @@ import java.nio.file.Paths; import org.eclipse.gemini.web.core.spi.ServletContainerException; +import org.eclipse.osgi.service.urlconversion.URLConverter; +import org.eclipse.virgo.test.stubs.framework.StubFilter; import org.junit.Before; import org.junit.Test; import org.osgi.framework.BundleContext; +import org.osgi.util.tracker.ServiceTracker; public class TomcatServletContainerFactoryTests { private BundleContext bundleContext; + private ServiceTracker<URLConverter, URLConverter> converter; + @Before public void setUp() throws Exception { this.bundleContext = createMock(BundleContext.class); + this.converter = new ServiceTracker<>(this.bundleContext, createMock(StubFilter.class), null); expect(this.bundleContext.getProperty(TomcatConfigLocator.CONFIG_PATH_FRAMEWORK_PROPERTY)).andReturn(null); expect(this.bundleContext.getProperty(OsgiAwareEmbeddedTomcat.USE_NAMING)).andReturn(null); expect(this.bundleContext.getProperty(BundleDependenciesJarScanFilter.SCANNER_SKIP_BUNDLES_PROPERTY_NAME)).andReturn(null); @@ -49,7 +55,8 @@ public void testCreateContainerWithConfigFile() throws Exception { TomcatServletContainerFactory factory = new TomcatServletContainerFactory(); replay(this.bundleContext); - TomcatServletContainer container = factory.createContainer(Files.newInputStream(Paths.get("src/test/resources/server.xml")), this.bundleContext); + TomcatServletContainer container = factory.createContainer( + Files.newInputStream(Paths.get("src/test/resources/server.xml")), this.bundleContext, this.converter); assertNotNull(container); verify(this.bundleContext); } @@ -58,7 +65,8 @@ public void testCreateContainerWithInvalidConfigFile() throws Exception { TomcatServletContainerFactory factory = new TomcatServletContainerFactory(); replay(this.bundleContext); - TomcatServletContainer container = factory.createContainer(Files.newInputStream(Paths.get("src/test/resources/invalid-server.xml")), this.bundleContext); + TomcatServletContainer container = factory.createContainer( + Files.newInputStream(Paths.get("src/test/resources/invalid-server.xml")), this.bundleContext, this.converter); assertNotNull(container); verify(this.bundleContext); }
diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerTests.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerTests.java index 07e9b5e..4eacede 100644 --- a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerTests.java +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatServletContainerTests.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2015 SAP SE + * Copyright (c) 2012, 2017 SAP SE * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -37,12 +37,15 @@ import org.eclipse.gemini.web.core.spi.ServletContainerException; import org.eclipse.gemini.web.core.spi.WebApplicationHandle; import org.eclipse.gemini.web.tomcat.internal.loader.BundleWebappLoader; +import org.eclipse.osgi.service.urlconversion.URLConverter; +import org.eclipse.virgo.test.stubs.framework.StubFilter; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Filter; +import org.osgi.util.tracker.ServiceTracker; public class TomcatServletContainerTests { @@ -72,6 +75,8 @@ private WebApplicationHandle webApplicationHandle; + private ServiceTracker<URLConverter, URLConverter> converter; + @Before public void setUp() throws Exception { this.bundleContext = createMock(BundleContext.class); @@ -83,6 +88,7 @@ this.host = createMock(Host.class); this.servletContext = createMock(ServletContext.class); this.webApplicationHandle = createMock(WebApplicationHandle.class); + this.converter = new ServiceTracker<>(this.bundleContext, createMock(StubFilter.class), null); expect(this.bundleContext.createFilter(FILTER_1)).andReturn(this.filter); expect(this.bundleContext.createFilter(FILTER_2)).andReturn(this.filter); @@ -195,7 +201,7 @@ private TomcatServletContainer createTomcatServletContainer() { replay(this.bundleContext, this.bundle, this.filter, this.server, this.service, this.engine, this.host, this.servletContext, this.webApplicationHandle); - OsgiAwareEmbeddedTomcat osgiAwareEmbeddedTomcat = new OsgiAwareEmbeddedTomcat(this.bundleContext); + OsgiAwareEmbeddedTomcat osgiAwareEmbeddedTomcat = new OsgiAwareEmbeddedTomcat(this.bundleContext, this.converter); osgiAwareEmbeddedTomcat.setServer(this.server); return new TomcatServletContainer(osgiAwareEmbeddedTomcat, this.bundleContext); }