src/share/classes/com/sun/tools/jdeps/ClassFileReader.java

Tue, 24 Dec 2013 09:17:37 -0800

author
ksrini
date
Tue, 24 Dec 2013 09:17:37 -0800
changeset 2227
998b10c43157
parent 2139
defadd528513
child 2525
2eb010b6cb22
child 2538
1e39ae45d8ac
permissions
-rw-r--r--

8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com

     1 /*
     2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 package com.sun.tools.jdeps;
    27 import com.sun.tools.classfile.ClassFile;
    28 import com.sun.tools.classfile.ConstantPoolException;
    29 import com.sun.tools.classfile.Dependencies.ClassFileError;
    30 import java.io.*;
    31 import java.nio.file.FileVisitResult;
    32 import java.nio.file.Files;
    33 import java.nio.file.Path;
    34 import java.nio.file.SimpleFileVisitor;
    35 import java.nio.file.attribute.BasicFileAttributes;
    36 import java.util.*;
    37 import java.util.jar.JarEntry;
    38 import java.util.jar.JarFile;
    40 /**
    41  * ClassFileReader reads ClassFile(s) of a given path that can be
    42  * a .class file, a directory, or a JAR file.
    43  */
    44 public class ClassFileReader {
    45     /**
    46      * Returns a ClassFileReader instance of a given path.
    47      */
    48     public static ClassFileReader newInstance(Path path) throws IOException {
    49         if (!Files.exists(path)) {
    50             throw new FileNotFoundException(path.toString());
    51         }
    53         if (Files.isDirectory(path)) {
    54             return new DirectoryReader(path);
    55         } else if (path.getFileName().toString().endsWith(".jar")) {
    56             return new JarFileReader(path);
    57         } else {
    58             return new ClassFileReader(path);
    59         }
    60     }
    62     /**
    63      * Returns a ClassFileReader instance of a given JarFile.
    64      */
    65     public static ClassFileReader newInstance(Path path, JarFile jf) throws IOException {
    66         return new JarFileReader(path, jf);
    67     }
    69     protected final Path path;
    70     protected final String baseFileName;
    71     private ClassFileReader(Path path) {
    72         this.path = path;
    73         this.baseFileName = path.getFileName() != null
    74                                 ? path.getFileName().toString()
    75                                 : path.toString();
    76     }
    78     public String getFileName() {
    79         return baseFileName;
    80     }
    82     /**
    83      * Returns the ClassFile matching the given binary name
    84      * or a fully-qualified class name.
    85      */
    86     public ClassFile getClassFile(String name) throws IOException {
    87         if (name.indexOf('.') > 0) {
    88             int i = name.lastIndexOf('.');
    89             String pathname = name.replace('.', File.separatorChar) + ".class";
    90             if (baseFileName.equals(pathname) ||
    91                     baseFileName.equals(pathname.substring(0, i) + "$" +
    92                                         pathname.substring(i+1, pathname.length()))) {
    93                 return readClassFile(path);
    94             }
    95         } else {
    96             if (baseFileName.equals(name.replace('/', File.separatorChar) + ".class")) {
    97                 return readClassFile(path);
    98             }
    99         }
   100         return null;
   101     }
   103     public Iterable<ClassFile> getClassFiles() throws IOException {
   104         return new Iterable<ClassFile>() {
   105             public Iterator<ClassFile> iterator() {
   106                 return new FileIterator();
   107             }
   108         };
   109     }
   111     protected ClassFile readClassFile(Path p) throws IOException {
   112         InputStream is = null;
   113         try {
   114             is = Files.newInputStream(p);
   115             return ClassFile.read(is);
   116         } catch (ConstantPoolException e) {
   117             throw new ClassFileError(e);
   118         } finally {
   119             if (is != null) {
   120                 is.close();
   121             }
   122         }
   123     }
   125     class FileIterator implements Iterator<ClassFile> {
   126         int count;
   127         FileIterator() {
   128             this.count = 0;
   129         }
   130         public boolean hasNext() {
   131             return count == 0 && baseFileName.endsWith(".class");
   132         }
   134         public ClassFile next() {
   135             if (!hasNext()) {
   136                 throw new NoSuchElementException();
   137             }
   138             try {
   139                 ClassFile cf = readClassFile(path);
   140                 count++;
   141                 return cf;
   142             } catch (IOException e) {
   143                 throw new ClassFileError(e);
   144             }
   145         }
   147         public void remove() {
   148             throw new UnsupportedOperationException("Not supported yet.");
   149         }
   150     }
   152     public String toString() {
   153         return path.toString();
   154     }
   156     private static class DirectoryReader extends ClassFileReader {
   157         DirectoryReader(Path path) throws IOException {
   158             super(path);
   159         }
   161         public ClassFile getClassFile(String name) throws IOException {
   162             if (name.indexOf('.') > 0) {
   163                 int i = name.lastIndexOf('.');
   164                 String pathname = name.replace('.', File.separatorChar) + ".class";
   165                 Path p = path.resolve(pathname);
   166                 if (!Files.exists(p)) {
   167                     p = path.resolve(pathname.substring(0, i) + "$" +
   168                                      pathname.substring(i+1, pathname.length()));
   169                 }
   170                 if (Files.exists(p)) {
   171                     return readClassFile(p);
   172                 }
   173             } else {
   174                 Path p = path.resolve(name + ".class");
   175                 if (Files.exists(p)) {
   176                     return readClassFile(p);
   177                 }
   178             }
   179             return null;
   180         }
   182         public Iterable<ClassFile> getClassFiles() throws IOException {
   183             final Iterator<ClassFile> iter = new DirectoryIterator();
   184             return new Iterable<ClassFile>() {
   185                 public Iterator<ClassFile> iterator() {
   186                     return iter;
   187                 }
   188             };
   189         }
   191         private List<Path> walkTree(Path dir) throws IOException {
   192             final List<Path> files = new ArrayList<Path>();
   193             Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
   194                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
   195                         throws IOException {
   196                     if (file.getFileName().toString().endsWith(".class")) {
   197                         files.add(file);
   198                     }
   199                     return FileVisitResult.CONTINUE;
   200                 }
   201             });
   202             return files;
   203         }
   205         class DirectoryIterator implements Iterator<ClassFile> {
   206             private List<Path> entries;
   207             private int index = 0;
   208             DirectoryIterator() throws IOException {
   209                 entries = walkTree(path);
   210                 index = 0;
   211             }
   213             public boolean hasNext() {
   214                 return index != entries.size();
   215             }
   217             public ClassFile next() {
   218                 if (!hasNext()) {
   219                     throw new NoSuchElementException();
   220                 }
   221                 Path path = entries.get(index++);
   222                 try {
   223                     return readClassFile(path);
   224                 } catch (IOException e) {
   225                     throw new ClassFileError(e);
   226                 }
   227             }
   229             public void remove() {
   230                 throw new UnsupportedOperationException("Not supported yet.");
   231             }
   232         }
   233     }
   235     private static class JarFileReader extends ClassFileReader {
   236         final JarFile jarfile;
   237         JarFileReader(Path path) throws IOException {
   238             this(path, new JarFile(path.toFile()));
   239         }
   240         JarFileReader(Path path, JarFile jf) throws IOException {
   241             super(path);
   242             this.jarfile = jf;
   243         }
   245         public ClassFile getClassFile(String name) throws IOException {
   246             if (name.indexOf('.') > 0) {
   247                 int i = name.lastIndexOf('.');
   248                 String entryName = name.replace('.', '/') + ".class";
   249                 JarEntry e = jarfile.getJarEntry(entryName);
   250                 if (e == null) {
   251                     e = jarfile.getJarEntry(entryName.substring(0, i) + "$"
   252                             + entryName.substring(i + 1, entryName.length()));
   253                 }
   254                 if (e != null) {
   255                     return readClassFile(e);
   256                 }
   257             } else {
   258                 JarEntry e = jarfile.getJarEntry(name + ".class");
   259                 if (e != null) {
   260                     return readClassFile(e);
   261                 }
   262             }
   263             return null;
   264         }
   266         private ClassFile readClassFile(JarEntry e) throws IOException {
   267             InputStream is = null;
   268             try {
   269                 is = jarfile.getInputStream(e);
   270                 return ClassFile.read(is);
   271             } catch (ConstantPoolException ex) {
   272                 throw new ClassFileError(ex);
   273             } finally {
   274                 if (is != null)
   275                     is.close();
   276             }
   277         }
   279         public Iterable<ClassFile> getClassFiles() throws IOException {
   280             final Iterator<ClassFile> iter = new JarFileIterator();
   281             return new Iterable<ClassFile>() {
   282                 public Iterator<ClassFile> iterator() {
   283                     return iter;
   284                 }
   285             };
   286         }
   288         class JarFileIterator implements Iterator<ClassFile> {
   289             private Enumeration<JarEntry> entries;
   290             private JarEntry nextEntry;
   291             JarFileIterator() {
   292                 this.entries = jarfile.entries();
   293                 while (entries.hasMoreElements()) {
   294                     JarEntry e = entries.nextElement();
   295                     String name = e.getName();
   296                     if (name.endsWith(".class")) {
   297                         this.nextEntry = e;
   298                         break;
   299                     }
   300                 }
   301             }
   303             public boolean hasNext() {
   304                 return nextEntry != null;
   305             }
   307             public ClassFile next() {
   308                 if (!hasNext()) {
   309                     throw new NoSuchElementException();
   310                 }
   312                 ClassFile cf;
   313                 try {
   314                     cf = readClassFile(nextEntry);
   315                 } catch (IOException ex) {
   316                     throw new ClassFileError(ex);
   317                 }
   318                 JarEntry entry = nextEntry;
   319                 nextEntry = null;
   320                 while (entries.hasMoreElements()) {
   321                     JarEntry e = entries.nextElement();
   322                     String name = e.getName();
   323                     if (name.endsWith(".class")) {
   324                         nextEntry = e;
   325                         break;
   326                     }
   327                 }
   328                 return cf;
   329             }
   331             public void remove() {
   332                 throw new UnsupportedOperationException("Not supported yet.");
   333             }
   334         }
   335     }
   336 }

mercurial