From 1d1ba56c886da4590c1d952ca037e5c9b1cd0e5c Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 22 Aug 2017 17:02:17 +1000 Subject: [PATCH] Issue #1499 ClasspathPattern module support Added simple but inefficient implementation for jrt matching --- .../jetty/webapp/ClasspathPattern.java | 78 +++++++++++----- .../jetty/webapp/ClasspathPatternTest.java | 93 +++++++++++++++++++ 2 files changed, 147 insertions(+), 24 deletions(-) diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java index 5c089b1a331..1ccc7fd35b3 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/ClasspathPattern.java @@ -79,7 +79,8 @@ public class ClasspathPattern extends AbstractSet _pattern=pattern; _inclusive = !pattern.startsWith("-"); _name = _inclusive ? pattern : pattern.substring(1).trim(); - _type = _name.startsWith("file:")?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME); + boolean is_location = _name.startsWith("file:") || _name.startsWith("jrt:"); + _type = is_location?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME); } Entry(String name, boolean include) @@ -87,7 +88,8 @@ public class ClasspathPattern extends AbstractSet _pattern=include?name:("-"+name); _inclusive = include; _name = name; - _type = _name.startsWith("file:")?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME); + boolean is_location = _name.startsWith("file:") || _name.startsWith("jrt:"); + _type = is_location?Type.LOCATION:(_name.endsWith(".")?Type.PACKAGE:Type.CLASSNAME); } @@ -308,36 +310,65 @@ public class ClasspathPattern extends AbstractSet } @SuppressWarnings("serial") - public static class ByLocation extends HashSet implements Predicate + public static class ByLocation extends HashSet implements Predicate { @Override - public boolean test(Path path) + public boolean test(URI uri) { - for (File file: this) + // TODO this is very inefficient with object creation + + switch(uri.getScheme()) { - if (file.isDirectory()) + case "file": { - if (path.startsWith(file.toPath())) + Path path = Paths.get(uri); + for (URI u: this) { - return true; - } - } - else - { - if (path.equals(file.toPath())) - { - return true; + if (u.getScheme().equals("file")) + { + File file = new File(u); + if (file.isDirectory()) + { + if (path.startsWith(file.toPath())) + { + return true; + } + } else + { + if (path.equals(file.toPath())) + { + return true; + } + } + } } + return false; } + + case "jrt": + { + String module = uri.getPath().split("/")[1]; + for (URI u: this) + { + if (u.getScheme().equals("jrt")) + { + String m = u.toString().split("/")[1]; + if (module.equals(m)) + return true; + } + } + return false; + } + + default: + throw new IllegalStateException("unknown URI scheme: "+uri); } - - return false; } } Map _entries = new HashMap<>(); IncludeExcludeSet _patterns = new IncludeExcludeSet<>(ByPackageOrName.class); - IncludeExcludeSet _locations = new IncludeExcludeSet<>(ByLocation.class); + IncludeExcludeSet _locations = new IncludeExcludeSet<>(ByLocation.class); public ClasspathPattern() { @@ -412,11 +443,11 @@ public class ClasspathPattern extends AbstractSet { try { - File file = Resource.newResource(entry.getName()).getFile().getAbsoluteFile().getCanonicalFile(); + URI uri = Resource.newResource(entry.getName()).getURI(); if (entry.isInclusive()) - _locations.include(file); + _locations.include(uri); else - _locations.exclude(file); + _locations.exclude(uri); } catch (Exception e) { @@ -526,7 +557,7 @@ public class ClasspathPattern extends AbstractSet return byName; // Already excluded so no need to check location. URI location = TypeUtil.getLocationOfClass(clazz); Boolean byLocation = location == null ? null - : _locations.isIncludedAndNotExcluded(Paths.get(location)); + : _locations.isIncludedAndNotExcluded(location); if (LOG.isDebugEnabled()) LOG.debug("match {} from {} byName={} byLocation={} in {}",clazz,location,byName,byLocation,this); @@ -564,8 +595,7 @@ public class ClasspathPattern extends AbstractSet URI jarUri = URIUtil.getJarSource(url.toURI()); if ("file".equalsIgnoreCase(jarUri.getScheme())) { - File file = new File(jarUri); - byLocation = _locations.isIncludedAndNotExcluded(file.toPath()); + byLocation = _locations.isIncludedAndNotExcluded(jarUri); } } catch(Exception e) diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java index 26561839de0..13d817531a3 100644 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/ClasspathPatternTest.java @@ -154,6 +154,49 @@ public class ClasspathPatternTest Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true)); } + @SuppressWarnings("restriction") + @Test + public void testIncludedLocationsOrModule() throws Exception + { + Assume.assumeTrue(JDK.IS_9); + + // jar from JVM classloader + URI mod_string = TypeUtil.getLocationOfClass(String.class); + // System.err.println(mod_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"); + Assert.assertThat(pattern.match(String.class), Matchers.is(false)); + Assert.assertThat(pattern.match(Test.class), Matchers.is(false)); + Assert.assertThat(pattern.match(JDK.class), Matchers.is(false)); + Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(false)); + + // Add module for all JVM base classes + pattern.include("jrt:/java.base"); + + // Add jar for individual class and classes directory + pattern.include(loc_junit.toString(), loc_test.toString()); + + Assert.assertThat(pattern.match(String.class), Matchers.is(true)); + Assert.assertThat(pattern.match(Test.class), Matchers.is(true)); + Assert.assertThat(pattern.match(JDK.class), Matchers.is(false)); + Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true)); + + pattern.add("-java.lang.String"); + Assert.assertThat(pattern.match(String.class), Matchers.is(false)); + Assert.assertThat(pattern.match(Test.class), Matchers.is(true)); + Assert.assertThat(pattern.match(JDK.class), Matchers.is(false)); + Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true)); + } + @SuppressWarnings("restriction") @Test public void testExcludeLocations() throws Exception @@ -194,6 +237,46 @@ public class ClasspathPatternTest Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(false)); } + @SuppressWarnings("restriction") + @Test + public void testExcludeLocationsOrModule() throws Exception + { + Assume.assumeTrue(JDK.IS_9); + + // jar from JVM classloader + URI mod_string = TypeUtil.getLocationOfClass(String.class); + // System.err.println(mod_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(); + + // include everything + pattern.include("."); + + Assert.assertThat(pattern.match(String.class), Matchers.is(true)); + Assert.assertThat(pattern.match(Test.class), Matchers.is(true)); + Assert.assertThat(pattern.match(JDK.class), Matchers.is(true)); + Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(true)); + + // Add directory for both JVM classes + pattern.exclude("jrt:/java.base/"); + + // Add jar for individual class and classes directory + pattern.exclude(loc_junit.toString(), loc_test.toString()); + + Assert.assertThat(pattern.match(String.class), Matchers.is(false)); + Assert.assertThat(pattern.match(Test.class), Matchers.is(false)); + Assert.assertThat(pattern.match(JDK.class), Matchers.is(true)); + Assert.assertThat(pattern.match(ClasspathPatternTest.class), Matchers.is(false)); + } + @Test public void testLarge() { @@ -208,4 +291,14 @@ public class ClasspathPatternTest Assert.assertTrue(pattern.match("n" + i + "." + Integer.toHexString(100 + i) + ".Name")); } } + + + @Test + public void testJvmModule() + { + URI uri = TypeUtil.getLocationOfClass(String.class); + System.err.println(uri); + System.err.println(uri.toString().split("/")[0]); + System.err.println(uri.toString().split("/")[1]); + } }