Skip to content

Commit 8f882df

Browse files
committed
restore the old way of resolving classes from the classpath
I measured this and found no noticeable performance impact. Thus I think it is safer to still use the current Classloader to resolve class files as well. In the end we will ignore duplicates in the set of locations anyway, and if the lookup time has no real impact, we are still safer in case there is some other quirk (like the manifest classpath that I forgot about when I refactored this to fix the Android problem). Signed-off-by: Peter Gafert <[email protected]>
1 parent bc353f4 commit 8f882df

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

archunit/src/main/java/com/tngtech/archunit/core/importer/Locations.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,21 @@
1515
*/
1616
package com.tngtech.archunit.core.importer;
1717

18+
import java.io.IOException;
1819
import java.net.URL;
1920
import java.util.Collection;
20-
import java.util.HashSet;
21+
import java.util.List;
2122
import java.util.Set;
2223

2324
import com.google.common.collect.ImmutableSet;
2425
import com.tngtech.archunit.PublicAPI;
26+
import com.tngtech.archunit.base.ArchUnitException.LocationException;
2527
import com.tngtech.archunit.core.InitialConfiguration;
2628

29+
import static com.google.common.collect.Sets.newHashSet;
2730
import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
31+
import static com.tngtech.archunit.base.ClassLoaders.getCurrentClassLoader;
32+
import static java.util.Collections.list;
2833

2934
/**
3035
* Represents a set of {@link Location locations} of Java class files. Also offers methods to derive concrete locations (i.e. URIs) from
@@ -106,7 +111,7 @@ private static String asResourceName(String qualifiedName) {
106111
private static Set<Location> getLocationsOf(String resourceName) {
107112
UrlSource classpath = locationResolver.get().resolveClassPath();
108113
NormalizedResourceName normalizedResourceName = NormalizedResourceName.from(resourceName);
109-
return ImmutableSet.copyOf(getResourceLocations(normalizedResourceName, classpath));
114+
return ImmutableSet.copyOf(getResourceLocations(getCurrentClassLoader(Locations.class), normalizedResourceName, classpath));
110115
}
111116

112117
/**
@@ -117,8 +122,8 @@ private static Set<Location> getLocationsOf(String resourceName) {
117122
* does not behave correctly for older Java versions,
118123
* because the folder entry {@code /java/io} is missing from {@code rt.jar}.
119124
*/
120-
private static Collection<Location> getResourceLocations(NormalizedResourceName resourceName, Iterable<URL> classpath) {
121-
Set<Location> result = new HashSet<>();
125+
private static Collection<Location> getResourceLocations(ClassLoader loader, NormalizedResourceName resourceName, Iterable<URL> classpath) {
126+
Set<Location> result = newHashSet(Locations.of(getResources(loader, resourceName)));
122127
for (Location location : Locations.of(classpath)) {
123128
if (containsEntryWithPrefix(location, resourceName)) {
124129
result.add(location.append(resourceName.toString()));
@@ -127,6 +132,14 @@ private static Collection<Location> getResourceLocations(NormalizedResourceName
127132
return result;
128133
}
129134

135+
private static List<URL> getResources(ClassLoader loader, NormalizedResourceName resourceName) {
136+
try {
137+
return list(loader.getResources(resourceName.toString()));
138+
} catch (IOException e) {
139+
throw new LocationException(e);
140+
}
141+
}
142+
130143
private static boolean containsEntryWithPrefix(Location location, NormalizedResourceName searchedJarEntryPrefix) {
131144
for (NormalizedResourceName name : location.iterateEntries()) {
132145
if (name.startsWith(searchedJarEntryPrefix)) {

archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterSlowTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.io.IOException;
55
import java.lang.annotation.Annotation;
66
import java.lang.reflect.Field;
7+
import java.net.URL;
8+
import java.net.URLClassLoader;
79
import java.util.List;
810

911
import com.google.common.base.Joiner;
@@ -14,6 +16,7 @@
1416
import com.tngtech.archunit.core.domain.JavaClass;
1517
import com.tngtech.archunit.core.domain.JavaClasses;
1618
import com.tngtech.archunit.core.domain.JavaPackage;
19+
import com.tngtech.archunit.testutil.ContextClassLoaderRule;
1720
import com.tngtech.archunit.testutil.SystemPropertiesRule;
1821
import com.tngtech.archunit.testutil.TransientCopyRule;
1922
import org.junit.Assert;
@@ -38,6 +41,8 @@ public class ClassFileImporterSlowTest {
3841
public final TemporaryFolder temporaryFolder = new TemporaryFolder();
3942
@Rule
4043
public final SystemPropertiesRule systemPropertiesRule = new SystemPropertiesRule();
44+
@Rule
45+
public final ContextClassLoaderRule contextClassLoaderRule = new ContextClassLoaderRule();
4146

4247
@Test
4348
public void imports_the_classpath() {
@@ -115,13 +120,16 @@ public void imports_duplicate_classes() throws IOException {
115120

116121
@Test
117122
public void imports_classes_from_classpath_specified_in_manifest_file() {
118-
String manifestClasspath = Joiner.on(" ").join(Splitter.on(File.pathSeparator).omitEmptyStrings().split(System.getProperty(JAVA_CLASS_PATH_PROP)));
123+
String manifestClasspath =
124+
Joiner.on(" ").join(Splitter.on(File.pathSeparator).omitEmptyStrings().split(System.getProperty(JAVA_CLASS_PATH_PROP)));
119125
String jarPath = new TestJarFile()
120126
.withManifestAttribute(CLASS_PATH, manifestClasspath)
121127
.create()
122128
.getName();
123129

124130
System.clearProperty(JAVA_CLASS_PATH_PROP);
131+
// Ensure we cannot load the class through the fallback via the Classloader
132+
Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], null));
125133
verifyCantLoadWithCurrentClasspath(getClass());
126134
System.setProperty(JAVA_CLASS_PATH_PROP, jarPath);
127135

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.tngtech.archunit.testutil;
2+
3+
import org.junit.rules.ExternalResource;
4+
5+
public class ContextClassLoaderRule extends ExternalResource {
6+
private ClassLoader contextClassLoader;
7+
8+
@Override
9+
public void before() {
10+
contextClassLoader = Thread.currentThread().getContextClassLoader();
11+
}
12+
13+
@Override
14+
public void after() {
15+
Thread.currentThread().setContextClassLoader(contextClassLoader);
16+
}
17+
}

0 commit comments

Comments
 (0)