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 05:00:22 UTC
svn commit: r1836867 - 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 05:00:21 2018
New Revision: 1836867
URL: http://svn.apache.org/viewvc?rev=1836867&view=rev
Log:
[BCEL-304] ClassPath.getClassFile does not work with Java 9 and higher.
Added:
commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java
Modified:
commons/proper/bcel/trunk/src/changes/changes.xml
commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.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=1836867&r1=1836866&r2=1836867&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 05:00:21 2018
@@ -62,7 +62,8 @@ The <action> type attribute can be add,u
-->
<body>
- <release version="6.3" date="2017-MM-DD" description="?">
+ <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.</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=1836867&r1=1836866&r2=1836867&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 05:00:21 2018
@@ -35,8 +35,7 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
- * Responsible for loading (class) files from the CLASSPATH. Inspired by
- * sun.tools.ClassPath.
+ * Responsible for loading (class) files from the CLASSPATH. Inspired by sun.tools.ClassPath.
*
* @version $Id$
*/
@@ -47,14 +46,23 @@ public class ClassPath {
private static final FilenameFilter ARCHIVE_FILTER = new FilenameFilter() {
@Override
- public boolean accept( final File dir, String name ) {
+ public boolean accept(final File dir, String name) {
name = name.toLowerCase(Locale.ENGLISH);
return name.endsWith(".zip") || name.endsWith(".jar");
}
};
- private final PathEntry[] paths;
- private final String class_path;
+ private static final FilenameFilter MODULES_FILTER = new FilenameFilter() {
+
+ @Override
+ public boolean accept(final File dir, String name) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ return name.endsWith(".jmod");
+ }
+ };
+
+ private final AbstractPathEntry[] paths;
+ private final String classPath;
private ClassPath parent;
public ClassPath(final ClassPath parent, final String class_path) {
@@ -68,8 +76,8 @@ public class ClassPath {
* @param class_path
*/
public ClassPath(final String class_path) {
- this.class_path = class_path;
- final List<PathEntry> list = new ArrayList<>();
+ this.classPath = class_path;
+ final List<AbstractPathEntry> list = new ArrayList<>();
for (final StringTokenizer tok = new StringTokenizer(class_path, File.pathSeparator); tok.hasMoreTokens();) {
final String path = tok.nextToken();
if (!path.isEmpty()) {
@@ -78,8 +86,10 @@ public class ClassPath {
if (file.exists()) {
if (file.isDirectory()) {
list.add(new Dir(path));
+ } else if (path.endsWith(".jmod")) {
+ list.add(new Module(new ZipFile(file)));
} else {
- list.add(new Zip(new ZipFile(file)));
+ list.add(new Jar(new ZipFile(file)));
}
}
} catch (final IOException e) {
@@ -89,12 +99,13 @@ public class ClassPath {
}
}
}
- paths = new PathEntry[list.size()];
+ paths = new AbstractPathEntry[list.size()];
list.toArray(paths);
}
/**
* Search for classes in CLASSPATH.
+ *
* @deprecated Use SYSTEM_CLASS_PATH constant
*/
@Deprecated
@@ -102,36 +113,35 @@ public class ClassPath {
this(getClassPath());
}
- /** @return used class path string
+ /**
+ * @return used class path string
*/
@Override
public String toString() {
if (parent != null) {
- return parent + File.pathSeparator + class_path;
+ return parent + File.pathSeparator + classPath;
}
- return class_path;
+ return classPath;
}
@Override
public int hashCode() {
if (parent != null) {
- return class_path.hashCode() + parent.hashCode();
+ return classPath.hashCode() + parent.hashCode();
}
- return class_path.hashCode();
+ return classPath.hashCode();
}
-
@Override
- public boolean equals( final Object o ) {
+ public boolean equals(final Object o) {
if (o instanceof ClassPath) {
- final ClassPath cp = (ClassPath)o;
- return class_path.equals(cp.toString());
+ final ClassPath cp = (ClassPath) o;
+ return classPath.equals(cp.toString());
}
return false;
}
-
- private static void getPathComponents( final String path, final List<String> list ) {
+ 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()) {
@@ -144,9 +154,9 @@ public class ClassPath {
}
}
-
- /** Checks for class path components in the following properties:
- * "java.class.path", "sun.boot.class.path", "java.ext.dirs"
+ /**
+ * Checks for class path components in the following properties: "java.class.path", "sun.boot.class.path",
+ * "java.ext.dirs"
*
* @return class path as used by default by BCEL
*/
@@ -169,6 +179,19 @@ public class ClassPath {
}
}
}
+ // Starting in JDK 9, .class files are in the jmods directory. Add them to the path.
+ String modules_path = System.getProperty("java.modules.path");
+ if (modules_path == null || modules_path.trim().isEmpty()) {
+ // Default to looking in JAVA_HOME/jmods
+ modules_path = System.getProperty("java.home") + File.separator + "jmods";
+ }
+ final File modules_dir = new File(modules_path);
+ 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) {
@@ -179,24 +202,25 @@ public class ClassPath {
return buf.toString().intern();
}
-
/**
- * @param name fully qualified class name, e.g. java.lang.String
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
* @return input stream for class
*/
- public InputStream getInputStream( final String name ) throws IOException {
- return getInputStream(name.replace('.', '/'), ".class");
+ public InputStream getInputStream(final String name) throws IOException {
+ return getInputStream(packageToFolder(name), ".class");
}
-
/**
* Return stream for class or resource on CLASSPATH.
*
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
* @return input stream for file on class path
*/
- public InputStream getInputStream( final String name, final String suffix ) throws IOException {
+ public InputStream getInputStream(final String name, final String suffix) throws IOException {
InputStream is = null;
try {
is = getClass().getClassLoader().getResourceAsStream(name + suffix); // may return null
@@ -210,12 +234,13 @@ public class ClassPath {
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
* @return InputStream supplying the resource, or null if no resource with that name.
* @since 6.0
*/
public InputStream getResourceAsStream(final String name) {
- for (final PathEntry path : paths) {
+ for (final AbstractPathEntry path : paths) {
InputStream is;
if ((is = path.getResourceAsStream(name)) != null) {
return is;
@@ -225,12 +250,13 @@ public class ClassPath {
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
* @return URL supplying the resource, or null if no resource with that name.
* @since 6.0
*/
public URL getResource(final String name) {
- for (final PathEntry path : paths) {
+ for (final AbstractPathEntry path : paths) {
URL url;
if ((url = path.getResource(name)) != null) {
return url;
@@ -240,14 +266,14 @@ public class ClassPath {
}
/**
- * @param name fully qualified resource name, e.g. java/lang/String.class
- * @return An Enumeration of URLs supplying the resource, or an
- * empty Enumeration if no resource with that name.
+ * @param name
+ * fully qualified resource name, e.g. java/lang/String.class
+ * @return An Enumeration of URLs supplying the resource, or an empty Enumeration if no resource with that name.
* @since 6.0
*/
public Enumeration<URL> getResources(final String name) {
final Vector<URL> results = new Vector<>();
- for (final PathEntry path : paths) {
+ for (final AbstractPathEntry path : paths) {
URL url;
if ((url = path.getResource(name)) != null) {
results.add(url);
@@ -257,11 +283,13 @@ public class ClassPath {
}
/**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suff, e.g. .java
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suff, e.g. .java
* @return class file for the java class
*/
- public ClassFile getClassFile( final String name, final String suffix ) throws IOException {
+ public ClassFile getClassFile(final String name, final String suffix) throws IOException {
ClassFile cf = null;
if (parent != null) {
@@ -281,30 +309,31 @@ public class ClassPath {
private ClassFile getClassFileInternal(final String name, final String suffix) throws IOException {
- for (final PathEntry path : paths) {
- final ClassFile cf = path.getClassFile(name, suffix);
+ for (final AbstractPathEntry path : paths) {
+ final ClassFile cf = path.getClassFile(name, suffix);
- if(cf != null) {
- return cf;
- }
- }
-
- return null;
- }
+ if (cf != null) {
+ return cf;
+ }
+ }
+ return null;
+ }
/**
- * @param name fully qualified class name, e.g. java.lang.String
+ * @param name
+ * fully qualified class name, e.g. java.lang.String
* @return input stream for class
*/
- public ClassFile getClassFile( final String name ) throws IOException {
+ public ClassFile getClassFile(final String name) throws IOException {
return getClassFile(name, ".class");
}
-
/**
- * @param name fully qualified file name, e.g. java/lang/String
- * @param suffix file name ends with suffix, e.g. .java
+ * @param name
+ * fully qualified file name, e.g. java/lang/String
+ * @param suffix
+ * file name ends with suffix, e.g. .java
* @return byte array for file on class path
*/
public byte[] getBytes(final String name, final String suffix) throws IOException {
@@ -324,20 +353,19 @@ public class ClassPath {
}
}
-
/**
* @return byte array for class
*/
- public byte[] getBytes( final String name ) throws IOException {
+ public byte[] getBytes(final String name) throws IOException {
return getBytes(name, ".class");
}
-
/**
- * @param name name of file to search for, e.g. java/lang/String.java
+ * @param name
+ * name of file to search for, e.g. java/lang/String.java
* @return full (canonical) path for file
*/
- public String getPath( String name ) throws IOException {
+ public String getPath(String name) throws IOException {
final int index = name.lastIndexOf('.');
String suffix = "";
if (index > 0) {
@@ -347,58 +375,62 @@ public class ClassPath {
return getPath(name, suffix);
}
-
/**
- * @param name name of file to search for, e.g. java/lang/String
- * @param suffix file name suffix, e.g. .java
+ * @param name
+ * name of file to search for, e.g. java/lang/String
+ * @param suffix
+ * file name suffix, e.g. .java
* @return full (canonical) path for file, if it exists
*/
- public String getPath( final String name, final String suffix ) throws IOException {
+ public String getPath(final String name, final String suffix) throws IOException {
return getClassFile(name, suffix).getPath();
}
- private abstract static class PathEntry {
+ private abstract static class AbstractPathEntry {
+
+ abstract ClassFile getClassFile(String name, String suffix) throws IOException;
- abstract ClassFile getClassFile( String name, String suffix ) throws IOException;
abstract URL getResource(String name);
+
abstract InputStream getResourceAsStream(String name);
}
- /** Contains information about file/ZIP entry of the Java class.
+ /**
+ * Contains information about file/ZIP entry of the Java class.
*/
public interface ClassFile {
- /** @return input stream for class file.
+ /**
+ * @return input stream for class file.
*/
InputStream getInputStream() throws IOException;
-
- /** @return canonical path to class file.
+ /**
+ * @return canonical path to class file.
*/
String getPath();
-
- /** @return base path of found class, i.e. class is contained relative
- * to that path, which may either denote a directory, or zip file
+ /**
+ * @return base path of found class, i.e. class is contained relative to that path, which may either denote a
+ * directory, or zip file
*/
String getBase();
-
- /** @return modification time of class file.
+ /**
+ * @return modification time of class file.
*/
long getTime();
-
- /** @return size of class file.
+ /**
+ * @return size of class file.
*/
long getSize();
}
- private static class Dir extends PathEntry {
+ private static class Dir extends AbstractPathEntry {
private final String dir;
-
Dir(final String d) {
dir = d;
}
@@ -406,29 +438,28 @@ public class ClassPath {
@Override
URL getResource(final String name) {
// Resource specification uses '/' whatever the platform
- final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ final File file = toFile(name);
try {
return file.exists() ? file.toURI().toURL() : null;
} catch (final MalformedURLException e) {
- return null;
+ return null;
}
}
@Override
InputStream getResourceAsStream(final String name) {
// Resource specification uses '/' whatever the platform
- final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ final File file = toFile(name);
try {
- return file.exists() ? new FileInputStream(file) : null;
+ return file.exists() ? new FileInputStream(file) : null;
} catch (final IOException e) {
- return null;
+ return null;
}
}
@Override
- ClassFile getClassFile( final String name, final String suffix ) throws IOException {
- final File file = new File(dir + File.separatorChar
- + name.replace('.', File.separatorChar) + suffix);
+ 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() {
@Override
@@ -436,7 +467,6 @@ public class ClassPath {
return new FileInputStream(file);
}
-
@Override
public String getPath() {
try {
@@ -446,19 +476,16 @@ public class ClassPath {
}
}
-
@Override
public long getTime() {
return file.lastModified();
}
-
@Override
public long getSize() {
return file.length();
}
-
@Override
public String getBase() {
return dir;
@@ -466,6 +493,9 @@ public class ClassPath {
} : null;
}
+ private File toFile(final String name) {
+ return new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ }
@Override
public String toString() {
@@ -473,38 +503,63 @@ public class ClassPath {
}
}
- private static class Zip extends PathEntry {
+ private static class Module extends AbstractZip {
- private final ZipFile zip;
+ Module(final ZipFile zip) {
+ super(zip);
+ }
+
+ @Override
+ protected String toEntryName(final String name, final String suffix) {
+ return "classes/" + packageToFolder(name) + suffix;
+ }
+
+ }
+ private static class Jar extends AbstractZip {
- Zip(final ZipFile z) {
- zip = z;
+ Jar(final ZipFile zip) {
+ super(zip);
+ }
+
+ @Override
+ protected String toEntryName(final String name, final String suffix) {
+ return packageToFolder(name) + suffix;
+ }
+
+ }
+
+ private static abstract class AbstractZip extends AbstractPathEntry {
+
+ private final ZipFile zip;
+
+ AbstractZip(final ZipFile zip) {
+ this.zip = zip;
}
@Override
URL getResource(final String name) {
final ZipEntry entry = zip.getEntry(name);
try {
- return (entry != null) ? new URL("jar:file:" + zip.getName() + "!/" + name) : null;
+ return entry != null ? new URL("jar:file:" + zip.getName() + "!/" + name) : null;
} catch (final MalformedURLException e) {
return null;
- }
+ }
}
@Override
InputStream getResourceAsStream(final String name) {
final ZipEntry entry = zip.getEntry(name);
try {
- return (entry != null) ? zip.getInputStream(entry) : null;
+ return entry != null ? zip.getInputStream(entry) : null;
} catch (final IOException e) {
return null;
}
}
@Override
- ClassFile getClassFile( final String name, final String suffix ) throws IOException {
- final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
+ ClassFile getClassFile(final String name, final String suffix) throws IOException {
+ final ZipEntry entry = zip.getEntry(toEntryName(name, suffix));
if (entry == null) {
return null;
@@ -517,30 +572,38 @@ public class ClassPath {
return zip.getInputStream(entry);
}
-
@Override
public String getPath() {
return entry.toString();
}
-
@Override
public long getTime() {
return entry.getTime();
}
-
@Override
public long getSize() {
return entry.getSize();
}
-
@Override
public String getBase() {
return zip.getName();
}
};
}
+
+ protected abstract String toEntryName(final String name, final String suffix);
+
+ @Override
+ public String toString() {
+ return zip.getName();
+ }
+
+ }
+
+ static String packageToFolder(final String name) {
+ return name.replace('.', '/');
}
}
Added: 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=1836867&view=auto
==============================================================================
--- commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java (added)
+++ commons/proper/bcel/trunk/src/test/java/org/apache/bcel/util/ClassPathTestCase.java Sat Jul 28 05:00:21 2018
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.bcel.util;
+
+import java.io.IOException;
+
+import org.apache.bcel.AbstractTestCase;
+
+public class ClassPathTestCase extends AbstractTestCase {
+
+ public void testGetClassFile() throws IOException {
+ ClassPath.SYSTEM_CLASS_PATH.getClassFile("java.lang.String");
+ }
+}
\ No newline at end of file