src/share/classes/com/sun/tools/javap/JavapTask.java

Tue, 19 May 2009 11:50:54 -0700

author
jjg
date
Tue, 19 May 2009 11:50:54 -0700
changeset 283
cd0630109de5
parent 90
6be961ee2290
child 291
47cf04bb80c9
permissions
-rw-r--r--

6824493: experimental support for additional info for instructions
Reviewed-by: mcimadamore

jjg@46 1 /*
xdono@54 2 * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
jjg@46 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@46 4 *
jjg@46 5 * This code is free software; you can redistribute it and/or modify it
jjg@46 6 * under the terms of the GNU General Public License version 2 only, as
jjg@46 7 * published by the Free Software Foundation. Sun designates this
jjg@46 8 * particular file as subject to the "Classpath" exception as provided
jjg@46 9 * by Sun in the LICENSE file that accompanied this code.
jjg@46 10 *
jjg@46 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@46 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@46 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@46 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@46 15 * accompanied this code).
jjg@46 16 *
jjg@46 17 * You should have received a copy of the GNU General Public License version
jjg@46 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@90 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@46 20 *
jjg@46 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
jjg@46 22 * CA 95054 USA or visit www.sun.com if you need additional information or
jjg@46 23 * have any questions.
jjg@46 24 */
jjg@46 25
jjg@46 26 package com.sun.tools.javap;
jjg@46 27
jjg@46 28 import java.io.EOFException;
jjg@46 29 import java.io.FileNotFoundException;
jjg@88 30 import java.io.FilterInputStream;
jjg@88 31 import java.io.InputStream;
jjg@46 32 import java.io.IOException;
jjg@46 33 import java.io.OutputStream;
jjg@46 34 import java.io.PrintWriter;
jjg@46 35 import java.io.StringWriter;
jjg@46 36 import java.io.Writer;
jjg@88 37 import java.security.DigestInputStream;
jjg@88 38 import java.security.MessageDigest;
jjg@46 39 import java.text.MessageFormat;
jjg@46 40 import java.util.ArrayList;
jjg@46 41 import java.util.Arrays;
jjg@283 42 import java.util.EnumSet;
jjg@46 43 import java.util.HashMap;
jjg@46 44 import java.util.Iterator;
jjg@46 45 import java.util.List;
jjg@46 46 import java.util.Locale;
jjg@46 47 import java.util.Map;
jjg@46 48 import java.util.MissingResourceException;
jjg@46 49 import java.util.ResourceBundle;
jjg@46 50
jjg@46 51 import javax.tools.Diagnostic;
jjg@46 52 import javax.tools.DiagnosticListener;
jjg@46 53 import javax.tools.JavaFileManager;
jjg@46 54 import javax.tools.JavaFileObject;
jjg@46 55 import javax.tools.StandardJavaFileManager;
jjg@46 56 import javax.tools.StandardLocation;
jjg@46 57
jjg@46 58 import com.sun.tools.classfile.*;
jjg@46 59
jjg@46 60 /**
jjg@46 61 * "Main" class for javap, normally accessed from the command line
jjg@46 62 * via Main, or from JSR199 via DisassemblerTool.
jjg@46 63 *
jjg@46 64 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
jjg@46 65 * you write code that depends on this, you do so at your own risk.
jjg@46 66 * This code and its internal interfaces are subject to change or
jjg@46 67 * deletion without notice.</b>
jjg@46 68 */
jjg@283 69 public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
jjg@46 70 public class BadArgs extends Exception {
jjg@46 71 static final long serialVersionUID = 8765093759964640721L;
jjg@46 72 BadArgs(String key, Object... args) {
jjg@46 73 super(JavapTask.this.getMessage(key, args));
jjg@46 74 this.key = key;
jjg@46 75 this.args = args;
jjg@46 76 }
jjg@46 77
jjg@46 78 BadArgs showUsage(boolean b) {
jjg@46 79 showUsage = b;
jjg@46 80 return this;
jjg@46 81 }
jjg@46 82
jjg@46 83 final String key;
jjg@46 84 final Object[] args;
jjg@46 85 boolean showUsage;
jjg@46 86 }
jjg@46 87
jjg@46 88 static abstract class Option {
jjg@46 89 Option(boolean hasArg, String... aliases) {
jjg@46 90 this.hasArg = hasArg;
jjg@46 91 this.aliases = aliases;
jjg@46 92 }
jjg@46 93
jjg@46 94 boolean matches(String opt) {
jjg@46 95 for (String a: aliases) {
jjg@46 96 if (a.equals(opt))
jjg@46 97 return true;
jjg@46 98 }
jjg@46 99 return false;
jjg@46 100 }
jjg@46 101
jjg@46 102 boolean ignoreRest() {
jjg@46 103 return false;
jjg@46 104 }
jjg@46 105
jjg@46 106 abstract void process(JavapTask task, String opt, String arg) throws BadArgs;
jjg@46 107
jjg@46 108 final boolean hasArg;
jjg@46 109 final String[] aliases;
jjg@46 110 }
jjg@46 111
jjg@46 112 static Option[] recognizedOptions = {
jjg@46 113
jjg@46 114 new Option(false, "-help", "--help", "-?") {
jjg@46 115 void process(JavapTask task, String opt, String arg) {
jjg@46 116 task.options.help = true;
jjg@46 117 }
jjg@46 118 },
jjg@46 119
jjg@46 120 new Option(false, "-version") {
jjg@46 121 void process(JavapTask task, String opt, String arg) {
jjg@46 122 task.options.version = true;
jjg@46 123 }
jjg@46 124 },
jjg@46 125
jjg@46 126 new Option(false, "-fullversion") {
jjg@46 127 void process(JavapTask task, String opt, String arg) {
jjg@46 128 task.options.fullVersion = true;
jjg@46 129 }
jjg@46 130 },
jjg@46 131
jjg@46 132 new Option(false, "-v", "-verbose", "-all") {
jjg@46 133 void process(JavapTask task, String opt, String arg) {
jjg@46 134 task.options.verbose = true;
jjg@46 135 task.options.showFlags = true;
jjg@46 136 task.options.showAllAttrs = true;
jjg@46 137 }
jjg@46 138 },
jjg@46 139
jjg@46 140 new Option(false, "-l") {
jjg@46 141 void process(JavapTask task, String opt, String arg) {
jjg@46 142 task.options.showLineAndLocalVariableTables = true;
jjg@46 143 }
jjg@46 144 },
jjg@46 145
jjg@46 146 new Option(false, "-public") {
jjg@46 147 void process(JavapTask task, String opt, String arg) {
jjg@68 148 task.options.accessOptions.add(opt);
jjg@46 149 task.options.showAccess = AccessFlags.ACC_PUBLIC;
jjg@46 150 }
jjg@46 151 },
jjg@46 152
jjg@46 153 new Option(false, "-protected") {
jjg@46 154 void process(JavapTask task, String opt, String arg) {
jjg@68 155 task.options.accessOptions.add(opt);
jjg@46 156 task.options.showAccess = AccessFlags.ACC_PROTECTED;
jjg@46 157 }
jjg@46 158 },
jjg@46 159
jjg@46 160 new Option(false, "-package") {
jjg@46 161 void process(JavapTask task, String opt, String arg) {
jjg@68 162 task.options.accessOptions.add(opt);
jjg@46 163 task.options.showAccess = 0;
jjg@46 164 }
jjg@46 165 },
jjg@46 166
jjg@46 167 new Option(false, "-p", "-private") {
jjg@46 168 void process(JavapTask task, String opt, String arg) {
jjg@68 169 if (!task.options.accessOptions.contains("-p") &&
jjg@68 170 !task.options.accessOptions.contains("-private")) {
jjg@68 171 task.options.accessOptions.add(opt);
jjg@68 172 }
jjg@46 173 task.options.showAccess = AccessFlags.ACC_PRIVATE;
jjg@46 174 }
jjg@46 175 },
jjg@46 176
jjg@46 177 new Option(false, "-c") {
jjg@46 178 void process(JavapTask task, String opt, String arg) {
jjg@46 179 task.options.showDisassembled = true;
jjg@46 180 }
jjg@46 181 },
jjg@46 182
jjg@46 183 new Option(false, "-s") {
jjg@46 184 void process(JavapTask task, String opt, String arg) {
jjg@46 185 task.options.showInternalSignatures = true;
jjg@46 186 }
jjg@46 187 },
jjg@46 188
jjg@46 189 // new Option(false, "-all") {
jjg@46 190 // void process(JavapTask task, String opt, String arg) {
jjg@46 191 // task.options.showAllAttrs = true;
jjg@46 192 // }
jjg@46 193 // },
jjg@46 194
jjg@46 195 new Option(false, "-h") {
jjg@46 196 void process(JavapTask task, String opt, String arg) throws BadArgs {
jjg@46 197 throw task.new BadArgs("err.h.not.supported");
jjg@46 198 }
jjg@46 199 },
jjg@46 200
jjg@46 201 new Option(false, "-verify", "-verify-verbose") {
jjg@46 202 void process(JavapTask task, String opt, String arg) throws BadArgs {
jjg@46 203 throw task.new BadArgs("err.verify.not.supported");
jjg@46 204 }
jjg@46 205 },
jjg@46 206
jjg@88 207 new Option(false, "-sysinfo") {
jjg@88 208 void process(JavapTask task, String opt, String arg) {
jjg@88 209 task.options.sysInfo = true;
jjg@88 210 }
jjg@88 211 },
jjg@88 212
jjg@46 213 new Option(false, "-Xold") {
jjg@46 214 void process(JavapTask task, String opt, String arg) throws BadArgs {
jjg@46 215 // -Xold is only supported as first arg when invoked from
jjg@46 216 // command line; this is handled in Main,main
jjg@46 217 throw task.new BadArgs("err.Xold.not.supported.here");
jjg@46 218 }
jjg@46 219 },
jjg@46 220
jjg@46 221 new Option(false, "-Xnew") {
jjg@46 222 void process(JavapTask task, String opt, String arg) throws BadArgs {
jjg@46 223 // ignore: this _is_ the new version
jjg@46 224 }
jjg@46 225 },
jjg@46 226
jjg@46 227 new Option(false, "-XDcompat") {
jjg@46 228 void process(JavapTask task, String opt, String arg) {
jjg@46 229 task.options.compat = true;
jjg@46 230 }
jjg@46 231 },
jjg@46 232
jjg@46 233 new Option(false, "-XDjsr277") {
jjg@46 234 void process(JavapTask task, String opt, String arg) {
jjg@46 235 task.options.jsr277 = true;
jjg@46 236 }
jjg@46 237 },
jjg@46 238
jjg@46 239 new Option(false, "-XDignore.symbol.file") {
jjg@46 240 void process(JavapTask task, String opt, String arg) {
jjg@46 241 task.options.ignoreSymbolFile = true;
jjg@46 242 }
jjg@87 243 },
jjg@87 244
jjg@283 245 new Option(false, "-XDdetails") {
jjg@283 246 void process(JavapTask task, String opt, String arg) {
jjg@283 247 task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
jjg@283 248 }
jjg@283 249
jjg@283 250 },
jjg@283 251
jjg@283 252 new Option(false, "-XDdetails:") {
jjg@283 253 @Override
jjg@283 254 boolean matches(String opt) {
jjg@283 255 int sep = opt.indexOf(":");
jjg@283 256 return sep != -1 && super.matches(opt.substring(0, sep + 1));
jjg@283 257 }
jjg@283 258
jjg@283 259 void process(JavapTask task, String opt, String arg) throws BadArgs {
jjg@283 260 int sep = opt.indexOf(":");
jjg@283 261 for (String v: opt.substring(sep + 1).split("[,: ]+")) {
jjg@283 262 if (!handleArg(task, v))
jjg@283 263 throw task.new BadArgs("err.invalid.arg.for.option", v);
jjg@283 264 }
jjg@283 265 }
jjg@283 266
jjg@283 267 boolean handleArg(JavapTask task, String arg) {
jjg@283 268 if (arg.length() == 0)
jjg@283 269 return true;
jjg@283 270
jjg@283 271 if (arg.equals("all")) {
jjg@283 272 task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
jjg@283 273 return true;
jjg@283 274 }
jjg@283 275
jjg@283 276 boolean on = true;
jjg@283 277 if (arg.startsWith("-")) {
jjg@283 278 on = false;
jjg@283 279 arg = arg.substring(1);
jjg@283 280 }
jjg@283 281
jjg@283 282 for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
jjg@283 283 if (arg.equalsIgnoreCase(k.option)) {
jjg@283 284 if (on)
jjg@283 285 task.options.details.add(k);
jjg@283 286 else
jjg@283 287 task.options.details.remove(k);
jjg@283 288 return true;
jjg@283 289 }
jjg@283 290 }
jjg@283 291 return false;
jjg@283 292 }
jjg@283 293 },
jjg@283 294
jjg@87 295 new Option(false, "-constants") {
jjg@87 296 void process(JavapTask task, String opt, String arg) {
jjg@87 297 task.options.showConstants = true;
jjg@87 298 }
jjg@46 299 }
jjg@46 300
jjg@46 301 };
jjg@46 302
jjg@46 303 JavapTask() {
jjg@46 304 context = new Context();
jjg@283 305 context.put(Messages.class, this);
jjg@46 306 options = Options.instance(context);
jjg@46 307 }
jjg@46 308
jjg@46 309 JavapTask(Writer out,
jjg@46 310 JavaFileManager fileManager,
jjg@46 311 DiagnosticListener<? super JavaFileObject> diagnosticListener,
jjg@46 312 Iterable<String> options,
jjg@46 313 Iterable<String> classes) {
jjg@46 314 this();
jjg@46 315 this.log = getPrintWriterForWriter(out);
jjg@46 316 this.fileManager = fileManager;
jjg@46 317 this.diagnosticListener = diagnosticListener;
jjg@46 318
jjg@46 319 try {
jjg@46 320 handleOptions(options, false);
jjg@46 321 } catch (BadArgs e) {
jjg@46 322 throw new IllegalArgumentException(e.getMessage());
jjg@46 323 }
jjg@46 324
jjg@46 325 this.classes = new ArrayList<String>();
jjg@46 326 for (String classname: classes) {
jjg@46 327 classname.getClass(); // null-check
jjg@46 328 this.classes.add(classname);
jjg@46 329 }
jjg@46 330 }
jjg@46 331
jjg@46 332 public void setLocale(Locale locale) {
jjg@46 333 if (locale == null)
jjg@46 334 locale = Locale.getDefault();
jjg@46 335 task_locale = locale;
jjg@46 336 }
jjg@46 337
jjg@46 338 public void setLog(PrintWriter log) {
jjg@46 339 this.log = log;
jjg@46 340 }
jjg@46 341
jjg@46 342 public void setLog(OutputStream s) {
jjg@46 343 setLog(getPrintWriterForStream(s));
jjg@46 344 }
jjg@46 345
jjg@46 346 private static PrintWriter getPrintWriterForStream(OutputStream s) {
jjg@46 347 return new PrintWriter(s, true);
jjg@46 348 }
jjg@46 349
jjg@46 350 private static PrintWriter getPrintWriterForWriter(Writer w) {
jjg@46 351 if (w == null)
jjg@46 352 return getPrintWriterForStream(null);
jjg@46 353 else if (w instanceof PrintWriter)
jjg@46 354 return (PrintWriter) w;
jjg@46 355 else
jjg@46 356 return new PrintWriter(w, true);
jjg@46 357 }
jjg@46 358
jjg@46 359 public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
jjg@46 360 diagnosticListener = dl;
jjg@46 361 }
jjg@46 362
jjg@46 363 public void setDiagnosticListener(OutputStream s) {
jjg@46 364 setDiagnosticListener(getDiagnosticListenerForStream(s));
jjg@46 365 }
jjg@46 366
jjg@46 367 private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
jjg@46 368 return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
jjg@46 369 }
jjg@46 370
jjg@46 371 private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
jjg@46 372 final PrintWriter pw = getPrintWriterForWriter(w);
jjg@46 373 return new DiagnosticListener<JavaFileObject> () {
jjg@46 374 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
jjg@46 375 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
jjg@66 376 pw.print(getMessage("err.prefix"));
jjg@46 377 pw.print(" ");
jjg@46 378 }
jjg@46 379 pw.println(diagnostic.getMessage(null));
jjg@46 380 }
jjg@46 381 };
jjg@46 382 }
jjg@46 383
jjg@64 384 /** Result codes.
jjg@64 385 */
jjg@64 386 static final int
jjg@64 387 EXIT_OK = 0, // Compilation completed with no errors.
jjg@64 388 EXIT_ERROR = 1, // Completed but reported errors.
jjg@64 389 EXIT_CMDERR = 2, // Bad command-line arguments
jjg@64 390 EXIT_SYSERR = 3, // System error or resource exhaustion.
jjg@64 391 EXIT_ABNORMAL = 4; // Compiler terminated abnormally
jjg@64 392
jjg@46 393 int run(String[] args) {
jjg@46 394 try {
jjg@46 395 handleOptions(args);
jjg@64 396
jjg@64 397 // the following gives consistent behavior with javac
jjg@64 398 if (classes == null || classes.size() == 0) {
jjg@64 399 if (options.help || options.version || options.fullVersion)
jjg@64 400 return EXIT_OK;
jjg@64 401 else
jjg@64 402 return EXIT_CMDERR;
jjg@64 403 }
jjg@64 404
jjg@46 405 boolean ok = run();
jjg@64 406 return ok ? EXIT_OK : EXIT_ERROR;
jjg@46 407 } catch (BadArgs e) {
jjg@46 408 diagnosticListener.report(createDiagnostic(e.key, e.args));
jjg@66 409 if (e.showUsage) {
jjg@66 410 log.println(getMessage("main.usage.summary", progname));
jjg@66 411 }
jjg@64 412 return EXIT_CMDERR;
jjg@46 413 } catch (InternalError e) {
jjg@46 414 Object[] e_args;
jjg@46 415 if (e.getCause() == null)
jjg@46 416 e_args = e.args;
jjg@46 417 else {
jjg@46 418 e_args = new Object[e.args.length + 1];
jjg@46 419 e_args[0] = e.getCause();
jjg@46 420 System.arraycopy(e.args, 0, e_args, 1, e.args.length);
jjg@46 421 }
jjg@46 422 diagnosticListener.report(createDiagnostic("err.internal.error", e_args));
jjg@64 423 return EXIT_ABNORMAL;
jjg@46 424 } finally {
jjg@46 425 log.flush();
jjg@46 426 }
jjg@46 427 }
jjg@46 428
jjg@46 429 public void handleOptions(String[] args) throws BadArgs {
jjg@46 430 handleOptions(Arrays.asList(args), true);
jjg@46 431 }
jjg@46 432
jjg@46 433 private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
jjg@46 434 if (log == null) {
jjg@46 435 log = getPrintWriterForStream(System.out);
jjg@46 436 if (diagnosticListener == null)
jjg@46 437 diagnosticListener = getDiagnosticListenerForStream(System.err);
jjg@46 438 } else {
jjg@46 439 if (diagnosticListener == null)
jjg@46 440 diagnosticListener = getDiagnosticListenerForWriter(log);
jjg@46 441 }
jjg@46 442
jjg@46 443
jjg@46 444 if (fileManager == null)
jjg@46 445 fileManager = getDefaultFileManager(diagnosticListener, log);
jjg@46 446
jjg@46 447 Iterator<String> iter = args.iterator();
jjg@64 448 boolean noArgs = !iter.hasNext();
jjg@46 449
jjg@46 450 while (iter.hasNext()) {
jjg@46 451 String arg = iter.next();
jjg@46 452 if (arg.startsWith("-"))
jjg@46 453 handleOption(arg, iter);
jjg@46 454 else if (allowClasses) {
jjg@46 455 if (classes == null)
jjg@46 456 classes = new ArrayList<String>();
jjg@46 457 classes.add(arg);
jjg@46 458 while (iter.hasNext())
jjg@46 459 classes.add(iter.next());
jjg@46 460 } else
jjg@46 461 throw new BadArgs("err.unknown.option", arg).showUsage(true);
jjg@46 462 }
jjg@46 463
jjg@68 464 if (!options.compat && options.accessOptions.size() > 1) {
jjg@68 465 StringBuilder sb = new StringBuilder();
jjg@68 466 for (String opt: options.accessOptions) {
jjg@68 467 if (sb.length() > 0)
jjg@68 468 sb.append(" ");
jjg@68 469 sb.append(opt);
jjg@68 470 }
jjg@68 471 throw new BadArgs("err.incompatible.options", sb);
jjg@68 472 }
jjg@68 473
jjg@46 474 if (options.ignoreSymbolFile && fileManager instanceof JavapFileManager)
jjg@46 475 ((JavapFileManager) fileManager).setIgnoreSymbolFile(true);
jjg@46 476
jjg@46 477 if ((classes == null || classes.size() == 0) &&
jjg@64 478 !(noArgs || options.help || options.version || options.fullVersion)) {
jjg@46 479 throw new BadArgs("err.no.classes.specified");
jjg@46 480 }
jjg@64 481
jjg@64 482 if (noArgs || options.help)
jjg@64 483 showHelp();
jjg@64 484
jjg@64 485 if (options.version || options.fullVersion)
jjg@64 486 showVersion(options.fullVersion);
jjg@46 487 }
jjg@46 488
jjg@46 489 private void handleOption(String name, Iterator<String> rest) throws BadArgs {
jjg@46 490 for (Option o: recognizedOptions) {
jjg@46 491 if (o.matches(name)) {
jjg@46 492 if (o.hasArg) {
jjg@46 493 if (rest.hasNext())
jjg@46 494 o.process(this, name, rest.next());
jjg@46 495 else
jjg@46 496 throw new BadArgs("err.missing.arg", name).showUsage(true);
jjg@46 497 } else
jjg@46 498 o.process(this, name, null);
jjg@46 499
jjg@46 500 if (o.ignoreRest()) {
jjg@46 501 while (rest.hasNext())
jjg@46 502 rest.next();
jjg@46 503 }
jjg@46 504 return;
jjg@46 505 }
jjg@46 506 }
jjg@46 507
jjg@46 508 if (fileManager.handleOption(name, rest))
jjg@46 509 return;
jjg@46 510
jjg@46 511 throw new BadArgs("err.unknown.option", name).showUsage(true);
jjg@46 512 }
jjg@46 513
jjg@46 514 public Boolean call() {
jjg@46 515 return run();
jjg@46 516 }
jjg@46 517
jjg@46 518 public boolean run() {
jjg@46 519 if (classes == null || classes.size() == 0)
jjg@64 520 return false;
jjg@46 521
jjg@46 522 context.put(PrintWriter.class, log);
jjg@46 523 ClassWriter classWriter = ClassWriter.instance(context);
jjg@283 524 SourceWriter sourceWriter = SourceWriter.instance(context);
jjg@283 525 sourceWriter.setFileManager(fileManager);
jjg@46 526
jjg@46 527 boolean ok = true;
jjg@46 528
jjg@46 529 for (String className: classes) {
jjg@46 530 JavaFileObject fo;
jjg@46 531 try {
jjg@46 532 if (className.endsWith(".class")) {
jjg@46 533 if (fileManager instanceof StandardJavaFileManager) {
jjg@46 534 StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
jjg@46 535 fo = sfm.getJavaFileObjects(className).iterator().next();
jjg@46 536 } else {
jjg@46 537 diagnosticListener.report(createDiagnostic("err.not.standard.file.manager", className));
jjg@46 538 ok = false;
jjg@46 539 continue;
jjg@46 540 }
jjg@46 541 } else {
jjg@46 542 fo = getClassFileObject(className);
jjg@46 543 if (fo == null) {
jjg@46 544 // see if it is an inner class, by replacing dots to $, starting from the right
jjg@46 545 String cn = className;
jjg@46 546 int lastDot;
jjg@46 547 while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
jjg@46 548 cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
jjg@46 549 fo = getClassFileObject(cn);
jjg@46 550 }
jjg@46 551 }
jjg@46 552 if (fo == null) {
jjg@46 553 diagnosticListener.report(createDiagnostic("err.class.not.found", className));
jjg@46 554 ok = false;
jjg@46 555 continue;
jjg@46 556 }
jjg@46 557 }
jjg@46 558 Attribute.Factory attributeFactory = new Attribute.Factory();
jjg@46 559 attributeFactory.setCompat(options.compat);
jjg@46 560 attributeFactory.setJSR277(options.jsr277);
jjg@88 561
jjg@88 562 InputStream in = fo.openInputStream();
jjg@88 563 SizeInputStream sizeIn = null;
jjg@88 564 MessageDigest md = null;
jjg@88 565 if (options.sysInfo || options.verbose) {
jjg@88 566 md = MessageDigest.getInstance("MD5");
jjg@88 567 in = new DigestInputStream(in, md);
jjg@88 568 in = sizeIn = new SizeInputStream(in);
jjg@88 569 }
jjg@88 570
jjg@88 571 ClassFile cf = ClassFile.read(in, attributeFactory);
jjg@88 572
jjg@88 573 if (options.sysInfo || options.verbose) {
jjg@88 574 classWriter.setFile(fo.toUri());
jjg@88 575 classWriter.setLastModified(fo.getLastModified());
jjg@88 576 classWriter.setDigest("MD5", md.digest());
jjg@88 577 classWriter.setFileSize(sizeIn.size());
jjg@88 578 }
jjg@88 579
jjg@46 580 classWriter.write(cf);
jjg@88 581
jjg@46 582 } catch (ConstantPoolException e) {
jjg@46 583 diagnosticListener.report(createDiagnostic("err.bad.constant.pool", className, e.getLocalizedMessage()));
jjg@46 584 ok = false;
jjg@46 585 } catch (EOFException e) {
jjg@46 586 diagnosticListener.report(createDiagnostic("err.end.of.file", className));
jjg@46 587 ok = false;
jjg@46 588 } catch (FileNotFoundException e) {
jjg@46 589 diagnosticListener.report(createDiagnostic("err.file.not.found", e.getLocalizedMessage()));
jjg@46 590 ok = false;
jjg@46 591 } catch (IOException e) {
jjg@46 592 //e.printStackTrace();
jjg@46 593 Object msg = e.getLocalizedMessage();
jjg@46 594 if (msg == null)
jjg@46 595 msg = e;
jjg@46 596 diagnosticListener.report(createDiagnostic("err.ioerror", className, msg));
jjg@46 597 ok = false;
jjg@46 598 } catch (Throwable t) {
jjg@46 599 StringWriter sw = new StringWriter();
jjg@46 600 PrintWriter pw = new PrintWriter(sw);
jjg@46 601 t.printStackTrace(pw);
jjg@46 602 pw.close();
jjg@46 603 diagnosticListener.report(createDiagnostic("err.crash", t.toString(), sw.toString()));
jjg@52 604 ok = false;
jjg@46 605 }
jjg@46 606 }
jjg@46 607
jjg@46 608 return ok;
jjg@46 609 }
jjg@46 610
jjg@46 611 private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
jjg@46 612 return JavapFileManager.create(dl, log, options);
jjg@46 613 }
jjg@46 614
jjg@46 615 private JavaFileObject getClassFileObject(String className) throws IOException {
jjg@46 616 JavaFileObject fo;
jjg@46 617 fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
jjg@46 618 if (fo == null)
jjg@46 619 fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
jjg@46 620 return fo;
jjg@46 621 }
jjg@46 622
jjg@46 623 private void showHelp() {
jjg@46 624 log.println(getMessage("main.usage", progname));
jjg@46 625 for (Option o: recognizedOptions) {
jjg@46 626 String name = o.aliases[0].substring(1); // there must always be at least one name
jjg@46 627 if (name.startsWith("X") || name.equals("fullversion") || name.equals("h") || name.equals("verify"))
jjg@46 628 continue;
jjg@46 629 log.println(getMessage("main.opt." + name));
jjg@46 630 }
jjg@46 631 String[] fmOptions = { "-classpath", "-bootclasspath" };
jjg@46 632 for (String o: fmOptions) {
jjg@46 633 if (fileManager.isSupportedOption(o) == -1)
jjg@46 634 continue;
jjg@46 635 String name = o.substring(1);
jjg@46 636 log.println(getMessage("main.opt." + name));
jjg@46 637 }
jjg@46 638
jjg@46 639 }
jjg@46 640
jjg@46 641 private void showVersion(boolean full) {
jjg@46 642 log.println(version(full ? "full" : "release"));
jjg@46 643 }
jjg@46 644
jjg@46 645 private static final String versionRBName = "com.sun.tools.javap.resources.version";
jjg@46 646 private static ResourceBundle versionRB;
jjg@46 647
jjg@46 648 private String version(String key) {
jjg@46 649 // key=version: mm.nn.oo[-milestone]
jjg@46 650 // key=full: mm.mm.oo[-milestone]-build
jjg@46 651 if (versionRB == null) {
jjg@46 652 try {
jjg@46 653 versionRB = ResourceBundle.getBundle(versionRBName);
jjg@46 654 } catch (MissingResourceException e) {
jjg@46 655 return getMessage("version.resource.missing", System.getProperty("java.version"));
jjg@46 656 }
jjg@46 657 }
jjg@46 658 try {
jjg@46 659 return versionRB.getString(key);
jjg@46 660 }
jjg@46 661 catch (MissingResourceException e) {
jjg@46 662 return getMessage("version.unknown", System.getProperty("java.version"));
jjg@46 663 }
jjg@46 664 }
jjg@46 665
jjg@46 666 private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) {
jjg@46 667 return new Diagnostic<JavaFileObject>() {
jjg@46 668 public Kind getKind() {
jjg@46 669 return Diagnostic.Kind.ERROR;
jjg@46 670 }
jjg@46 671
jjg@46 672 public JavaFileObject getSource() {
jjg@46 673 return null;
jjg@46 674 }
jjg@46 675
jjg@46 676 public long getPosition() {
jjg@46 677 return Diagnostic.NOPOS;
jjg@46 678 }
jjg@46 679
jjg@46 680 public long getStartPosition() {
jjg@46 681 return Diagnostic.NOPOS;
jjg@46 682 }
jjg@46 683
jjg@46 684 public long getEndPosition() {
jjg@46 685 return Diagnostic.NOPOS;
jjg@46 686 }
jjg@46 687
jjg@46 688 public long getLineNumber() {
jjg@46 689 return Diagnostic.NOPOS;
jjg@46 690 }
jjg@46 691
jjg@46 692 public long getColumnNumber() {
jjg@46 693 return Diagnostic.NOPOS;
jjg@46 694 }
jjg@46 695
jjg@46 696 public String getCode() {
jjg@46 697 return key;
jjg@46 698 }
jjg@46 699
jjg@46 700 public String getMessage(Locale locale) {
jjg@46 701 return JavapTask.this.getMessage(locale, key, args);
jjg@46 702 }
jjg@46 703
jjg@46 704 };
jjg@46 705
jjg@46 706 }
jjg@46 707
jjg@283 708 public String getMessage(String key, Object... args) {
jjg@46 709 return getMessage(task_locale, key, args);
jjg@46 710 }
jjg@46 711
jjg@283 712 public String getMessage(Locale locale, String key, Object... args) {
jjg@46 713 if (bundles == null) {
jjg@46 714 // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
jjg@46 715 // and for efficiency, keep a hard reference to the bundle for the task
jjg@46 716 // locale
jjg@46 717 bundles = new HashMap<Locale, ResourceBundle>();
jjg@46 718 }
jjg@46 719
jjg@46 720 if (locale == null)
jjg@46 721 locale = Locale.getDefault();
jjg@46 722
jjg@46 723 ResourceBundle b = bundles.get(locale);
jjg@46 724 if (b == null) {
jjg@46 725 try {
jjg@46 726 b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);
jjg@46 727 bundles.put(locale, b);
jjg@46 728 } catch (MissingResourceException e) {
jjg@46 729 throw new InternalError("Cannot find javap resource bundle for locale " + locale);
jjg@46 730 }
jjg@46 731 }
jjg@46 732
jjg@46 733 try {
jjg@46 734 return MessageFormat.format(b.getString(key), args);
jjg@46 735 } catch (MissingResourceException e) {
jjg@46 736 throw new InternalError(e, key);
jjg@46 737 }
jjg@46 738 }
jjg@46 739
jjg@46 740 Context context;
jjg@46 741 JavaFileManager fileManager;
jjg@46 742 PrintWriter log;
jjg@46 743 DiagnosticListener<? super JavaFileObject> diagnosticListener;
jjg@46 744 List<String> classes;
jjg@46 745 Options options;
jjg@46 746 //ResourceBundle bundle;
jjg@46 747 Locale task_locale;
jjg@46 748 Map<Locale, ResourceBundle> bundles;
jjg@46 749
jjg@46 750 private static final String progname = "javap";
jjg@88 751
jjg@88 752 private static class SizeInputStream extends FilterInputStream {
jjg@88 753 SizeInputStream(InputStream in) {
jjg@88 754 super(in);
jjg@88 755 }
jjg@88 756
jjg@88 757 int size() {
jjg@88 758 return size;
jjg@88 759 }
jjg@88 760
jjg@88 761 @Override
jjg@88 762 public int read(byte[] buf, int offset, int length) throws IOException {
jjg@88 763 int n = super.read(buf, offset, length);
jjg@88 764 if (n > 0)
jjg@88 765 size += n;
jjg@88 766 return n;
jjg@88 767 }
jjg@88 768
jjg@88 769 @Override
jjg@88 770 public int read() throws IOException {
jjg@88 771 int b = super.read();
jjg@88 772 size += 1;
jjg@88 773 return b;
jjg@88 774 }
jjg@88 775
jjg@88 776 private int size;
jjg@88 777 }
jjg@46 778 }

mercurial