Author: ggregory Date: Sat Jul 28 05:00:45 2018 New Revision: 1836868 URL: http://svn.apache.org/viewvc?rev=1836868&view=rev Log: [BCEL-304] ClassPath.getClassFile does not work with Java 9 and higher. Sort.
Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/util/ClassPath.java 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=1836868&r1=1836867&r2=1836868&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:45 2018 @@ -41,119 +41,241 @@ import java.util.zip.ZipFile; */ public class ClassPath { - public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(getClassPath()); + private abstract static class AbstractPathEntry { - private static final FilenameFilter ARCHIVE_FILTER = new FilenameFilter() { + abstract ClassFile getClassFile(String name, String suffix) throws IOException; + + abstract URL getResource(String name); + + abstract InputStream getResourceAsStream(String name); + } + + private static abstract class AbstractZip extends AbstractPathEntry { + + private final ZipFile zip; + + AbstractZip(final ZipFile zip) { + this.zip = zip; + } @Override - public boolean accept(final File dir, String name) { - name = name.toLowerCase(Locale.ENGLISH); - return name.endsWith(".zip") || name.endsWith(".jar"); + ClassFile getClassFile(final String name, final String suffix) throws IOException { + final ZipEntry entry = zip.getEntry(toEntryName(name, suffix)); + + if (entry == null) { + return null; + } + + return new ClassFile() { + + @Override + public String getBase() { + return zip.getName(); + } + + @Override + public InputStream getInputStream() throws IOException { + return zip.getInputStream(entry); + } + + @Override + public String getPath() { + return entry.toString(); + } + + @Override + public long getSize() { + return entry.getSize(); + } + + @Override + public long getTime() { + return entry.getTime(); + } + }; } - }; - private static final FilenameFilter MODULES_FILTER = new FilenameFilter() { + @Override + URL getResource(final String name) { + final ZipEntry entry = zip.getEntry(name); + try { + return entry != null ? new URL("jar:file:" + zip.getName() + "!/" + name) : null; + } catch (final MalformedURLException e) { + return null; + } + } @Override - public boolean accept(final File dir, String name) { - name = name.toLowerCase(Locale.ENGLISH); - return name.endsWith(".jmod"); + InputStream getResourceAsStream(final String name) { + final ZipEntry entry = zip.getEntry(name); + try { + return entry != null ? zip.getInputStream(entry) : null; + } catch (final IOException e) { + return null; + } } - }; - private final AbstractPathEntry[] paths; - private final String classPath; - private ClassPath parent; + protected abstract String toEntryName(final String name, final String suffix); + + @Override + public String toString() { + return zip.getName(); + } - public ClassPath(final ClassPath parent, final String class_path) { - this(class_path); - this.parent = parent; } /** - * Search for classes in given path. - * - * @param class_path + * Contains information about file/ZIP entry of the Java class. */ - public ClassPath(final String class_path) { - 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()) { - final File file = new File(path); - try { - 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 Jar(new ZipFile(file))); - } - } - } catch (final IOException e) { - if (path.endsWith(".zip") || path.endsWith(".jar")) { - System.err.println("CLASSPATH component " + file + ": " + e); + public interface ClassFile { + + /** + * @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 input stream for class file. + */ + InputStream getInputStream() throws IOException; + + /** + * @return canonical path to class file. + */ + String getPath(); + + /** + * @return size of class file. + */ + long getSize(); + + /** + * @return modification time of class file. + */ + long getTime(); + } + + private static class Dir extends AbstractPathEntry { + + private final String dir; + + Dir(final String d) { + dir = d; + } + + @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() { + + @Override + public String getBase() { + return dir; + } + + @Override + public InputStream getInputStream() throws IOException { + return new FileInputStream(file); + } + + @Override + public String getPath() { + try { + return file.getCanonicalPath(); + } catch (final IOException e) { + return null; } } + + @Override + public long getSize() { + return file.length(); + } + + @Override + public long getTime() { + return file.lastModified(); + } + } : null; + } + + @Override + URL getResource(final String name) { + // Resource specification uses '/' whatever the platform + final File file = toFile(name); + try { + return file.exists() ? file.toURI().toURL() : null; + } catch (final MalformedURLException e) { + return null; } } - paths = new AbstractPathEntry[list.size()]; - list.toArray(paths); - } - /** - * Search for classes in CLASSPATH. - * - * @deprecated Use SYSTEM_CLASS_PATH constant - */ - @Deprecated - public ClassPath() { - this(getClassPath()); - } + @Override + InputStream getResourceAsStream(final String name) { + // Resource specification uses '/' whatever the platform + final File file = toFile(name); + try { + return file.exists() ? new FileInputStream(file) : null; + } catch (final IOException e) { + return null; + } + } - /** - * @return used class path string - */ - @Override - public String toString() { - if (parent != null) { - return parent + File.pathSeparator + classPath; + private File toFile(final String name) { + return new File(dir + File.separatorChar + name.replace('/', File.separatorChar)); } - return classPath; - } - @Override - public int hashCode() { - if (parent != null) { - return classPath.hashCode() + parent.hashCode(); + @Override + public String toString() { + return dir; } - return classPath.hashCode(); } + private static class Jar extends AbstractZip { - @Override - public boolean equals(final Object o) { - if (o instanceof ClassPath) { - final ClassPath cp = (ClassPath) o; - return classPath.equals(cp.toString()); + Jar(final ZipFile zip) { + super(zip); } - return false; + + @Override + protected String toEntryName(final String name, final String suffix) { + return packageToFolder(name) + suffix; + } + } + private static class Module extends AbstractZip { - 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 File file = new File(name); - if (file.exists()) { - list.add(name); - } - } + Module(final ZipFile zip) { + super(zip); + } + + @Override + protected String toEntryName(final String name, final String suffix) { + return "classes/" + packageToFolder(name) + suffix; } + } + private static final FilenameFilter ARCHIVE_FILTER = new FilenameFilter() { + + @Override + public boolean accept(final File dir, String name) { + name = name.toLowerCase(Locale.ENGLISH); + return name.endsWith(".zip") || name.endsWith(".jar"); + } + }; + + 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"); + } + }; + + public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(getClassPath()); + /** * Checks for class path components in the following properties: "java.class.path", "sun.boot.class.path", * "java.ext.dirs" @@ -202,84 +324,124 @@ public class ClassPath { return buf.toString().intern(); } + 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 File file = new File(name); + if (file.exists()) { + list.add(name); + } + } + } + } + + static String packageToFolder(final String name) { + return name.replace('.', '/'); + } + + private final String classPath; + + private ClassPath parent; + + private final AbstractPathEntry[] paths; + /** - * @param name - * fully qualified class name, e.g. java.lang.String - * @return input stream for class + * Search for classes in CLASSPATH. + * + * @deprecated Use SYSTEM_CLASS_PATH constant */ - public InputStream getInputStream(final String name) throws IOException { - return getInputStream(packageToFolder(name), ".class"); + @Deprecated + public ClassPath() { + this(getClassPath()); + } + + public ClassPath(final ClassPath parent, final String class_path) { + this(class_path); + this.parent = parent; } /** - * Return stream for class or resource on CLASSPATH. + * Search for classes in given path. * - * @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 + * @param class_path */ - public InputStream getInputStream(final String name, final String suffix) throws IOException { - InputStream is = null; - try { - is = getClass().getClassLoader().getResourceAsStream(name + suffix); // may return null - } catch (final Exception e) { - // ignored + public ClassPath(final String class_path) { + 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()) { + final File file = new File(path); + try { + 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 Jar(new ZipFile(file))); + } + } + } catch (final IOException e) { + if (path.endsWith(".zip") || path.endsWith(".jar")) { + System.err.println("CLASSPATH component " + file + ": " + e); + } + } + } } - if (is != null) { - return is; + paths = new AbstractPathEntry[list.size()]; + list.toArray(paths); + } + + @Override + public boolean equals(final Object o) { + if (o instanceof ClassPath) { + final ClassPath cp = (ClassPath) o; + return classPath.equals(cp.toString()); } - return getClassFile(name, suffix).getInputStream(); + return false; } /** - * @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 + * @return byte array for class */ - public InputStream getResourceAsStream(final String name) { - for (final AbstractPathEntry path : paths) { - InputStream is; - if ((is = path.getResourceAsStream(name)) != null) { - return is; - } - } - return null; + public byte[] getBytes(final String name) throws IOException { + return getBytes(name, ".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 + * 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 URL getResource(final String name) { - for (final AbstractPathEntry path : paths) { - URL url; - if ((url = path.getResource(name)) != null) { - return url; + public byte[] getBytes(final String name, final String suffix) throws IOException { + DataInputStream dis = null; + try (InputStream is = getInputStream(name, suffix)) { + if (is == null) { + throw new IOException("Couldn't find: " + name + suffix); + } + dis = new DataInputStream(is); + final byte[] bytes = new byte[is.available()]; + dis.readFully(bytes); + return bytes; + } finally { + if (dis != null) { + dis.close(); } } - return null; } /** * @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 + * fully qualified class name, e.g. java.lang.String + * @return input stream for class */ - public Enumeration<URL> getResources(final String name) { - final Vector<URL> results = new Vector<>(); - for (final AbstractPathEntry path : paths) { - URL url; - if ((url = path.getResource(name)) != null) { - results.add(url); - } - } - return results.elements(); + public ClassFile getClassFile(final String name) throws IOException { + return getClassFile(name, ".class"); } /** @@ -325,39 +487,30 @@ public class ClassPath { * fully qualified class name, e.g. java.lang.String * @return input stream for class */ - public ClassFile getClassFile(final String name) throws IOException { - return getClassFile(name, ".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 suffix, e.g. .java - * @return byte array for file on class path + * file name ends with suff, e.g. .java + * @return input stream for file on class path */ - public byte[] getBytes(final String name, final String suffix) throws IOException { - DataInputStream dis = null; - try (InputStream is = getInputStream(name, suffix)) { - if (is == null) { - throw new IOException("Couldn't find: " + name + suffix); - } - dis = new DataInputStream(is); - final byte[] bytes = new byte[is.available()]; - dis.readFully(bytes); - return bytes; - } finally { - if (dis != null) { - dis.close(); - } + public InputStream getInputStream(final String name, final String suffix) throws IOException { + InputStream is = null; + try { + is = getClass().getClassLoader().getResourceAsStream(name + suffix); // may return null + } catch (final Exception e) { + // ignored } - } - - /** - * @return byte array for class - */ - public byte[] getBytes(final String name) throws IOException { - return getBytes(name, ".class"); + if (is != null) { + return is; + } + return getClassFile(name, suffix).getInputStream(); } /** @@ -386,224 +539,71 @@ public class ClassPath { return getClassFile(name, suffix).getPath(); } - private abstract static class AbstractPathEntry { - - 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. + * @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 interface ClassFile { - - /** - * @return input stream for class file. - */ - InputStream getInputStream() throws IOException; - - /** - * @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 - */ - String getBase(); - - /** - * @return modification time of class file. - */ - long getTime(); - - /** - * @return size of class file. - */ - long getSize(); - } - - private static class Dir extends AbstractPathEntry { - - private final String dir; - - Dir(final String d) { - dir = d; - } - - @Override - URL getResource(final String name) { - // Resource specification uses '/' whatever the platform - final File file = toFile(name); - try { - return file.exists() ? file.toURI().toURL() : null; - } catch (final MalformedURLException e) { - return null; + public URL getResource(final String name) { + for (final AbstractPathEntry path : paths) { + URL url; + if ((url = path.getResource(name)) != null) { + return url; } } + return null; + } - @Override - InputStream getResourceAsStream(final String name) { - // Resource specification uses '/' whatever the platform - final File file = toFile(name); - try { - return file.exists() ? new FileInputStream(file) : null; - } catch (final IOException e) { - return null; + /** + * @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 AbstractPathEntry path : paths) { + InputStream is; + if ((is = path.getResourceAsStream(name)) != null) { + return is; } } - - @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() { - - @Override - public InputStream getInputStream() throws IOException { - return new FileInputStream(file); - } - - @Override - public String getPath() { - try { - return file.getCanonicalPath(); - } catch (final IOException e) { - return null; - } - } - - @Override - public long getTime() { - return file.lastModified(); - } - - @Override - public long getSize() { - return file.length(); - } - - @Override - public String getBase() { - return dir; - } - } : null; - } - - private File toFile(final String name) { - return new File(dir + File.separatorChar + name.replace('/', File.separatorChar)); - } - - @Override - public String toString() { - return dir; - } + return null; } - private static class Module extends AbstractZip { - - Module(final ZipFile zip) { - super(zip); - } - - @Override - protected String toEntryName(final String name, final String suffix) { - return "classes/" + packageToFolder(name) + suffix; + /** + * @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 AbstractPathEntry path : paths) { + URL url; + if ((url = path.getResource(name)) != null) { + results.add(url); + } } - + return results.elements(); } - private static class Jar extends AbstractZip { - - Jar(final ZipFile zip) { - super(zip); - } - - @Override - protected String toEntryName(final String name, final String suffix) { - return packageToFolder(name) + suffix; + @Override + public int hashCode() { + if (parent != null) { + return classPath.hashCode() + parent.hashCode(); } - + return classPath.hashCode(); } - 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; - } 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; - } catch (final IOException e) { - return null; - } - } - - @Override - ClassFile getClassFile(final String name, final String suffix) throws IOException { - final ZipEntry entry = zip.getEntry(toEntryName(name, suffix)); - - if (entry == null) { - return null; - } - - return new ClassFile() { - - @Override - public InputStream getInputStream() throws IOException { - 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(); + /** + * @return used class path string + */ + @Override + public String toString() { + if (parent != null) { + return parent + File.pathSeparator + classPath; } - - } - - static String packageToFolder(final String name) { - return name.replace('.', '/'); + return classPath; } }