XBEAN-312 ensure we dont list mjar jars twice
git-svn-id: https://svn.apache.org/repos/asf/geronimo/xbean/trunk@1842433 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/xbean-finder/src/main/java/org/apache/xbean/finder/ClassLoaders.java b/xbean-finder/src/main/java/org/apache/xbean/finder/ClassLoaders.java
index 4468b8e..3e181d6 100644
--- a/xbean-finder/src/main/java/org/apache/xbean/finder/ClassLoaders.java
+++ b/xbean-finder/src/main/java/org/apache/xbean/finder/ClassLoaders.java
@@ -16,8 +16,6 @@
*/
package org.apache.xbean.finder;
-import org.apache.xbean.finder.util.Files;
-
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -28,12 +26,16 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.xbean.finder.util.Files;
public final class ClassLoaders {
private static final boolean DONT_USE_GET_URLS = Boolean.getBoolean("xbean.finder.use.get-resources");
private static final ClassLoader SYSTEM = ClassLoader.getSystemClassLoader();
private static final boolean UNIX = !System.getProperty("os.name").toLowerCase().contains("win");
+ private static final Pattern MJAR_PATTERN = Pattern.compile(".*/META-INF/versions/[0-9]+/$");
public static Set<URL> findUrls(final ClassLoader classLoader) throws IOException {
if (classLoader == null || (SYSTEM.getParent() != null && classLoader == SYSTEM.getParent())) {
@@ -115,7 +117,14 @@
final String externalForm = url.toExternalForm();
set.add(new URL(externalForm.substring(0, externalForm.lastIndexOf("META-INF"))));
}
- set.addAll(Collections.list(classLoader.getResources("")));
+ for (final URL url : Collections.list(classLoader.getResources(""))) {
+ final String externalForm = url.toExternalForm();
+ if (MJAR_PATTERN.matcher(externalForm).matches()) {
+ set.add(new URL(externalForm.substring(0, externalForm.lastIndexOf("META-INF"))));
+ } else {
+ set.add(url);
+ }
+ }
return set;
}
diff --git a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/MJarJarArchiveTest.java b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/MJarJarArchiveTest.java
index 2863dc3..a806400 100644
--- a/xbean-finder/src/test/java/org/apache/xbean/finder/archive/MJarJarArchiveTest.java
+++ b/xbean-finder/src/test/java/org/apache/xbean/finder/archive/MJarJarArchiveTest.java
@@ -18,8 +18,9 @@
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ALOAD;
@@ -34,16 +35,20 @@
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.apache.xbean.finder.AnnotationFinder;
+import org.apache.xbean.finder.ClassLoaders;
import org.apache.xbean.finder.util.IOUtil;
-import org.junit.Assume;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -95,29 +100,29 @@
jarOS.closeEntry();
}
{
+ jarOS.putNextEntry(new JarEntry("META-INF/"));
+ jarOS.closeEntry();
+ }
+ {
+ jarOS.putNextEntry(new JarEntry("META-INF/versions/"));
+ jarOS.closeEntry();
+ }
+ {
+ jarOS.putNextEntry(new JarEntry("META-INF/versions/" + version + "/"));
+ jarOS.closeEntry();
+ }
+ {
+ jarOS.putNextEntry(new JarEntry("META-INF/versions/9/"));
+ jarOS.closeEntry();
+ }
+ {
jarOS.putNextEntry(new JarEntry("META-INF/versions/" + version + "/org/test/Foo.class"));
-
- final ClassWriter writer = new ClassWriter(COMPUTE_FRAMES);
- writer.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "org/test/Foo", null, Type.getInternalName(Object.class), new String[0]);
-
- final MethodVisitor constructor = writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
- constructor.visitCode();
- constructor.visitVarInsn(ALOAD, 0);
- constructor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
- constructor.visitInsn(RETURN);
- constructor.visitMaxs(1, 1);
- constructor.visitEnd();
-
- final MethodVisitor run = writer.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
- run.visitAnnotation(Type.getDescriptor(Marker.class), true).visitEnd();
- run.visitCode();
- run.visitInsn(RETURN);
- run.visitMaxs(-1, -1);
- run.visitEnd();
-
- writer.visitEnd();
-
- jarOS.write(writer.toByteArray());
+ jarOS.write(createFooClazz().toByteArray());
+ jarOS.closeEntry();
+ }
+ {
+ jarOS.putNextEntry(new JarEntry("META-INF/versions/9/org/test/Foo.class"));
+ jarOS.write(createFooClazz().toByteArray());
jarOS.closeEntry();
}
} finally {
@@ -139,8 +144,63 @@
@Test
public void testGetBytecode() throws Exception {
- Assume.assumeFalse(System.getProperty("java.version", "1").startsWith("1"));
- final URLClassLoader loader = new URLClassLoader(new URL[]{jar.toURI().toURL()}, Thread.currentThread().getContextClassLoader()) {
+ ensureJava9OrLater();
+ final URLClassLoader loader = newMJarClassLoader();
+ final JarArchive archive = new JarArchive(loader, jar.toURI().toURL());
+ final AnnotationFinder finder = new AnnotationFinder(archive, true);
+ assertEquals(1, finder.findAnnotatedMethods(Marker.class).size());
+ if (Closeable.class.isInstance(loader)) {
+ Closeable.class.cast(loader).close();
+ }
+ }
+
+ @Test
+ public void classLoaderScanningOneUrl() throws Exception {
+ ensureJava9OrLater();
+ final URLClassLoader loader = newMJarClassLoader();
+ final Set<URL> urls = ClassLoaders.findUrlFromResources(loader);
+ final Collection<String> testUrls = new ArrayList<String>();
+ for (final URL u : urls) {
+ final String str = u.toExternalForm();
+ if (str.contains("org.apache.xbean.finder.archive.MJarJarArchiveTest")) {
+ testUrls.add(str);
+ }
+ }
+ assertEquals(1, testUrls.size());
+ if (Closeable.class.isInstance(loader)) {
+ Closeable.class.cast(loader).close();
+ }
+ }
+
+ private void ensureJava9OrLater() {
+ assumeTrue(!System.getProperty("java.version", "1").startsWith("1."));
+ }
+
+ private static ClassWriter createFooClazz() {
+ final ClassWriter writer = new ClassWriter(COMPUTE_FRAMES);
+ writer.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "org/test/Foo", null, Type.getInternalName(Object.class), new String[0]);
+
+ final MethodVisitor constructor = writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ constructor.visitCode();
+ constructor.visitVarInsn(ALOAD, 0);
+ constructor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ constructor.visitInsn(RETURN);
+ constructor.visitMaxs(1, 1);
+ constructor.visitEnd();
+
+ final MethodVisitor run = writer.visitMethod(ACC_PUBLIC, "run", "()V", null, null);
+ run.visitAnnotation(Type.getDescriptor(Marker.class), true).visitEnd();
+ run.visitCode();
+ run.visitInsn(RETURN);
+ run.visitMaxs(-1, -1);
+ run.visitEnd();
+
+ writer.visitEnd();
+ return writer;
+ }
+
+ private URLClassLoader newMJarClassLoader() throws MalformedURLException {
+ return new URLClassLoader(new URL[]{jar.toURI().toURL()}, Thread.currentThread().getContextClassLoader()) {
@Override
protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
@@ -169,12 +229,6 @@
return super.loadClass(name, resolve);
}
};
- final JarArchive archive = new JarArchive(loader, jar.toURI().toURL());
- final AnnotationFinder finder = new AnnotationFinder(archive, true);
- assertEquals(1, finder.findAnnotatedMethods(Marker.class).size());
- if (Closeable.class.isInstance(loader)) {
- Closeable.class.cast(loader).close();
- }
}
@Retention(RUNTIME)