Merge pull request #3777 from eclipse/jetty-9.4.x-3700-felix-webapp-testing
Issue #3700 - Adding felix webapp to test-distribution to help catch URLStreamHandler classloader issues earlier
This commit is contained in:
commit
b9fc1f7362
|
@ -169,7 +169,7 @@ public class IncludeExcludeSet<T,P> implements Predicate<P>
|
|||
/**
|
||||
* Test Included and not Excluded
|
||||
* @param item The item to test
|
||||
* @return Boolean.TRUE if item is included, Boolean.FALSE if item is excluded and null if neither
|
||||
* @return Boolean.TRUE if item is included, Boolean.FALSE if item is excluded or null if neither
|
||||
*/
|
||||
public Boolean isIncludedAndNotExcluded(P item)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
/**
|
||||
* Equivalent of ...
|
||||
*
|
||||
* <pre>
|
||||
* Module module = clazz.getModule();
|
||||
* if (module != null)
|
||||
* {
|
||||
* Configuration configuration = module.getLayer().configuration();
|
||||
* Optional<ResolvedModule> resolvedModule = configuration.findModule(module.getName());
|
||||
* if (resolvedModule.isPresent())
|
||||
* {
|
||||
* ModuleReference moduleReference = resolvedModule.get().reference();
|
||||
* Optional<URI> location = moduleReference.location();
|
||||
* if (location.isPresent())
|
||||
* {
|
||||
* return location.get();
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* return null;
|
||||
* </pre>
|
||||
*
|
||||
* In Jetty 10, this entire class can be moved to direct calls to java.lang.Module in TypeUtil.getModuleLocation()
|
||||
*/
|
||||
class ModuleLocation
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ModuleLocation.class);
|
||||
|
||||
private final Class<?> classModule;
|
||||
private final MethodHandle handleGetModule;
|
||||
private final MethodHandle handleGetLayer;
|
||||
private final MethodHandle handleConfiguration;
|
||||
private final MethodHandle handleGetName;
|
||||
private final MethodHandle handleOptionalResolvedModule;
|
||||
private final MethodHandle handleReference;
|
||||
private final MethodHandle handleLocation;
|
||||
|
||||
public ModuleLocation()
|
||||
{
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
try
|
||||
{
|
||||
classModule = loader.loadClass("java.lang.Module");
|
||||
handleGetModule = lookup.findVirtual(Class.class, "getModule", methodType(classModule));
|
||||
|
||||
Class<?> classLayer = loader.loadClass("java.lang.ModuleLayer");
|
||||
handleGetLayer = lookup.findVirtual(classModule, "getLayer", methodType(classLayer));
|
||||
|
||||
Class<?> classConfiguration = loader.loadClass("java.lang.module.Configuration");
|
||||
handleConfiguration = lookup.findVirtual(classLayer, "configuration", methodType(classConfiguration));
|
||||
|
||||
handleGetName = lookup.findVirtual(classModule, "getName", methodType(String.class));
|
||||
|
||||
Method findModuleMethod = classConfiguration.getMethod("findModule", new Class<?>[]{String.class});
|
||||
handleOptionalResolvedModule = lookup.findVirtual(classConfiguration, "findModule", methodType(findModuleMethod.getReturnType(), String.class));
|
||||
|
||||
Class<?> classResolvedModule = loader.loadClass("java.lang.module.ResolvedModule");
|
||||
Class<?> classReference = loader.loadClass("java.lang.module.ModuleReference");
|
||||
handleReference = lookup.findVirtual(classResolvedModule, "reference", methodType(classReference));
|
||||
|
||||
Method locationMethod = classReference.getMethod("location");
|
||||
handleLocation = lookup.findVirtual(classReference, "location", methodType(locationMethod.getReturnType()));
|
||||
}
|
||||
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported on this runtime", e);
|
||||
}
|
||||
}
|
||||
|
||||
public URI getModuleLocation(Class<?> clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Module module = clazz.getModule();
|
||||
Object module = handleGetModule.invoke(clazz);
|
||||
if (module == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// ModuleLayer layer = module.getLayer();
|
||||
Object layer = handleGetLayer.invoke(module);
|
||||
if (layer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Configuration configuration = layer.configuration();
|
||||
Object configuration = handleConfiguration.invoke(layer);
|
||||
if (configuration == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// String moduleName = module.getName();
|
||||
String moduleName = (String)handleGetName.invoke(module);
|
||||
if (moduleName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Optional<ResolvedModule> optionalResolvedModule = configuration.findModule(moduleName);
|
||||
Optional<?> optionalResolvedModule = (Optional<?>)handleOptionalResolvedModule.invoke(configuration, moduleName);
|
||||
if (!optionalResolvedModule.isPresent())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// ResolveModule resolved = optionalResolvedModule.get();
|
||||
Object resolved = optionalResolvedModule.get();
|
||||
|
||||
// ModuleReference moduleReference = resolved.reference();
|
||||
Object moduleReference = handleReference.invoke(resolved);
|
||||
|
||||
// Optional<URI> location = moduleReference.location();
|
||||
Optional<URI> location = (Optional<URI>)handleLocation.invoke(moduleReference);
|
||||
if (location != null || location.isPresent())
|
||||
{
|
||||
return location.get();
|
||||
}
|
||||
}
|
||||
catch (Throwable ignored)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.ignore(ignored);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -19,14 +19,20 @@
|
|||
package org.eclipse.jetty.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -36,6 +42,8 @@ import java.util.Map;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -171,6 +179,40 @@ public class TypeUtil
|
|||
}
|
||||
}
|
||||
|
||||
private static final MethodHandle[] LOCATION_METHODS;
|
||||
private static final ModuleLocation MODULE_LOCATION;
|
||||
|
||||
static
|
||||
{
|
||||
List<MethodHandle> locationMethods = new ArrayList<>();
|
||||
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MethodType type = methodType(URI.class, Class.class);
|
||||
|
||||
try
|
||||
{
|
||||
locationMethods.add(lookup.findStatic(TypeUtil.class, "getCodeSourceLocation", type));
|
||||
ModuleLocation moduleLocation = null;
|
||||
try
|
||||
{
|
||||
moduleLocation = new ModuleLocation();
|
||||
locationMethods.add(lookup.findStatic(TypeUtil.class, "getModuleLocation", type));
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
LOG.info("JVM Runtime does not support Modules");
|
||||
}
|
||||
MODULE_LOCATION = moduleLocation;
|
||||
locationMethods.add(lookup.findStatic(TypeUtil.class, "getClassLoaderLocation", type));
|
||||
locationMethods.add(lookup.findStatic(TypeUtil.class, "getSystemClassLoaderLocation", type));
|
||||
LOCATION_METHODS = locationMethods.toArray(new MethodHandle[0]);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Unable to establish Location Lookup Handles", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Array to List.
|
||||
* <p>
|
||||
|
@ -583,34 +625,115 @@ public class TypeUtil
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* Attempt to find the Location of a loaded Class.
|
||||
* <p>
|
||||
* This can be null for primitives, void, and in-memory classes.
|
||||
* </p>
|
||||
* @param clazz the loaded class to find a location for.
|
||||
* @return the location as a URI (this is a URI pointing to a holder of the class: a directory,
|
||||
* a jar file, a {@code jrt://} resource, etc), or null of no location available.
|
||||
*/
|
||||
public static URI getLocationOfClass(Class<?> clazz)
|
||||
{
|
||||
URI location;
|
||||
|
||||
for (MethodHandle locationMethod : LOCATION_METHODS)
|
||||
{
|
||||
try
|
||||
{
|
||||
location = (URI)locationMethod.invoke(clazz);
|
||||
if (location != null)
|
||||
{
|
||||
return location;
|
||||
}
|
||||
}
|
||||
catch (Throwable cause)
|
||||
{
|
||||
cause.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static URI getClassLoaderLocation(Class<?> clazz)
|
||||
{
|
||||
return getClassLoaderLocation(clazz, clazz.getClassLoader());
|
||||
}
|
||||
|
||||
public static URI getSystemClassLoaderLocation(Class<?> clazz)
|
||||
{
|
||||
return getClassLoaderLocation(clazz, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
public static URI getClassLoaderLocation(Class<?> clazz, ClassLoader loader)
|
||||
{
|
||||
if (loader == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
String resourceName = TypeUtil.toClassReference(clazz);
|
||||
if (loader != null)
|
||||
{
|
||||
URL url = loader.getResource(resourceName);
|
||||
if (url != null)
|
||||
{
|
||||
URI uri = url.toURI();
|
||||
String uriStr = uri.toASCIIString();
|
||||
if(uriStr.startsWith("jar:file:"))
|
||||
{
|
||||
uriStr = uriStr.substring(4);
|
||||
int idx = uriStr.indexOf("!/");
|
||||
if (idx > 0)
|
||||
{
|
||||
return URI.create(uriStr.substring(0, idx));
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ignore)
|
||||
{
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static URI getCodeSourceLocation(Class<?> clazz)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProtectionDomain domain = clazz.getProtectionDomain();
|
||||
ProtectionDomain domain = AccessController.doPrivileged((PrivilegedAction<ProtectionDomain>)() -> clazz.getProtectionDomain());
|
||||
if (domain != null)
|
||||
{
|
||||
CodeSource source = domain.getCodeSource();
|
||||
if (source != null)
|
||||
{
|
||||
URL location = source.getLocation();
|
||||
|
||||
|
||||
if (location != null)
|
||||
{
|
||||
return location.toURI();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String resourceName = TypeUtil.toClassReference(clazz);
|
||||
ClassLoader loader = clazz.getClassLoader();
|
||||
URL url = (loader == null ? ClassLoader.getSystemClassLoader() : loader).getResource(resourceName);
|
||||
if (url != null)
|
||||
{
|
||||
return URIUtil.getJarSource(url.toURI());
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
catch (URISyntaxException ignore)
|
||||
{
|
||||
LOG.debug(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static URI getModuleLocation(Class<?> clazz)
|
||||
{
|
||||
// In Jetty 10, this method can be implemented directly, without reflection
|
||||
if (MODULE_LOCATION != null)
|
||||
{
|
||||
return MODULE_LOCATION.getModuleLocation(clazz);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.EnabledOnJre;
|
||||
|
@ -104,7 +102,7 @@ public class TypeUtilTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsTrue() throws Exception
|
||||
public void testIsTrue()
|
||||
{
|
||||
assertTrue(TypeUtil.isTrue(Boolean.TRUE));
|
||||
assertTrue(TypeUtil.isTrue(true));
|
||||
|
@ -119,7 +117,7 @@ public class TypeUtilTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsFalse() throws Exception
|
||||
public void testIsFalse()
|
||||
{
|
||||
assertTrue(TypeUtil.isFalse(Boolean.FALSE));
|
||||
assertTrue(TypeUtil.isFalse(false));
|
||||
|
@ -134,17 +132,21 @@ public class TypeUtilTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetLocationOfClass() throws Exception
|
||||
public void testGetLocationOfClass_FromMavenRepo()
|
||||
{
|
||||
String mavenRepoPathProperty = System.getProperty( "mavenRepoPath");
|
||||
String mavenRepoPathProperty = System.getProperty("mavenRepoPath");
|
||||
assumeTrue(mavenRepoPathProperty != null);
|
||||
Path mavenRepoPath = Paths.get( mavenRepoPathProperty );
|
||||
Path mavenRepoPath = Paths.get(mavenRepoPathProperty);
|
||||
|
||||
String mavenRepo = mavenRepoPath.toFile().getPath().replaceAll("\\\\", "/");
|
||||
|
||||
// Classes from maven dependencies
|
||||
assertThat(TypeUtil.getLocationOfClass(Assertions.class).toASCIIString(),containsString(mavenRepo));
|
||||
|
||||
assertThat(TypeUtil.getLocationOfClass(org.junit.jupiter.api.Assertions.class).toASCIIString(), containsString(mavenRepo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLocationOfClass_ClassDirectory()
|
||||
{
|
||||
// Class from project dependencies
|
||||
assertThat(TypeUtil.getLocationOfClass(TypeUtil.class).toASCIIString(),containsString("/classes/"));
|
||||
}
|
||||
|
@ -154,10 +156,19 @@ public class TypeUtilTest
|
|||
public void testGetLocation_JvmCore_JPMS()
|
||||
{
|
||||
// Class from JVM core
|
||||
String expectedJavaBase = "/java.base/";
|
||||
String expectedJavaBase = "/java.base";
|
||||
assertThat(TypeUtil.getLocationOfClass(String.class).toASCIIString(),containsString(expectedJavaBase));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
public void testGetLocation_JavaLangThreadDeath_JPMS()
|
||||
{
|
||||
// Class from JVM core
|
||||
String expectedJavaBase = "/java.base";
|
||||
assertThat(TypeUtil.getLocationOfClass(java.lang.ThreadDeath.class).toASCIIString(),containsString(expectedJavaBase));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledOnJre(JRE.JAVA_8)
|
||||
public void testGetLocation_JvmCore_Java8RT()
|
||||
|
@ -166,4 +177,13 @@ public class TypeUtilTest
|
|||
String expectedJavaBase = "/rt.jar";
|
||||
assertThat(TypeUtil.getLocationOfClass(String.class).toASCIIString(),containsString(expectedJavaBase));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledOnJre(JRE.JAVA_8)
|
||||
public void testGetLocation_JavaLangThreadDeath_Java8RT()
|
||||
{
|
||||
// Class from JVM core
|
||||
String expectedJavaBase = "/rt.jar";
|
||||
assertThat(TypeUtil.getLocationOfClass(java.lang.ThreadDeath.class).toASCIIString(),containsString(expectedJavaBase));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,28 +18,27 @@
|
|||
|
||||
package org.eclipse.jetty.util.resource;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
|
||||
public class JrtResourceTest
|
||||
{
|
||||
private String testResURI = MavenTestingUtils.getTestResourcesDir().getAbsoluteFile().toURI().toASCIIString();
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
@Disabled("Not supported on Java 9+ Module API")
|
||||
public void testResourceFromUriForString()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -57,6 +56,7 @@ public class JrtResourceTest
|
|||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
@Disabled("Not supported on Java 9+ Module API")
|
||||
public void testResourceFromStringForString()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -73,6 +73,7 @@ public class JrtResourceTest
|
|||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
@Disabled("Not supported on Java 9+ Module API")
|
||||
public void testResourceFromURLForString()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -111,7 +112,4 @@ public class JrtResourceTest
|
|||
assertThat(resource.isDirectory(), is(false));
|
||||
assertThat(resource.length(),is(-1L));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -353,6 +353,8 @@ public class ClasspathPattern extends AbstractSet<String>
|
|||
@Override
|
||||
public boolean test(URI uri)
|
||||
{
|
||||
if ((uri == null) || (!uri.isAbsolute()))
|
||||
return false;
|
||||
if (!uri.getScheme().equals("file"))
|
||||
return false;
|
||||
Path path = Paths.get(uri);
|
||||
|
@ -390,6 +392,8 @@ public class ClasspathPattern extends AbstractSet<String>
|
|||
@Override
|
||||
public boolean test(URI uri)
|
||||
{
|
||||
if ((uri == null) || (!uri.isAbsolute()))
|
||||
return false;
|
||||
if (!uri.getScheme().equalsIgnoreCase("jrt"))
|
||||
return false;
|
||||
String module = uri.getPath();
|
||||
|
@ -443,6 +447,8 @@ public class ClasspathPattern extends AbstractSet<String>
|
|||
@Override
|
||||
public boolean test(URI name)
|
||||
{
|
||||
if ((name == null) || (!name.isAbsolute()))
|
||||
return false;
|
||||
return _byLocation.test(name) || _byModule.test(name);
|
||||
}
|
||||
|
||||
|
@ -726,13 +732,18 @@ public class ClasspathPattern extends AbstractSet<String>
|
|||
if (Boolean.FALSE==byName)
|
||||
return false;
|
||||
|
||||
Boolean byLocation = locations.isIncludedAndNotExcluded(location.get());
|
||||
if (Boolean.FALSE==byLocation)
|
||||
return false;
|
||||
URI uri = location.get();
|
||||
if (uri != null)
|
||||
{
|
||||
Boolean byLocation = locations.isIncludedAndNotExcluded(uri);
|
||||
if (Boolean.FALSE == byLocation)
|
||||
return false;
|
||||
|
||||
return Boolean.TRUE.equals(byName)
|
||||
|| Boolean.TRUE.equals(byLocation)
|
||||
|| !(names.hasIncludes() || locations.hasIncludes());
|
||||
return Boolean.TRUE.equals(byName)
|
||||
|| Boolean.TRUE.equals(byLocation)
|
||||
|| !(names.hasIncludes() || locations.hasIncludes());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,12 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.webapp;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
@ -34,6 +29,10 @@ import org.junit.jupiter.api.condition.DisabledOnJre;
|
|||
import org.junit.jupiter.api.condition.EnabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ClasspathPatternTest
|
||||
{
|
||||
private final ClasspathPattern _pattern = new ClasspathPattern();
|
||||
|
@ -122,15 +121,12 @@ public class ClasspathPatternTest
|
|||
{
|
||||
// jar from JVM classloader
|
||||
URI loc_string = TypeUtil.getLocationOfClass(String.class);
|
||||
// System.err.println(loc_string);
|
||||
|
||||
// a jar from maven repo jar
|
||||
URI loc_junit = TypeUtil.getLocationOfClass(Test.class);
|
||||
// System.err.println(loc_junit);
|
||||
|
||||
// class file
|
||||
URI loc_test = TypeUtil.getLocationOfClass(ClasspathPatternTest.class);
|
||||
// System.err.println(loc_test);
|
||||
|
||||
ClasspathPattern pattern = new ClasspathPattern();
|
||||
pattern.include("something");
|
||||
|
@ -139,7 +135,7 @@ public class ClasspathPatternTest
|
|||
assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(false));
|
||||
|
||||
// Add directory for both JVM classes
|
||||
pattern.include(Paths.get(loc_string).getParent().toUri().toString());
|
||||
pattern.include(loc_string.toASCIIString());
|
||||
|
||||
// Add jar for individual class and classes directory
|
||||
pattern.include(loc_junit.toString(), loc_test.toString());
|
||||
|
@ -220,7 +216,7 @@ public class ClasspathPatternTest
|
|||
assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true));
|
||||
|
||||
// Add directory for both JVM classes
|
||||
pattern.exclude(Paths.get(loc_string).getParent().toUri().toString());
|
||||
pattern.exclude(loc_string.toString());
|
||||
|
||||
// Add jar for individual class and classes directory
|
||||
pattern.exclude(loc_junit.toString(), loc_test.toString());
|
||||
|
|
|
@ -92,6 +92,13 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-felix-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.tests.distribution;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class OsgiAppTests extends AbstractDistributionTest
|
||||
{
|
||||
@Test
|
||||
public void testFelixWebappStart() throws Exception
|
||||
{
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
DistributionTester distribution = DistributionTester.Builder.newInstance()
|
||||
.jettyVersion(jettyVersion)
|
||||
.mavenLocalRepository(System.getProperty("mavenRepoPath"))
|
||||
.build();
|
||||
|
||||
String[] args1 = {
|
||||
"--create-startd",
|
||||
"--approve-all-licenses",
|
||||
"--add-to-start=http,deploy,annotations,plus,resources"
|
||||
};
|
||||
try (DistributionTester.Run run1 = distribution.start(args1))
|
||||
{
|
||||
assertTrue(run1.awaitFor(5, TimeUnit.SECONDS));
|
||||
assertEquals(0, run1.getExitValue());
|
||||
|
||||
File war = distribution.resolveArtifact("org.eclipse.jetty.tests:test-felix-webapp:war:" + jettyVersion);
|
||||
distribution.installWarFile(war, "test");
|
||||
|
||||
int port = distribution.freePort();
|
||||
try (DistributionTester.Run run2 = distribution.start("jetty.http.port=" + port))
|
||||
{
|
||||
assertTrue(run2.awaitConsoleLogsFor("Started @", 10, TimeUnit.SECONDS));
|
||||
|
||||
startHttpClient();
|
||||
ContentResponse response = client.GET("http://localhost:" + port + "/test/info");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
assertThat(response.getContentAsString(), containsString("Framework: org.apache.felix.framework"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@
|
|||
<module>test-jndi-webapp</module>
|
||||
<module>test-http2-webapp</module>
|
||||
<module>test-simple-webapp</module>
|
||||
<module>test-felix-webapp</module>
|
||||
<module>test-cdi2-webapp</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-webapps-parent</artifactId>
|
||||
<version>9.4.20-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>test-felix-webapp</artifactId>
|
||||
<name>Test :: Jetty Felix Webapp</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.felix</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>org.apache.felix.framework</artifactId>
|
||||
<version>6.0.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,82 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
|
||||
import org.osgi.framework.Constants;
|
||||
import org.osgi.framework.launch.Framework;
|
||||
import org.osgi.framework.launch.FrameworkFactory;
|
||||
|
||||
@WebListener
|
||||
public class AppListener implements ServletContextListener
|
||||
{
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
Framework framework = initFelix();
|
||||
sce.getServletContext().setAttribute(Framework.class.getName(), framework);
|
||||
}
|
||||
|
||||
private Framework initFelix()
|
||||
{
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
|
||||
try
|
||||
{
|
||||
Path cacheDir = Files.createTempDirectory("felix-cache");
|
||||
properties.put(Constants.FRAMEWORK_STORAGE, cacheDir.toAbsolutePath().toString());
|
||||
properties.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
|
||||
properties.put(Constants.FRAMEWORK_BUNDLE_PARENT, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK);
|
||||
properties.put(Constants.FRAMEWORK_BOOTDELEGATION, "*");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException("Unable to configure Felix", e);
|
||||
}
|
||||
|
||||
Framework framework = ServiceLoader.load(FrameworkFactory.class).iterator().next().newFramework(properties);
|
||||
|
||||
try
|
||||
{
|
||||
System.err.println("Initializing felix");
|
||||
framework.init();
|
||||
System.err.println("Starting felix");
|
||||
framework.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
throw new RuntimeException("Unable to start Felix", e);
|
||||
}
|
||||
|
||||
return framework;
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.demo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.launch.Framework;
|
||||
|
||||
@WebServlet("/info")
|
||||
public class InfoServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.setContentType("text/plain");
|
||||
resp.setCharacterEncoding("utf-8");
|
||||
|
||||
PrintWriter out = resp.getWriter();
|
||||
Framework framework = (Framework)getServletContext().getAttribute(Framework.class.getName());
|
||||
out.printf("Framework: %s\n", framework);
|
||||
BundleContext bundleContext = framework.getBundleContext();
|
||||
out.printf("BundleContext: %s\n", bundleContext);
|
||||
Bundle bundleSelf = bundleContext.getBundle();
|
||||
out.printf("BundleContext.bundle: %s\n", bundleSelf);
|
||||
for (Bundle bundle : bundleContext.getBundles())
|
||||
{
|
||||
out.printf("bundle[]: %s\n", bundle);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue