6729471: javap should accept class files on the command line

Wed, 05 Aug 2009 08:38:18 -0700

author
jjg
date
Wed, 05 Aug 2009 08:38:18 -0700
changeset 350
526de25e0b28
parent 349
bc0b1f404c40
child 351
b5ab848ba68f
child 352
160d7a994e69
child 363
21f1d2462c7c

6729471: javap should accept class files on the command line
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/javap/JavapTask.java file | annotate | diff | comparison | revisions
test/tools/javap/T6729471.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javap/JavapTask.java	Wed Aug 05 07:43:50 2009 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javap/JavapTask.java	Wed Aug 05 08:38:18 2009 -0700
     1.3 @@ -32,8 +32,10 @@
     1.4  import java.io.IOException;
     1.5  import java.io.OutputStream;
     1.6  import java.io.PrintWriter;
     1.7 +import java.io.Reader;
     1.8  import java.io.StringWriter;
     1.9  import java.io.Writer;
    1.10 +import java.net.URI;
    1.11  import java.security.DigestInputStream;
    1.12  import java.security.MessageDigest;
    1.13  import java.security.NoSuchAlgorithmException;
    1.14 @@ -49,6 +51,8 @@
    1.15  import java.util.MissingResourceException;
    1.16  import java.util.ResourceBundle;
    1.17  
    1.18 +import javax.lang.model.element.Modifier;
    1.19 +import javax.lang.model.element.NestingKind;
    1.20  import javax.tools.Diagnostic;
    1.21  import javax.tools.DiagnosticListener;
    1.22  import javax.tools.JavaFileManager;
    1.23 @@ -57,6 +61,9 @@
    1.24  import javax.tools.StandardLocation;
    1.25  
    1.26  import com.sun.tools.classfile.*;
    1.27 +import java.net.URISyntaxException;
    1.28 +import java.net.URL;
    1.29 +import java.net.URLConnection;
    1.30  
    1.31  /**
    1.32   *  "Main" class for javap, normally accessed from the command line
    1.33 @@ -607,30 +614,10 @@
    1.34  
    1.35      protected boolean writeClass(ClassWriter classWriter, String className)
    1.36              throws IOException, ConstantPoolException {
    1.37 -        JavaFileObject fo;
    1.38 -        if (className.endsWith(".class")) {
    1.39 -            if (fileManager instanceof StandardJavaFileManager) {
    1.40 -                StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
    1.41 -                fo = sfm.getJavaFileObjects(className).iterator().next();
    1.42 -            } else {
    1.43 -                reportError("err.not.standard.file.manager", className);
    1.44 -                return false;
    1.45 -            }
    1.46 -        } else {
    1.47 -            fo = getClassFileObject(className);
    1.48 -            if (fo == null) {
    1.49 -                // see if it is an inner class, by replacing dots to $, starting from the right
    1.50 -                String cn = className;
    1.51 -                int lastDot;
    1.52 -                while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
    1.53 -                    cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
    1.54 -                    fo = getClassFileObject(cn);
    1.55 -                }
    1.56 -            }
    1.57 -            if (fo == null) {
    1.58 -                reportError("err.class.not.found", className);
    1.59 -                return false;
    1.60 -            }
    1.61 +        JavaFileObject fo = open(className);
    1.62 +        if (fo == null) {
    1.63 +            reportError("err.class.not.found", className);
    1.64 +            return false;
    1.65          }
    1.66  
    1.67          ClassFileInfo cfInfo = read(fo);
    1.68 @@ -675,6 +662,102 @@
    1.69          return true;
    1.70      }
    1.71  
    1.72 +    protected JavaFileObject open(String className) throws IOException {
    1.73 +        // for compatibility, first see if it is a class name
    1.74 +        JavaFileObject fo = getClassFileObject(className);
    1.75 +        if (fo != null)
    1.76 +            return fo;
    1.77 +
    1.78 +        // see if it is an inner class, by replacing dots to $, starting from the right
    1.79 +        String cn = className;
    1.80 +        int lastDot;
    1.81 +        while ((lastDot = cn.lastIndexOf(".")) != -1) {
    1.82 +            cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
    1.83 +            fo = getClassFileObject(cn);
    1.84 +            if (fo != null)
    1.85 +                return fo;
    1.86 +        }
    1.87 +
    1.88 +        if (!className.endsWith(".class"))
    1.89 +            return null;
    1.90 +
    1.91 +        if (fileManager instanceof StandardJavaFileManager) {
    1.92 +            StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
    1.93 +            fo = sfm.getJavaFileObjects(className).iterator().next();
    1.94 +            if (fo != null && fo.getLastModified() != 0) {
    1.95 +                return fo;
    1.96 +            }
    1.97 +        }
    1.98 +
    1.99 +        // see if it is a URL, and if so, wrap it in just enough of a JavaFileObject
   1.100 +        // to suit javap's needs
   1.101 +        if (className.matches("^[A-Za-z]+:.*")) {
   1.102 +            try {
   1.103 +                final URI uri = new URI(className);
   1.104 +                final URL url = uri.toURL();
   1.105 +                final URLConnection conn = url.openConnection();
   1.106 +                return new JavaFileObject() {
   1.107 +                    public Kind getKind() {
   1.108 +                        return JavaFileObject.Kind.CLASS;
   1.109 +                    }
   1.110 +
   1.111 +                    public boolean isNameCompatible(String simpleName, Kind kind) {
   1.112 +                        throw new UnsupportedOperationException();
   1.113 +                    }
   1.114 +
   1.115 +                    public NestingKind getNestingKind() {
   1.116 +                        throw new UnsupportedOperationException();
   1.117 +                    }
   1.118 +
   1.119 +                    public Modifier getAccessLevel() {
   1.120 +                        throw new UnsupportedOperationException();
   1.121 +                    }
   1.122 +
   1.123 +                    public URI toUri() {
   1.124 +                        return uri;
   1.125 +                    }
   1.126 +
   1.127 +                    public String getName() {
   1.128 +                        return url.toString();
   1.129 +                    }
   1.130 +
   1.131 +                    public InputStream openInputStream() throws IOException {
   1.132 +                        return conn.getInputStream();
   1.133 +                    }
   1.134 +
   1.135 +                    public OutputStream openOutputStream() throws IOException {
   1.136 +                        throw new UnsupportedOperationException();
   1.137 +                    }
   1.138 +
   1.139 +                    public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   1.140 +                        throw new UnsupportedOperationException();
   1.141 +                    }
   1.142 +
   1.143 +                    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   1.144 +                        throw new UnsupportedOperationException();
   1.145 +                    }
   1.146 +
   1.147 +                    public Writer openWriter() throws IOException {
   1.148 +                        throw new UnsupportedOperationException();
   1.149 +                    }
   1.150 +
   1.151 +                    public long getLastModified() {
   1.152 +                        return conn.getLastModified();
   1.153 +                    }
   1.154 +
   1.155 +                    public boolean delete() {
   1.156 +                        throw new UnsupportedOperationException();
   1.157 +                    }
   1.158 +
   1.159 +                };
   1.160 +            } catch (URISyntaxException ignore) {
   1.161 +            } catch (IOException ignore) {
   1.162 +            }
   1.163 +        }
   1.164 +
   1.165 +        return null;
   1.166 +    }
   1.167 +
   1.168      public static class ClassFileInfo {
   1.169          ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
   1.170              this.fo = fo;
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/test/tools/javap/T6729471.java	Wed Aug 05 08:38:18 2009 -0700
     2.3 @@ -0,0 +1,109 @@
     2.4 +/*
     2.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.
    2.11 + *
    2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.15 + * version 2 for more details (a copy is included in the LICENSE file that
    2.16 + * accompanied this code).
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License version
    2.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.21 + *
    2.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    2.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    2.24 + * have any questions.
    2.25 + */
    2.26 +
    2.27 +
    2.28 +/*
    2.29 + * @test
    2.30 + * @bug 6729471
    2.31 + * @summary javap does not output inner interfaces of an interface
    2.32 + */
    2.33 +
    2.34 +import java.io.*;
    2.35 +import java.util.*;
    2.36 +
    2.37 +public class T6729471
    2.38 +{
    2.39 +    public static void main(String... args) {
    2.40 +        new T6729471().run();
    2.41 +    }
    2.42 +
    2.43 +    void run() {
    2.44 +        // simple class
    2.45 +        verify("java.util.Map",
    2.46 +                "public abstract boolean containsKey(java.lang.Object)");
    2.47 +
    2.48 +        // inner class
    2.49 +        verify("java.util.Map.Entry",
    2.50 +                "public abstract K getKey()");
    2.51 +
    2.52 +        // file name
    2.53 +        verify("../classes/tools/javap/T6729471.class",
    2.54 +                "public static void main(java.lang.String...)");
    2.55 +
    2.56 +        // file url
    2.57 +        verify("file:../classes/tools/javap/T6729471.class",
    2.58 +                "public static void main(java.lang.String...)");
    2.59 +
    2.60 +        // jar url: rt.jar
    2.61 +        File java_home = new File(System.getProperty("java.home"));
    2.62 +        if (java_home.getName().equals("jre"))
    2.63 +            java_home = java_home.getParentFile();
    2.64 +        File rt_jar = new File(new File(new File(java_home, "jre"), "lib"), "rt.jar");
    2.65 +        verify("jar:file:" + rt_jar + "!/java/util/Map.class",
    2.66 +                "public abstract boolean containsKey(java.lang.Object)");
    2.67 +
    2.68 +        // jar url: ct.sym, if it exists
    2.69 +        File ct_sym = new File(new File(java_home, "lib"), "ct.sym");
    2.70 +        if (ct_sym.exists()) {
    2.71 +            verify("jar:file:" + ct_sym + "!/META-INF/sym/rt.jar/java/util/Map.class",
    2.72 +                "public abstract boolean containsKey(java.lang.Object)");
    2.73 +        } else
    2.74 +            System.err.println("warning: ct.sym not found");
    2.75 +
    2.76 +        if (errors > 0)
    2.77 +            throw new Error(errors + " found.");
    2.78 +    }
    2.79 +
    2.80 +    void verify(String className, String... expects) {
    2.81 +        String output = javap(className);
    2.82 +        for (String expect: expects) {
    2.83 +            if (output.indexOf(expect)< 0)
    2.84 +                error(expect + " not found");
    2.85 +        }
    2.86 +    }
    2.87 +
    2.88 +    void error(String msg) {
    2.89 +        System.err.println(msg);
    2.90 +        errors++;
    2.91 +    }
    2.92 +
    2.93 +    int errors;
    2.94 +
    2.95 +    String javap(String className) {
    2.96 +        String testClasses = System.getProperty("test.classes", ".");
    2.97 +        StringWriter sw = new StringWriter();
    2.98 +        PrintWriter out = new PrintWriter(sw);
    2.99 +        String[] args = { "-classpath", testClasses, className };
   2.100 +        int rc = com.sun.tools.javap.Main.run(args, out);
   2.101 +        out.close();
   2.102 +        String output = sw.toString();
   2.103 +        System.out.println("class " + className);
   2.104 +        System.out.println(output);
   2.105 +        if (rc != 0)
   2.106 +            throw new Error("javap failed. rc=" + rc);
   2.107 +        if (output.indexOf("Error:") != -1)
   2.108 +            throw new Error("javap reported error.");
   2.109 +        return output;
   2.110 +    }
   2.111 +}
   2.112 +

mercurial