-
-
Save rmannibucau/ced8a809672a12a6f026e5ccac58a679 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java b/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java | |
index 7651ac3b..33a7b840 100644 | |
--- a/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java | |
+++ b/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java | |
@@ -16,6 +16,7 @@ | |
*/ | |
package org.apache.xbean.finder.archive; | |
+import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.net.URL; | |
@@ -42,20 +43,52 @@ public class JarArchive implements Archive, AutoCloseable { | |
private final MJarSupport mjar = new MJarSupport(); | |
public JarArchive(ClassLoader loader, URL url) { | |
-// if (!"jar".equals(url.getProtocol())) throw new IllegalArgumentException("not a jar url: " + url); | |
- | |
try { | |
this.loader = loader; | |
this.url = url; | |
- URL u = url; | |
- String jarPath = url.getFile(); | |
- if (jarPath.contains("!")) { | |
- jarPath = jarPath.substring(0, jarPath.indexOf("!")); | |
- u = new URL(jarPath); | |
+ String filePath = null; | |
+ switch (url.getProtocol()) { | |
+ case "jar": // if there is the resource marker, extract actual path | |
+ String jarPath = url.getFile(); | |
+ if (jarPath.startsWith("file:")) { | |
+ jarPath = jarPath.substring("file:".length()); | |
+ } | |
+ jarPath = FileArchive.decode(jarPath); | |
+ | |
+ int resourceSep = jarPath.indexOf("!/"); | |
+ if (resourceSep > 0) { | |
+ String substring = jarPath; | |
+ while (resourceSep > 0) { | |
+ substring = jarPath.substring(0, resourceSep); | |
+ if (new File(substring).exists()) { | |
+ break; | |
+ } | |
+ resourceSep = jarPath.indexOf("!/", resourceSep + 2); | |
+ } | |
+ if (!new File(substring).exists()) { | |
+ // unlikely but full path can be right, tested after cause unlikely | |
+ filePath = FileArchive.decode(FileArchive.decode(jarPath)); | |
+ if (!new File(filePath).exists()) { | |
+ throw new IllegalStateException("Can't find a file in '" + url + "' URL."); | |
+ } | |
+ } else { | |
+ filePath = substring; | |
+ } | |
+ } else { | |
+ filePath = jarPath; | |
+ } | |
+ break; | |
+ case "file": | |
+ filePath = FileArchive.decode(url.getFile()); | |
+ break; | |
+ default: | |
+ throw new IllegalStateException( | |
+ "Not a supported protocol: '" + url.getProtocol() + "' in '" + url + "'"); | |
} | |
- jar = new JarFile(FileArchive.decode(u.getFile())); // no more an url | |
- } catch (IOException e) { | |
+ | |
+ jar = new JarFile(filePath); | |
+ } catch (final IOException e) { | |
throw new IllegalStateException(e); | |
} | |
} | |
diff --git a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/Archives.java b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/Archives.java | |
index 470db26c..affa3ca9 100644 | |
--- a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/Archives.java | |
+++ b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/Archives.java | |
@@ -115,6 +115,22 @@ public class Archives { | |
// Create the ZIP file | |
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(classpath))); | |
+ putClasses(loader, out, classes); | |
+ | |
+ for (Map.Entry<String, String> entry : entries.entrySet()) { | |
+ | |
+ out.putNextEntry(new ZipEntry(entry.getKey())); | |
+ | |
+ out.write(entry.getValue().getBytes()); | |
+ } | |
+ | |
+ // Complete the ZIP file | |
+ out.close(); | |
+ return classpath; | |
+ } | |
+ | |
+ public static void putClasses(final ClassLoader loader, final ZipOutputStream out, | |
+ final Class<?>[] classes) throws IOException { | |
for (Class clazz : classes) { | |
String name = clazz.getName().replace('.', '/') + ".class"; | |
@@ -134,16 +150,5 @@ public class Archives { | |
// Complete the entry | |
out.closeEntry(); | |
} | |
- | |
- for (Map.Entry<String, String> entry : entries.entrySet()) { | |
- | |
- out.putNextEntry(new ZipEntry(entry.getKey())); | |
- | |
- out.write(entry.getValue().getBytes()); | |
- } | |
- | |
- // Complete the ZIP file | |
- out.close(); | |
- return classpath; | |
} | |
} | |
diff --git a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/JarArchiveTest.java b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/JarArchiveTest.java | |
index a4ae0918..8f497fb3 100644 | |
--- a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/JarArchiveTest.java | |
+++ b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/JarArchiveTest.java | |
@@ -21,19 +21,27 @@ import org.acme.foo.Green; | |
import org.acme.foo.Red; | |
import org.junit.Before; | |
import org.junit.BeforeClass; | |
+import org.junit.Rule; | |
import org.junit.Test; | |
+import org.junit.rules.TemporaryFolder; | |
import java.io.File; | |
import java.net.URL; | |
import java.net.URLClassLoader; | |
+import java.nio.charset.StandardCharsets; | |
+import java.nio.file.Files; | |
import java.util.ArrayList; | |
import java.util.List; | |
+import java.util.jar.JarEntry; | |
+import java.util.jar.JarOutputStream; | |
+import static java.util.Collections.singletonList; | |
import static junit.framework.Assert.assertEquals; | |
import static junit.framework.Assert.assertFalse; | |
import static junit.framework.Assert.assertNotNull; | |
import static junit.framework.Assert.assertTrue; | |
import static junit.framework.Assert.fail; | |
+import static org.apache.xbean.finder.archive.Archives.putClasses; | |
/** | |
* @version $Rev$ $Date$ | |
@@ -44,6 +52,9 @@ public class JarArchiveTest { | |
private static File classpath; | |
private JarArchive archive; | |
+ @Rule | |
+ public final TemporaryFolder tmp = new TemporaryFolder(); | |
+ | |
@BeforeClass | |
public static void classSetUp() throws Exception { | |
@@ -90,10 +101,7 @@ public class JarArchiveTest { | |
@Test | |
public void testIterator() throws Exception { | |
- List<String> actual = new ArrayList<String>(); | |
- for (Archive.Entry entry : archive) { | |
- actual.add(entry.getName()); | |
- } | |
+ List<String> actual = list(archive); | |
assertFalse(0 == actual.size()); | |
@@ -104,5 +112,74 @@ public class JarArchiveTest { | |
assertEquals(classes.length, actual.size()); | |
} | |
+ private List<String> list(final JarArchive archive) { | |
+ final List<String> actual = new ArrayList<>(); | |
+ for (final Archive.Entry entry : archive) { | |
+ actual.add(entry.getName()); | |
+ } | |
+ return actual; | |
+ } | |
+ | |
+ @Test | |
+ public void exclamationMarkInFilename() throws Exception { | |
+ createAndAssertBlueArchive(tmp.newFile("foo!bar.jar")); | |
+ } | |
+ | |
+ @Test | |
+ public void exclamationMarkAsResourceSep() throws Exception { | |
+ createAndAssertBlueArchive(new File(tmp.newFolder("foo!"), "the-file.jar")); | |
+ } | |
+ | |
+ @Test | |
+ public void exclamationMarkInFilePath() throws Exception { | |
+ createAndAssertBlueArchive(new File(tmp.newFolder("foo!bar"), "the-file.jar")); | |
+ } | |
+ @Test | |
+ public void exclamationMarkInResource() throws Exception { | |
+ final File file = tmp.newFile("file.jar"); | |
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader(); | |
+ try (final JarOutputStream out = new JarOutputStream(Files.newOutputStream(file.toPath()))) { | |
+ putClasses(loader, out, new Class<?>[]{Blue.class}); | |
+ out.putNextEntry(new JarEntry("foo!/bar.marker")); | |
+ out.write("Just a marker to find the file for ex".getBytes(StandardCharsets.UTF_8)); | |
+ out.closeEntry(); | |
+ } | |
+ | |
+ try ( | |
+ final URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toURI().toURL()}); | |
+ final JarArchive jar = new JarArchive( | |
+ loader, urlClassLoader.getResource("foo!/bar.marker"))) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ } | |
+ | |
+ private void createAndAssertBlueArchive(final File file) throws Exception { | |
+ final ClassLoader loader = Thread.currentThread().getContextClassLoader(); | |
+ try (final JarOutputStream out = new JarOutputStream(Files.newOutputStream(file.toPath()))) { | |
+ putClasses(loader, out, new Class<?>[]{Blue.class}); | |
+ } | |
+ | |
+ final URL url = file.toURI().toURL(); | |
+ // file:... | |
+ try (final JarArchive jar = new JarArchive(loader, url)) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ // file:... with marker with exclamation mark - this one is highly unlikely | |
+ try (final JarArchive jar = new JarArchive(loader, url)) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ // no resource | |
+ try (final JarArchive jar = new JarArchive(loader, new URL("jar", null, -1, url.toExternalForm()))) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ // resource | |
+ try (final JarArchive jar = new JarArchive(loader, new URL("jar", null, -1, url.toExternalForm() + "!/whatever"))) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ // resource with exclamation mark | |
+ try (final JarArchive jar = new JarArchive(loader, new URL("jar", null, -1, url.toExternalForm() + "!/whatever/is!/the!/marker"))) { | |
+ assertEquals(singletonList("org.acme.foo.Blue"), list(jar)); | |
+ } | |
+ } | |
} | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment