You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2018/07/28 15:34:40 UTC
svn commit: r1836927 - in /commons/proper/bcel/trunk/src:
changes/changes.xml main/java/org/apache/bcel/util/ClassPath.java
test/java/org/apache/bcel/util/ClassPathTestCase.java
Author: ggregory
Date: Sat Jul 28 15:34:40 2018
New Revision: 1836927
URL: http://svn.apache.org/viewvc?rev=1836927&view=rev
Log:
[BCEL-305] ClassPath.getClassFile() and friends do not work with JRE 9 and higher.
Modified:
commons/proper/bcel/trunk/src/changes/changes.xml
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java
commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java
Modified: commons/proper/bcel/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/changes/changes.xml?rev=1836927&r1=1836926&r2=1836927&view=diff
==============================================================================
--- commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] Sat Jul 28 15:34:40 2018
@@ -63,7 +63,8 @@ The <action> type attribute can be add,u
<body>
<release version="6.3" date="2018-MM-DD" description="?">
- <action issue="BCEL-304" type="fix" dev="ggregory" due-to="Gary Gregory, Ed Pavlak">ClassPath.getClassFile does not work with JDK 9 and higher (PR #22.)</action>
+ <action issue="BCEL-304" type="fix" dev="ggregory" due-to="Gary Gregory, Ed Pavlak">ClassPath.getClassFile() and friends do not work with JDK 9 and higher (PR #22.)</action>
+ <action issue="BCEL-305" type="fix" dev="ggregory" due-to="Gary Gregory">ClassPath.getClassFile() and friends do not work with JRE 9 and higher</action>
</release>
<release version="6.2" date="2017-12-08" description="Experimental Java 9 Support">
Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java?rev=1836927&r1=1836926&r2=1836927&view=diff
==============================================================================
--- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java (original)
+++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java Sat Jul 28 15:34:40 2018
@@ -17,6 +17,7 @@
*/
package org.apache.bcel.util;
+import java.io.Closeable;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -24,11 +25,24 @@ import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.zip.ZipEntry;
@@ -39,9 +53,9 @@ import java.util.zip.ZipFile;
*
* @version $Id$
*/
-public class ClassPath {
+public class ClassPath implements Closeable {
- private abstract static class AbstractPathEntry {
+ private abstract static class AbstractPathEntry implements Closeable {
abstract ClassFile getClassFile(String name, String suffix) throws IOException;
@@ -52,15 +66,23 @@ public class ClassPath {
private static abstract class AbstractZip extends AbstractPathEntry {
- private final ZipFile zip;
+ private final ZipFile zipFile;
+
+ AbstractZip(final ZipFile zipFile) {
+ this.zipFile = Objects.requireNonNull(zipFile, "zipFile");
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (zipFile != null) {
+ zipFile.close();
+ }
- AbstractZip(final ZipFile zip) {
- this.zip = zip;
}
@Override
ClassFile getClassFile(final String name, final String suffix) throws IOException {
- final ZipEntry entry = zip.getEntry(toEntryName(name, suffix));
+ final ZipEntry entry = zipFile.getEntry(toEntryName(name, suffix));
if (entry == null) {
return null;
@@ -70,12 +92,12 @@ public class ClassPath {
@Override
public String getBase() {
- return zip.getName();
+ return zipFile.getName();
}
@Override
public InputStream getInputStream() throws IOException {
- return zip.getInputStream(entry);
+ return zipFile.getInputStream(entry);
}
@Override
@@ -97,9 +119,9 @@ public class ClassPath {
@Override
URL getResource(final String name) {
- final ZipEntry entry = zip.getEntry(name);
+ final ZipEntry entry = zipFile.getEntry(name);
try {
- return entry != null ? new URL("jar:file:" + zip.getName() + "!/" + name) : null;
+ return entry != null ? new URL("jar:file:" + zipFile.getName() + "!/" + name) : null;
} catch (final MalformedURLException e) {
return null;
}
@@ -107,9 +129,9 @@ public class ClassPath {
@Override
InputStream getResourceAsStream(final String name) {
- final ZipEntry entry = zip.getEntry(name);
+ final ZipEntry entry = zipFile.getEntry(name);
try {
- return entry != null ? zip.getInputStream(entry) : null;
+ return entry != null ? zipFile.getInputStream(entry) : null;
} catch (final IOException e) {
return null;
}
@@ -119,7 +141,7 @@ public class ClassPath {
@Override
public String toString() {
- return zip.getName();
+ return zipFile.getName();
}
}
@@ -165,6 +187,12 @@ public class ClassPath {
}
@Override
+ public void close() throws IOException {
+ // Nothing to do
+
+ }
+
+ @Override
ClassFile getClassFile(final String name, final String suffix) throws IOException {
final File file = new File(dir + File.separatorChar + name.replace('.', File.separatorChar) + suffix);
return file.exists() ? new ClassFile() {
@@ -231,6 +259,7 @@ public class ClassPath {
return dir;
}
}
+
private static class Jar extends AbstractZip {
Jar(final ZipFile zip) {
@@ -243,6 +272,195 @@ public class ClassPath {
}
}
+
+ private static class JrtModule extends AbstractPathEntry {
+
+ private final Path modulePath;
+
+ public JrtModule(final Path modulePath) {
+ this.modulePath = Objects.requireNonNull(modulePath, "modulePath");
+ }
+
+ @Override
+ public void close() throws IOException {
+ // Nothing to do.
+
+ }
+
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ final Path resolved = modulePath.resolve(packageToFolder(name) + suffix);
+ if (Files.exists(resolved)) {
+ return new ClassFile() {
+
+ @Override
+ public String getBase() {
+ return resolved.getFileName().toString();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return Files.newInputStream(resolved);
+ }
+
+ @Override
+ public String getPath() {
+ return resolved.toString();
+ }
+
+ @Override
+ public long getSize() {
+ try {
+ return Files.size(resolved);
+ } catch (final IOException e) {
+ return 0;
+ }
+ }
+
+ @Override
+ public long getTime() {
+ try {
+ return Files.getLastModifiedTime(resolved).toMillis();
+ } catch (final IOException e) {
+ return 0;
+ }
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ URL getResource(final String name) {
+ final Path resovled = modulePath.resolve(name);
+ try {
+ return Files.exists(resovled) ? new URL("jrt:" + modulePath + "/" + name) : null;
+ } catch (final MalformedURLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ try {
+ return Files.newInputStream(modulePath.resolve(name));
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return modulePath.toString();
+ }
+
+ }
+
+ private static class JrtModules extends AbstractPathEntry {
+
+ @SuppressWarnings("resource")
+ private static JrtModule[] getJreModules() {
+ final List<JrtModule> list = new ArrayList<>();
+ final Path jrePath = Paths.get(System.getProperty("java.home"));
+ try {
+ final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar");
+ if (Files.exists(jrtFsPath)) {
+ final Map<String, ?> emptyMap = Collections.emptyMap();
+ try (URLClassLoader classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() });
+ FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader)) {
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(fs.getPath("/modules"))) {
+ final Iterator<Path> iterator = ds.iterator();
+ while (iterator.hasNext()) {
+ list.add(new JrtModule(iterator.next()));
+ }
+ }
+ }
+ }
+ } catch (final Exception e) {
+ // Log?
+ e.printStackTrace();
+ }
+ return list.toArray(new JrtModule[list.size()]);
+ }
+ URLClassLoader classLoader;
+ FileSystem fs;
+
+ private final JrtModule[] modules;
+
+ @SuppressWarnings("resource")
+ public JrtModules() {
+ final List<JrtModule> list = new ArrayList<>();
+ try {
+ final Map<String, ?> emptyMap = Collections.emptyMap();
+ final Path jrePath = Paths.get(System.getProperty("java.home"));
+ final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar");
+ this.classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() });
+ this.fs = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader);
+ try (DirectoryStream<Path> ds = Files.newDirectoryStream(fs.getPath("/modules"))) {
+ final Iterator<Path> iterator = ds.iterator();
+ while (iterator.hasNext()) {
+ list.add(new JrtModule(iterator.next()));
+ }
+ }
+ } catch (final IOException e) {
+ // TODO ?
+ e.printStackTrace();
+ }
+ this.modules = list.toArray(new JrtModule[list.size()]);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (modules != null) {
+ for (final JrtModule module : modules) {
+ module.close();
+ }
+ }
+ }
+
+ @Override
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (final JrtModule module : modules) {
+ final ClassFile classFile = module.getClassFile(name, suffix);
+ if (classFile != null) {
+ return classFile;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ URL getResource(final String name) {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (final JrtModule module : modules) {
+ final URL url = module.getResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ InputStream getResourceAsStream(final String name) {
+ // don't use a for each loop to avoid creating an iterator for the GC to collect.
+ for (final JrtModule module : modules) {
+ final InputStream inputStream = module.getResourceAsStream(name);
+ if (inputStream != null) {
+ return inputStream;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return Arrays.toString(modules);
+ }
+
+ }
+
private static class Module extends AbstractZip {
Module(final ZipFile zip) {
@@ -276,6 +494,21 @@ public class ClassPath {
public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(getClassPath());
+ private static void addJdkModules(final String javaHome, final List<String> list) {
+ String modulesPath = System.getProperty("java.modules.path");
+ if (modulesPath == null || modulesPath.trim().isEmpty()) {
+ // Default to looking in JAVA_HOME/jmods
+ modulesPath = javaHome + File.separator + "jmods";
+ }
+ final File modulesDir = new File(modulesPath);
+ if (modulesDir.exists()) {
+ final String[] modules = modulesDir.list(MODULES_FILTER);
+ for (final String module : modules) {
+ list.add(modulesDir.getPath() + File.separatorChar + module);
+ }
+ }
+ }
+
/**
* Checks for class path components in the following properties: "java.class.path", "sun.boot.class.path",
* "java.ext.dirs"
@@ -287,7 +520,21 @@ public class ClassPath {
final String classPathProp = System.getProperty("java.class.path");
final String bootClassPathProp = System.getProperty("sun.boot.class.path");
final String extDirs = System.getProperty("java.ext.dirs");
+ // System.out.println("java.version = " + System.getProperty("java.version"));
+ // System.out.println("java.class.path = " + classPathProp);
+ // System.out.println("sun.boot.class.path=" + bootClassPathProp);
+ // System.out.println("java.ext.dirs=" + extDirs);
+ final String javaHome = System.getProperty("java.home");
final List<String> list = new ArrayList<>();
+
+ // Starting in JRE 9, .class files are in the modules directory. Add them to the path.
+ final Path modulesPath = Paths.get(javaHome).resolve("lib/modules");
+ if (Files.exists(modulesPath) && Files.isRegularFile(modulesPath)) {
+ list.add(modulesPath.toAbsolutePath().toString());
+ }
+ // Starting in JDK 9, .class files are in the jmods directory. Add them to the path.
+ addJdkModules(javaHome, list);
+
getPathComponents(classPathProp, list);
getPathComponents(bootClassPathProp, list);
final List<String> dirs = new ArrayList<>();
@@ -301,20 +548,7 @@ public class ClassPath {
}
}
}
- final String javaHome = System.getProperty("java.home");
- // Starting in JDK 9, .class files are in the jmods directory. Add them to the path.
- String modulesPath = System.getProperty("java.modules.path");
- if (modulesPath == null || modulesPath.trim().isEmpty()) {
- // Default to looking in JAVA_HOME/jmods
- modulesPath = javaHome + File.separator + "jmods";
- }
- final File modules_dir = new File(modulesPath);
- if (modules_dir.exists()) {
- final String[] modules = modules_dir.list(MODULES_FILTER);
- for (final String module : modules) {
- list.add(modules_dir.getPath() + File.separatorChar + module);
- }
- }
+
final StringBuilder buf = new StringBuilder();
String separator = "";
for (final String path : list) {
@@ -327,9 +561,9 @@ public class ClassPath {
private static void getPathComponents(final String path, final List<String> list) {
if (path != null) {
- final StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
- while (tok.hasMoreTokens()) {
- final String name = tok.nextToken();
+ final StringTokenizer tokenizer = new StringTokenizer(path, File.pathSeparator);
+ while (tokenizer.hasMoreTokens()) {
+ final String name = tokenizer.nextToken();
final File file = new File(name);
if (file.exists()) {
list.add(name);
@@ -358,20 +592,21 @@ public class ClassPath {
this(getClassPath());
}
- public ClassPath(final ClassPath parent, final String class_path) {
- this(class_path);
+ public ClassPath(final ClassPath parent, final String classPath) {
+ this(classPath);
this.parent = parent;
}
/**
* Search for classes in given path.
*
- * @param class_path
+ * @param classPath
*/
- public ClassPath(final String class_path) {
- this.classPath = class_path;
+ @SuppressWarnings("resource")
+ public ClassPath(final String classPath) {
+ this.classPath = classPath;
final List<AbstractPathEntry> list = new ArrayList<>();
- for (final StringTokenizer tokenizer = new StringTokenizer(class_path, File.pathSeparator); tokenizer
+ for (final StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); tokenizer
.hasMoreTokens();) {
final String path = tokenizer.nextToken();
if (!path.isEmpty()) {
@@ -382,6 +617,8 @@ public class ClassPath {
list.add(new Dir(path));
} else if (path.endsWith(".jmod")) {
list.add(new Module(new ZipFile(file)));
+ } else if (path.endsWith(File.separator + "modules")) {
+ list.add(new JrtModules());
} else {
list.add(new Jar(new ZipFile(file)));
}
@@ -398,6 +635,16 @@ public class ClassPath {
}
@Override
+ public void close() throws IOException {
+ if (paths != null) {
+ for (final AbstractPathEntry path : paths) {
+ path.close();
+ }
+ }
+
+ }
+
+ @Override
public boolean equals(final Object o) {
if (o instanceof ClassPath) {
final ClassPath cp = (ClassPath) o;
Modified: commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java
URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java?rev=1836927&r1=1836926&r2=1836927&view=diff
==============================================================================
--- commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java (original)
+++ commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java Sat Jul 28 15:34:40 2018
@@ -19,12 +19,25 @@
package org.apache.bcel.util;
import java.io.IOException;
+import java.io.InputStream;
import org.apache.bcel.AbstractTestCase;
+import org.junit.Assert;
public class ClassPathTestCase extends AbstractTestCase {
public void testGetClassFile() throws IOException {
- ClassPath.SYSTEM_CLASS_PATH.getClassFile("java.lang.String");
+ Assert.assertNotNull(ClassPath.SYSTEM_CLASS_PATH.getClassFile("java.lang.String"));
+ }
+
+ public void testGetResource() throws IOException {
+ Assert.assertNotNull(ClassPath.SYSTEM_CLASS_PATH.getResource("java/lang/String.class"));
+ }
+
+ public void testGetResourceAsStream() throws IOException {
+ try (final InputStream inputStream = ClassPath.SYSTEM_CLASS_PATH
+ .getResourceAsStream("java/lang/String.class")) {
+ Assert.assertNotNull(inputStream);
+ }
}
}
\ No newline at end of file