Skip to content

Commit da19214

Browse files
committed
use standard lib component to discover classes on the boot classpath
1 parent 83093d8 commit da19214

File tree

2 files changed

+91
-22
lines changed

2 files changed

+91
-22
lines changed

affinity/src/main/java/net/openhft/affinity/BootClassPath.java

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,41 +19,97 @@
1919

2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
22-
import sun.misc.URLClassPath;
2322

24-
import java.io.File;
25-
import java.net.MalformedURLException;
26-
import java.net.URL;
23+
import java.io.IOException;
24+
import java.nio.file.FileVisitResult;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import java.nio.file.Paths;
28+
import java.nio.file.SimpleFileVisitor;
29+
import java.nio.file.attribute.BasicFileAttributes;
30+
import java.util.Collections;
31+
import java.util.Enumeration;
32+
import java.util.HashSet;
33+
import java.util.Set;
34+
import java.util.jar.JarEntry;
35+
import java.util.jar.JarFile;
2736

2837
enum BootClassPath {
2938
INSTANCE;
3039

31-
private final URLClassPath bootClassPath = new URLClassPath(getBootClassPathURLs());
40+
private final Set<String> bootClassPathResources = Collections.unmodifiableSet(getResourcesOnBootClasspath());
3241

3342
public final boolean has(String binaryClassName) {
34-
String resourceClassName = binaryClassName.replace('.', '/').concat(".class");
35-
return bootClassPath.getResource(resourceClassName, false) != null;
43+
final String resourceClassName = binaryClassName.replace('.', '/').concat(".class");
44+
return bootClassPathResources.contains(resourceClassName);
3645
}
3746

38-
private URL[] getBootClassPathURLs() {
39-
Logger LOGGER = LoggerFactory.getLogger(BootClassPath.class);
40-
try {
41-
String bootClassPath = System.getProperty("sun.boot.class.path");
42-
LOGGER.trace("Boot class-path is: {}", bootClassPath);
47+
private static Set<String> getResourcesOnBootClasspath() {
48+
final Logger logger = LoggerFactory.getLogger(BootClassPath.class);
49+
final Set<String> resources = new HashSet<>();
50+
final String bootClassPath = System.getProperty("sun.boot.class.path");
51+
logger.trace("Boot class-path is: {}", bootClassPath);
52+
53+
final String pathSeparator = System.getProperty("path.separator");
54+
logger.trace("Path separator is: '{}'", pathSeparator);
55+
56+
final String[] pathElements = bootClassPath.split(pathSeparator);
57+
58+
for (final String pathElement : pathElements) {
59+
resources.addAll(findResources(Paths.get(pathElement), logger));
60+
}
61+
62+
return resources;
63+
}
64+
65+
private static Set<String> findResources(final Path path, final Logger logger) {
66+
if (!Files.exists(path)) {
67+
return Collections.emptySet();
68+
}
69+
70+
if (Files.isDirectory(path)) {
71+
return findResourcesInDirectory(path, logger);
72+
}
4373

44-
String pathSeparator = System.getProperty("path.separator");
45-
LOGGER.trace("Path separator is: '{}'", pathSeparator);
74+
return findResourcesInJar(path, logger);
75+
}
4676

47-
String[] pathElements = bootClassPath.split(pathSeparator);
48-
URL[] pathURLs = new URL[pathElements.length];
49-
for (int i = 0; i < pathElements.length; i++) {
50-
pathURLs[i] = new File(pathElements[i]).toURI().toURL();
77+
private static Set<String> findResourcesInJar(final Path path, final Logger logger) {
78+
final Set<String> jarResources = new HashSet<>();
79+
try {
80+
final JarFile jarFile = new JarFile(path.toFile());
81+
final Enumeration<JarEntry> entries = jarFile.entries();
82+
while (entries.hasMoreElements()) {
83+
final JarEntry jarEntry = entries.nextElement();
84+
if (jarEntry.getName().endsWith(".class")) {
85+
jarResources.add(jarEntry.getName());
86+
}
5187
}
5288

53-
return pathURLs;
54-
} catch (MalformedURLException e) {
55-
LOGGER.warn("Parsing the boot class-path failed! Reason: {}", e.getMessage());
56-
return new URL[0];
89+
90+
} catch (IOException e) {
91+
logger.warn("Not a jar file: {}", path);
92+
}
93+
94+
return jarResources;
95+
}
96+
97+
private static Set<String> findResourcesInDirectory(final Path path, final Logger logger) {
98+
final Set<String> dirResources = new HashSet<>();
99+
try {
100+
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
101+
@Override
102+
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
103+
if (file.getFileName().toString().endsWith(".class")) {
104+
dirResources.add(path.relativize(file).toString());
105+
}
106+
return super.visitFile(file, attrs);
107+
}
108+
});
109+
} catch (IOException e) {
110+
logger.warn("Error walking dir: " + path, e);
57111
}
112+
113+
return dirResources;
58114
}
59115
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.openhft.affinity;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertTrue;
6+
7+
public class BootClassPathTest {
8+
@Test
9+
public void shouldDetectClassesOnClassPath() throws Exception {
10+
assertTrue(BootClassPath.INSTANCE.has("java.lang.Thread"));
11+
assertTrue(BootClassPath.INSTANCE.has("java.lang.Runtime"));
12+
}
13+
}

0 commit comments

Comments
 (0)