stream()
+ {
+ return entries.values().stream();
+ }
+
+ public VersionedJarEntry getEntry(String name)
+ {
+ return entries.get(name);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s[%b,%d]",jarFile.getName(),isMultiRelease(),getVersion());
+ }
+
+ public class VersionedJarEntry
{
final JarEntry entry;
final String name;
final int version;
+ final boolean inner;
+ final String outer;
VersionedJarEntry(JarEntry entry)
{
@@ -65,17 +129,18 @@ public class MultiReleaseJarFile
String name = entry.getName();
if (name.startsWith(META_INF_VERSIONS))
{
- v=-1;
+ v = -1;
int index = name.indexOf('/', META_INF_VERSIONS.length());
- if (index >= 0 && index < name.length())
+ if (index > META_INF_VERSIONS.length() && index < name.length())
{
try
{
- v = Integer.parseInt(name.substring(META_INF_VERSIONS.length(), index), 10);
+ v = TypeUtil.parseInt(name, META_INF_VERSIONS.length(), index - META_INF_VERSIONS.length(), 10);
name = name.substring(index + 1);
}
catch (NumberFormatException x)
{
+ throw new RuntimeException("illegal version in "+jarFile,x);
}
}
}
@@ -83,9 +148,21 @@ public class MultiReleaseJarFile
this.entry = entry;
this.name = name;
this.version = v;
+ this.inner = name.contains("$") && name.toLowerCase().endsWith(".class");
+ this.outer = inner ? name.substring(0, name.indexOf('$')) + name.substring(name.length() - 6, name.length()) : null;
}
- public int version()
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getNameInJar()
+ {
+ return entry.getName();
+ }
+
+ public int getVersion()
{
return version;
}
@@ -95,15 +172,34 @@ public class MultiReleaseJarFile
return version > 0;
}
+ public boolean isDirectory()
+ {
+ return entry.isDirectory();
+ }
+
+ public InputStream getInputStream() throws IOException
+ {
+ return jarFile.getInputStream(entry);
+ }
+
+ boolean isApplicable()
+ {
+ if (multiRelease)
+ return this.version>=0 && this.version <= majorVersion && name.length()>0;
+ return this.version==0;
+ }
+
+ boolean isReplacedBy(VersionedJarEntry entry)
+ {
+ if (isDirectory())
+ return entry.version==0;
+ return this.name.equals(entry.name) && entry.version>version;
+ }
+
@Override
public String toString()
{
- return entry.toString() + (version==0?"[base]":("["+version+"]"));
- }
-
- public JarEntry resolve(JarFile jf)
- {
- return entry;
+ return String.format("%s->%s[%d]",name,entry.getName(),version);
}
}
}
diff --git a/jetty-util/src/main/java9/org/eclipse/jetty/util/MultiReleaseJarFile.java b/jetty-util/src/main/java9/org/eclipse/jetty/util/MultiReleaseJarFile.java
deleted file mode 100644
index b15e2a3ceaf..00000000000
--- a/jetty-util/src/main/java9/org/eclipse/jetty/util/MultiReleaseJarFile.java
+++ /dev/null
@@ -1,143 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2017 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.io.File;
-import java.io.IOException;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.stream.Stream;
-
-/**
- * Utility class to create a stream of Multi Release {@link JarEntry}s
- * This is the java 9 version of this class.
- * A java 8 version of this class is included as the base version in a Multi Release
- * jetty-util jar, that uses does not use java 9 APIs.
- */
-public class MultiReleaseJarFile
-{
- private static final String META_INF_VERSIONS = "META-INF/versions/";
-
- public static JarFile open(File file) throws IOException
- {
- return new JarFile(file,true,JarFile.OPEN_READ,Runtime.version());
- }
-
- public static Stream streamVersioned(JarFile jf)
- {
- return jf.stream()
- .map(VersionedJarEntry::new);
- }
-
- public static Stream stream(JarFile jf)
- {
- if (!jf.isMultiRelease())
- return jf.stream();
-
- // Map to hold unversioned name to VersionedJarEntry
- Map entries = new TreeMap<>();
-
- // Fill the map, removing non applicable entries and replacing versions with later versions.
- streamVersioned(jf)
- .filter(e->e.isApplicable(jf.getVersion().major()))
- .forEach(e->entries.compute(e.name, (k, v) -> v==null || v.isReplacedBy(e) ? e : v));
-
- // filter the values to remove non applicable inner classes and map to versioned entry
- return entries.values().stream()
- .filter(e-> {
- if (!e.inner)
- return true;
- VersionedJarEntry outer = entries.get(e.outer);
- return outer != null && outer.version == e.version;
- })
- .map(e->e.resolve(jf));
- }
-
- public static class VersionedJarEntry
- {
- final JarEntry entry;
- final String name;
- final int version;
- final boolean inner;
- final String outer;
-
- VersionedJarEntry(JarEntry entry)
- {
- int v = 0;
- String name = entry.getName();
- if (name.startsWith(META_INF_VERSIONS))
- {
- v=-1;
- int index = name.indexOf('/', META_INF_VERSIONS.length());
- if (index >= 0 && index < name.length())
- {
- try
- {
- v = Integer.parseInt(name, META_INF_VERSIONS.length(), index, 10);
- name = name.substring(index + 1);
- }
- catch (NumberFormatException x)
- {
- }
- }
- }
-
- this.entry = entry;
- this.name = name;
- this.version = v;
- this.inner = name.contains("$") && name.toLowerCase().endsWith(".class");
- this.outer = inner?name.substring(0,name.indexOf('$'))+name.substring(name.length()-6,name.length()):null;
- }
-
- public int version()
- {
- return version;
- }
-
- public boolean isVersioned()
- {
- return version > 0;
- }
-
- boolean isApplicable(int version)
- {
- return this.version>=0 && this.version <= version;
- }
-
- boolean isReplacedBy(VersionedJarEntry entry)
- {
- return this.name.equals(entry.name) && entry.version>version;
- }
-
- @Override
- public String toString()
- {
- return entry.toString() + (version==0?"[base]":("["+version+"]"));
- }
-
- public JarEntry resolve(JarFile jf)
- {
- if (version>0)
- return jf.getJarEntry(name);
- return entry;
- }
- }
-}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiReleaseJarFileTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiReleaseJarFileTest.java
new file mode 100644
index 00000000000..01031f6296a
--- /dev/null
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiReleaseJarFileTest.java
@@ -0,0 +1,92 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2017 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.io.File;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.jetty.toolchain.test.AdvancedRunner;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AdvancedRunner.class)
+public class MultiReleaseJarFileTest
+{
+ private File testResources = MavenTestingUtils.getTestResourcesDir().getAbsoluteFile();
+ private File example = new File(testResources,"example.jar");
+
+ @Test
+ public void testExampleJarIsMR() throws Exception
+ {
+ MultiReleaseJarFile jarFile = new MultiReleaseJarFile(example);
+ assertTrue(jarFile.isMultiRelease());
+ }
+
+ @Test
+ public void testBase() throws Exception
+ {
+ MultiReleaseJarFile jarFile = new MultiReleaseJarFile(example,8,false);
+ assertThat(jarFile.getEntry("META-INF/MANIFEST.MF").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/OnlyInBase.class").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/InBoth$InnerBase.class").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/InBoth$InnerBoth.class").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/InBoth.class").getVersion(), is(0));
+
+ assertThat(jarFile.stream().count(), is(5L));
+ }
+
+ @Test
+ public void test9() throws Exception
+ {
+ MultiReleaseJarFile jarFile = new MultiReleaseJarFile(example,9,false);
+ assertThat(jarFile.getEntry("META-INF/MANIFEST.MF").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/OnlyInBase.class").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/InBoth$InnerBoth.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/InBoth.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/OnlyIn9.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/onlyIn9/OnlyIn9.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/InBoth$Inner9.class").getVersion(), is(9));
+
+ assertThat(jarFile.stream().count(), is(7L));
+ }
+
+ @Test
+ public void test10() throws Exception
+ {
+ MultiReleaseJarFile jarFile = new MultiReleaseJarFile(example,10,false);
+ assertThat(jarFile.getEntry("META-INF/MANIFEST.MF").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/OnlyInBase.class").getVersion(), is(0));
+ assertThat(jarFile.getEntry("org/example/InBoth.class").getVersion(), is(10));
+ assertThat(jarFile.getEntry("org/example/OnlyIn9.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/onlyIn9/OnlyIn9.class").getVersion(), is(9));
+ assertThat(jarFile.getEntry("org/example/In10Only.class").getVersion(), is(10));
+
+ assertThat(jarFile.stream().count(), is(6L));
+ }
+
+
+}
diff --git a/jetty-util/src/test/resources/example.jar b/jetty-util/src/test/resources/example.jar
index 3c3e1cdaa1d..171a823145c 100644
Binary files a/jetty-util/src/test/resources/example.jar and b/jetty-util/src/test/resources/example.jar differ
diff --git a/pom.xml b/pom.xml
index c4b333c0c7e..d8fc754385b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -150,6 +150,57 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+
+ **/org/eclipse/jetty/ant/**
+ **/org/eclipse/jetty/maven/**
+ **/org/eclipse/jetty/jspc/**
+
+ **/org/eclipse/jetty/embedded/**
+ **/org/eclipse/jetty/asyncrest/**
+ **/org/eclipse/jetty/demo/**
+
+ **/org/eclipse/jetty/gcloud/**
+ **/org/eclipse/jetty/infinispan/**
+ **/org/eclipse/jetty/osgi/**
+ **/org/eclipse/jetty/spring/**
+ **/org/eclipse/jetty/http/spi/**
+
+ **/org/eclipse/jetty/tests/**
+ **/org/eclipse/jetty/test/**
+
+
+
+
+ jacoco-initialize
+ initialize
+
+ prepare-agent
+
+
+
+ jacoco-site
+ package
+
+ report
+
+
+
+
+ **/org/eclipse/jetty/**
+
+
+
+
+
maven-pmd-plugin
@@ -1085,65 +1136,6 @@