Wed, 05 Aug 2009 08:38:18 -0700
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 +