Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java
58461 views
1
/*
2
* Copyright (c) 2007, 2020, 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
26
package com.sun.tools.javap;
27
28
import java.io.EOFException;
29
import java.io.FileNotFoundException;
30
import java.io.FilterInputStream;
31
import java.io.InputStream;
32
import java.io.IOException;
33
import java.io.OutputStream;
34
import java.io.PrintWriter;
35
import java.io.Reader;
36
import java.io.StringWriter;
37
import java.io.Writer;
38
import java.net.URI;
39
import java.net.URISyntaxException;
40
import java.net.URL;
41
import java.net.URLConnection;
42
import java.nio.file.NoSuchFileException;
43
import java.security.DigestInputStream;
44
import java.security.MessageDigest;
45
import java.security.NoSuchAlgorithmException;
46
import java.text.MessageFormat;
47
import java.util.ArrayList;
48
import java.util.Arrays;
49
import java.util.EnumSet;
50
import java.util.HashMap;
51
import java.util.Iterator;
52
import java.util.List;
53
import java.util.Locale;
54
import java.util.Map;
55
import java.util.MissingResourceException;
56
import java.util.Objects;
57
import java.util.ResourceBundle;
58
import java.util.Set;
59
60
import javax.lang.model.element.Modifier;
61
import javax.lang.model.element.NestingKind;
62
import javax.tools.Diagnostic;
63
import javax.tools.DiagnosticListener;
64
import javax.tools.JavaFileManager;
65
import javax.tools.JavaFileManager.Location;
66
import javax.tools.JavaFileObject;
67
import javax.tools.StandardJavaFileManager;
68
import javax.tools.StandardLocation;
69
70
import com.sun.tools.classfile.*;
71
72
/**
73
* "Main" class for javap, normally accessed from the command line
74
* via Main, or from JSR199 via DisassemblerTool.
75
*
76
* <p><b>This is NOT part of any supported API.
77
* If you write code that depends on this, you do so at your own risk.
78
* This code and its internal interfaces are subject to change or
79
* deletion without notice.</b>
80
*/
81
public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
82
public class BadArgs extends Exception {
83
static final long serialVersionUID = 8765093759964640721L;
84
BadArgs(String key, Object... args) {
85
super(JavapTask.this.getMessage(key, args));
86
this.key = key;
87
this.args = args;
88
}
89
90
BadArgs showUsage(boolean b) {
91
showUsage = b;
92
return this;
93
}
94
95
final String key;
96
final Object[] args;
97
boolean showUsage;
98
}
99
100
static abstract class Option {
101
Option(boolean hasArg, String... aliases) {
102
this.hasArg = hasArg;
103
this.aliases = aliases;
104
}
105
106
boolean matches(String opt) {
107
for (String a: aliases) {
108
if (a.equals(opt))
109
return true;
110
}
111
return false;
112
}
113
114
boolean ignoreRest() {
115
return false;
116
}
117
118
abstract void process(JavapTask task, String opt, String arg) throws BadArgs;
119
120
final boolean hasArg;
121
final String[] aliases;
122
}
123
124
static final Option[] recognizedOptions = {
125
126
new Option(false, "-help", "--help", "-?", "-h") {
127
@Override
128
void process(JavapTask task, String opt, String arg) {
129
task.options.help = true;
130
}
131
},
132
133
new Option(false, "-version") {
134
@Override
135
void process(JavapTask task, String opt, String arg) {
136
task.options.version = true;
137
}
138
},
139
140
new Option(false, "-fullversion") {
141
@Override
142
void process(JavapTask task, String opt, String arg) {
143
task.options.fullVersion = true;
144
}
145
},
146
147
new Option(false, "-v", "-verbose", "-all") {
148
@Override
149
void process(JavapTask task, String opt, String arg) {
150
task.options.verbose = true;
151
task.options.showDescriptors = true;
152
task.options.showFlags = true;
153
task.options.showAllAttrs = true;
154
}
155
},
156
157
new Option(false, "-l") {
158
@Override
159
void process(JavapTask task, String opt, String arg) {
160
task.options.showLineAndLocalVariableTables = true;
161
}
162
},
163
164
new Option(false, "-public") {
165
@Override
166
void process(JavapTask task, String opt, String arg) {
167
task.options.accessOptions.add(opt);
168
task.options.showAccess = AccessFlags.ACC_PUBLIC;
169
}
170
},
171
172
new Option(false, "-protected") {
173
@Override
174
void process(JavapTask task, String opt, String arg) {
175
task.options.accessOptions.add(opt);
176
task.options.showAccess = AccessFlags.ACC_PROTECTED;
177
}
178
},
179
180
new Option(false, "-package") {
181
@Override
182
void process(JavapTask task, String opt, String arg) {
183
task.options.accessOptions.add(opt);
184
task.options.showAccess = 0;
185
}
186
},
187
188
new Option(false, "-p", "-private") {
189
@Override
190
void process(JavapTask task, String opt, String arg) {
191
if (!task.options.accessOptions.contains("-p") &&
192
!task.options.accessOptions.contains("-private")) {
193
task.options.accessOptions.add(opt);
194
}
195
task.options.showAccess = AccessFlags.ACC_PRIVATE;
196
}
197
},
198
199
new Option(false, "-c") {
200
@Override
201
void process(JavapTask task, String opt, String arg) {
202
task.options.showDisassembled = true;
203
}
204
},
205
206
new Option(false, "-s") {
207
@Override
208
void process(JavapTask task, String opt, String arg) {
209
task.options.showDescriptors = true;
210
}
211
},
212
213
new Option(false, "-sysinfo") {
214
@Override
215
void process(JavapTask task, String opt, String arg) {
216
task.options.sysInfo = true;
217
}
218
},
219
220
new Option(false, "-XDdetails") {
221
@Override
222
void process(JavapTask task, String opt, String arg) {
223
task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
224
}
225
226
},
227
228
new Option(false, "-XDdetails:") {
229
@Override
230
boolean matches(String opt) {
231
int sep = opt.indexOf(":");
232
return sep != -1 && super.matches(opt.substring(0, sep + 1));
233
}
234
235
@Override
236
void process(JavapTask task, String opt, String arg) throws BadArgs {
237
int sep = opt.indexOf(":");
238
for (String v: opt.substring(sep + 1).split("[,: ]+")) {
239
if (!handleArg(task, v))
240
throw task.new BadArgs("err.invalid.arg.for.option", v);
241
}
242
}
243
244
boolean handleArg(JavapTask task, String arg) {
245
if (arg.length() == 0)
246
return true;
247
248
if (arg.equals("all")) {
249
task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
250
return true;
251
}
252
253
boolean on = true;
254
if (arg.startsWith("-")) {
255
on = false;
256
arg = arg.substring(1);
257
}
258
259
for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
260
if (arg.equalsIgnoreCase(k.option)) {
261
if (on)
262
task.options.details.add(k);
263
else
264
task.options.details.remove(k);
265
return true;
266
}
267
}
268
return false;
269
}
270
},
271
272
new Option(false, "-constants") {
273
@Override
274
void process(JavapTask task, String opt, String arg) {
275
task.options.showConstants = true;
276
}
277
},
278
279
new Option(false, "-XDinner") {
280
@Override
281
void process(JavapTask task, String opt, String arg) {
282
task.options.showInnerClasses = true;
283
}
284
},
285
286
new Option(false, "-XDindent:") {
287
@Override
288
boolean matches(String opt) {
289
int sep = opt.indexOf(":");
290
return sep != -1 && super.matches(opt.substring(0, sep + 1));
291
}
292
293
@Override
294
void process(JavapTask task, String opt, String arg) throws BadArgs {
295
int sep = opt.indexOf(":");
296
try {
297
int i = Integer.valueOf(opt.substring(sep + 1));
298
if (i > 0) // silently ignore invalid values
299
task.options.indentWidth = i;
300
} catch (NumberFormatException e) {
301
}
302
}
303
},
304
305
new Option(false, "-XDtab:") {
306
@Override
307
boolean matches(String opt) {
308
int sep = opt.indexOf(":");
309
return sep != -1 && super.matches(opt.substring(0, sep + 1));
310
}
311
312
@Override
313
void process(JavapTask task, String opt, String arg) throws BadArgs {
314
int sep = opt.indexOf(":");
315
try {
316
int i = Integer.valueOf(opt.substring(sep + 1));
317
if (i > 0) // silently ignore invalid values
318
task.options.tabColumn = i;
319
} catch (NumberFormatException e) {
320
}
321
}
322
},
323
324
new Option(true, "--module", "-m") {
325
@Override
326
void process(JavapTask task, String opt, String arg) throws BadArgs {
327
task.options.moduleName = arg;
328
}
329
},
330
331
// this option is processed by the launcher, and cannot be used when invoked via
332
// an API like ToolProvider. It exists here to be documented in the command-line help.
333
new Option(false, "-J") {
334
@Override
335
boolean matches(String opt) {
336
return opt.startsWith("-J");
337
}
338
339
@Override
340
void process(JavapTask task, String opt, String arg) throws BadArgs {
341
throw task.new BadArgs("err.only.for.launcher");
342
}
343
}
344
345
};
346
347
public JavapTask() {
348
context = new Context();
349
context.put(Messages.class, this);
350
options = Options.instance(context);
351
attributeFactory = new Attribute.Factory();
352
}
353
354
public JavapTask(Writer out,
355
JavaFileManager fileManager,
356
DiagnosticListener<? super JavaFileObject> diagnosticListener) {
357
this();
358
this.log = getPrintWriterForWriter(out);
359
this.fileManager = fileManager;
360
this.diagnosticListener = diagnosticListener;
361
}
362
363
public JavapTask(Writer out,
364
JavaFileManager fileManager,
365
DiagnosticListener<? super JavaFileObject> diagnosticListener,
366
Iterable<String> options,
367
Iterable<String> classes) {
368
this(out, fileManager, diagnosticListener);
369
370
this.classes = new ArrayList<>();
371
for (String classname: classes) {
372
Objects.requireNonNull(classname);
373
this.classes.add(classname);
374
}
375
376
try {
377
if (options != null)
378
handleOptions(options, false);
379
} catch (BadArgs e) {
380
throw new IllegalArgumentException(e.getMessage());
381
}
382
}
383
384
public void setLocale(Locale locale) {
385
if (locale == null)
386
locale = Locale.getDefault();
387
task_locale = locale;
388
}
389
390
public void setLog(Writer log) {
391
this.log = getPrintWriterForWriter(log);
392
}
393
394
public void setLog(OutputStream s) {
395
setLog(getPrintWriterForStream(s));
396
}
397
398
private static PrintWriter getPrintWriterForStream(OutputStream s) {
399
return new PrintWriter(s == null ? System.err : s, true);
400
}
401
402
private static PrintWriter getPrintWriterForWriter(Writer w) {
403
if (w == null)
404
return getPrintWriterForStream(null);
405
else if (w instanceof PrintWriter)
406
return (PrintWriter) w;
407
else
408
return new PrintWriter(w, true);
409
}
410
411
public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
412
diagnosticListener = dl;
413
}
414
415
public void setDiagnosticListener(OutputStream s) {
416
setDiagnosticListener(getDiagnosticListenerForStream(s));
417
}
418
419
private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
420
return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
421
}
422
423
private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
424
final PrintWriter pw = getPrintWriterForWriter(w);
425
return diagnostic -> {
426
switch (diagnostic.getKind()) {
427
case ERROR:
428
pw.print(getMessage("err.prefix"));
429
break;
430
case WARNING:
431
pw.print(getMessage("warn.prefix"));
432
break;
433
case NOTE:
434
pw.print(getMessage("note.prefix"));
435
break;
436
}
437
pw.print(" ");
438
pw.println(diagnostic.getMessage(null));
439
};
440
}
441
442
/** Result codes.
443
*/
444
static final int
445
EXIT_OK = 0, // Compilation completed with no errors.
446
EXIT_ERROR = 1, // Completed but reported errors.
447
EXIT_CMDERR = 2, // Bad command-line arguments
448
EXIT_SYSERR = 3, // System error or resource exhaustion.
449
EXIT_ABNORMAL = 4; // Compiler terminated abnormally
450
451
int run(String[] args) {
452
try {
453
try {
454
handleOptions(args);
455
456
// the following gives consistent behavior with javac
457
if (classes == null || classes.size() == 0) {
458
if (options.help || options.version || options.fullVersion)
459
return EXIT_OK;
460
else
461
return EXIT_CMDERR;
462
}
463
464
return run();
465
} finally {
466
if (defaultFileManager != null) {
467
try {
468
defaultFileManager.close();
469
defaultFileManager = null;
470
} catch (IOException e) {
471
throw new InternalError(e);
472
}
473
}
474
}
475
} catch (BadArgs e) {
476
reportError(e.key, e.args);
477
if (e.showUsage) {
478
printLines(getMessage("main.usage.summary", progname));
479
}
480
return EXIT_CMDERR;
481
} catch (InternalError e) {
482
Object[] e_args;
483
if (e.getCause() == null)
484
e_args = e.args;
485
else {
486
e_args = new Object[e.args.length + 1];
487
e_args[0] = e.getCause();
488
System.arraycopy(e.args, 0, e_args, 1, e.args.length);
489
}
490
reportError("err.internal.error", e_args);
491
return EXIT_ABNORMAL;
492
} finally {
493
log.flush();
494
}
495
}
496
497
public void handleOptions(String[] args) throws BadArgs {
498
handleOptions(Arrays.asList(args), true);
499
}
500
501
private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
502
if (log == null) {
503
log = getPrintWriterForStream(System.out);
504
if (diagnosticListener == null)
505
diagnosticListener = getDiagnosticListenerForStream(System.err);
506
} else {
507
if (diagnosticListener == null)
508
diagnosticListener = getDiagnosticListenerForWriter(log);
509
}
510
511
512
if (fileManager == null)
513
fileManager = getDefaultFileManager(diagnosticListener, log);
514
515
Iterator<String> iter = args.iterator();
516
boolean noArgs = !iter.hasNext();
517
518
while (iter.hasNext()) {
519
String arg = iter.next();
520
if (arg.startsWith("-"))
521
handleOption(arg, iter);
522
else if (allowClasses) {
523
if (classes == null)
524
classes = new ArrayList<>();
525
classes.add(arg);
526
while (iter.hasNext())
527
classes.add(iter.next());
528
} else
529
throw new BadArgs("err.unknown.option", arg).showUsage(true);
530
}
531
532
if (options.accessOptions.size() > 1) {
533
StringBuilder sb = new StringBuilder();
534
for (String opt: options.accessOptions) {
535
if (sb.length() > 0)
536
sb.append(" ");
537
sb.append(opt);
538
}
539
throw new BadArgs("err.incompatible.options", sb);
540
}
541
542
if ((classes == null || classes.size() == 0) &&
543
!(noArgs || options.help || options.version || options.fullVersion)) {
544
throw new BadArgs("err.no.classes.specified");
545
}
546
547
if (noArgs || options.help)
548
showHelp();
549
550
if (options.version || options.fullVersion)
551
showVersion(options.fullVersion);
552
}
553
554
private void handleOption(String name, Iterator<String> rest) throws BadArgs {
555
for (Option o: recognizedOptions) {
556
if (o.matches(name)) {
557
if (o.hasArg) {
558
if (rest.hasNext())
559
o.process(this, name, rest.next());
560
else
561
throw new BadArgs("err.missing.arg", name).showUsage(true);
562
} else
563
o.process(this, name, null);
564
565
if (o.ignoreRest()) {
566
while (rest.hasNext())
567
rest.next();
568
}
569
return;
570
}
571
}
572
573
try {
574
if (fileManager.handleOption(name, rest))
575
return;
576
} catch (IllegalArgumentException e) {
577
throw new BadArgs("err.invalid.use.of.option", name).showUsage(true);
578
}
579
580
throw new BadArgs("err.unknown.option", name).showUsage(true);
581
}
582
583
public Boolean call() {
584
return run() == 0;
585
}
586
587
public int run() {
588
if (classes == null || classes.isEmpty()) {
589
return EXIT_ERROR;
590
}
591
592
context.put(PrintWriter.class, log);
593
ClassWriter classWriter = ClassWriter.instance(context);
594
SourceWriter sourceWriter = SourceWriter.instance(context);
595
sourceWriter.setFileManager(fileManager);
596
597
if (options.moduleName != null) {
598
try {
599
moduleLocation = findModule(options.moduleName);
600
if (moduleLocation == null) {
601
reportError("err.cant.find.module", options.moduleName);
602
return EXIT_ERROR;
603
}
604
} catch (IOException e) {
605
reportError("err.cant.find.module.ex", options.moduleName, e);
606
return EXIT_ERROR;
607
}
608
}
609
610
int result = EXIT_OK;
611
612
for (String className: classes) {
613
try {
614
result = writeClass(classWriter, className);
615
} catch (ConstantPoolException e) {
616
reportError("err.bad.constant.pool", className, e.getLocalizedMessage());
617
result = EXIT_ERROR;
618
} catch (EOFException e) {
619
reportError("err.end.of.file", className);
620
result = EXIT_ERROR;
621
} catch (FileNotFoundException | NoSuchFileException e) {
622
reportError("err.file.not.found", e.getLocalizedMessage());
623
result = EXIT_ERROR;
624
} catch (IOException e) {
625
//e.printStackTrace();
626
Object msg = e.getLocalizedMessage();
627
if (msg == null) {
628
msg = e;
629
}
630
reportError("err.ioerror", className, msg);
631
result = EXIT_ERROR;
632
} catch (OutOfMemoryError e) {
633
reportError("err.nomem");
634
result = EXIT_ERROR;
635
} catch (FatalError e) {
636
Object msg = e.getLocalizedMessage();
637
if (msg == null) {
638
msg = e;
639
}
640
reportError("err.fatal.err", msg);
641
result = EXIT_ERROR;
642
} catch (Throwable t) {
643
StringWriter sw = new StringWriter();
644
PrintWriter pw = new PrintWriter(sw);
645
t.printStackTrace(pw);
646
pw.close();
647
reportError("err.crash", t.toString(), sw.toString());
648
result = EXIT_ABNORMAL;
649
}
650
}
651
652
return result;
653
}
654
655
protected int writeClass(ClassWriter classWriter, String className)
656
throws IOException, ConstantPoolException {
657
JavaFileObject fo = open(className);
658
if (fo == null) {
659
reportError("err.class.not.found", className);
660
return EXIT_ERROR;
661
}
662
663
ClassFileInfo cfInfo = read(fo);
664
if (!className.endsWith(".class")) {
665
if (cfInfo.cf.this_class == 0) {
666
if (!className.equals("module-info")) {
667
reportWarning("warn.unexpected.class", fo.getName(), className);
668
}
669
} else {
670
String cfName = cfInfo.cf.getName();
671
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", "."))) {
672
reportWarning("warn.unexpected.class", fo.getName(), className);
673
}
674
}
675
}
676
write(cfInfo);
677
678
if (options.showInnerClasses) {
679
ClassFile cf = cfInfo.cf;
680
Attribute a = cf.getAttribute(Attribute.InnerClasses);
681
if (a instanceof InnerClasses_attribute) {
682
InnerClasses_attribute inners = (InnerClasses_attribute) a;
683
try {
684
int result = EXIT_OK;
685
for (int i = 0; i < inners.classes.length; i++) {
686
int outerIndex = inners.classes[i].outer_class_info_index;
687
ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);
688
String outerClassName = outerClassInfo.getName();
689
if (outerClassName.equals(cf.getName())) {
690
int innerIndex = inners.classes[i].inner_class_info_index;
691
ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);
692
String innerClassName = innerClassInfo.getName();
693
classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
694
classWriter.println();
695
result = writeClass(classWriter, innerClassName);
696
if (result != EXIT_OK) return result;
697
}
698
}
699
return result;
700
} catch (ConstantPoolException e) {
701
reportError("err.bad.innerclasses.attribute", className);
702
return EXIT_ERROR;
703
}
704
} else if (a != null) {
705
reportError("err.bad.innerclasses.attribute", className);
706
return EXIT_ERROR;
707
}
708
}
709
710
return EXIT_OK;
711
}
712
713
protected JavaFileObject open(String className) throws IOException {
714
// for compatibility, first see if it is a class name
715
JavaFileObject fo = getClassFileObject(className);
716
if (fo != null)
717
return fo;
718
719
// see if it is an inner class, by replacing dots to $, starting from the right
720
String cn = className;
721
int lastDot;
722
while ((lastDot = cn.lastIndexOf(".")) != -1) {
723
cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
724
fo = getClassFileObject(cn);
725
if (fo != null)
726
return fo;
727
}
728
729
if (!className.endsWith(".class"))
730
return null;
731
732
if (fileManager instanceof StandardJavaFileManager) {
733
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
734
try {
735
fo = sfm.getJavaFileObjects(className).iterator().next();
736
if (fo != null && fo.getLastModified() != 0) {
737
return fo;
738
}
739
} catch (IllegalArgumentException ignore) {
740
}
741
}
742
743
// see if it is a URL, and if so, wrap it in just enough of a JavaFileObject
744
// to suit javap's needs
745
if (className.matches("^[A-Za-z]+:.*")) {
746
try {
747
final URI uri = new URI(className);
748
final URL url = uri.toURL();
749
final URLConnection conn = url.openConnection();
750
conn.setUseCaches(false);
751
return new JavaFileObject() {
752
public Kind getKind() {
753
return JavaFileObject.Kind.CLASS;
754
}
755
756
public boolean isNameCompatible(String simpleName, Kind kind) {
757
throw new UnsupportedOperationException();
758
}
759
760
public NestingKind getNestingKind() {
761
throw new UnsupportedOperationException();
762
}
763
764
public Modifier getAccessLevel() {
765
throw new UnsupportedOperationException();
766
}
767
768
public URI toUri() {
769
return uri;
770
}
771
772
public String getName() {
773
return uri.toString();
774
}
775
776
public InputStream openInputStream() throws IOException {
777
return conn.getInputStream();
778
}
779
780
public OutputStream openOutputStream() throws IOException {
781
throw new UnsupportedOperationException();
782
}
783
784
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
785
throw new UnsupportedOperationException();
786
}
787
788
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
789
throw new UnsupportedOperationException();
790
}
791
792
public Writer openWriter() throws IOException {
793
throw new UnsupportedOperationException();
794
}
795
796
public long getLastModified() {
797
return conn.getLastModified();
798
}
799
800
public boolean delete() {
801
throw new UnsupportedOperationException();
802
}
803
804
};
805
} catch (URISyntaxException | IOException ignore) {
806
}
807
}
808
809
return null;
810
}
811
812
public static class ClassFileInfo {
813
ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
814
this.fo = fo;
815
this.cf = cf;
816
this.digest = digest;
817
this.size = size;
818
}
819
public final JavaFileObject fo;
820
public final ClassFile cf;
821
public final byte[] digest;
822
public final int size;
823
}
824
825
public ClassFileInfo read(JavaFileObject fo) throws IOException, ConstantPoolException {
826
InputStream in = fo.openInputStream();
827
try {
828
SizeInputStream sizeIn = null;
829
MessageDigest md = null;
830
if (options.sysInfo || options.verbose) {
831
try {
832
md = MessageDigest.getInstance("SHA-256");
833
} catch (NoSuchAlgorithmException ignore) {
834
}
835
in = new DigestInputStream(in, md);
836
in = sizeIn = new SizeInputStream(in);
837
}
838
839
ClassFile cf = ClassFile.read(in, attributeFactory);
840
byte[] digest = (md == null) ? null : md.digest();
841
int size = (sizeIn == null) ? -1 : sizeIn.size();
842
return new ClassFileInfo(fo, cf, digest, size);
843
} finally {
844
in.close();
845
}
846
}
847
848
public void write(ClassFileInfo info) {
849
ClassWriter classWriter = ClassWriter.instance(context);
850
if (options.sysInfo || options.verbose) {
851
classWriter.setFile(info.fo.toUri());
852
classWriter.setLastModified(info.fo.getLastModified());
853
classWriter.setDigest("SHA-256", info.digest);
854
classWriter.setFileSize(info.size);
855
}
856
857
classWriter.write(info.cf);
858
}
859
860
protected void setClassFile(ClassFile classFile) {
861
ClassWriter classWriter = ClassWriter.instance(context);
862
classWriter.setClassFile(classFile);
863
}
864
865
protected void setMethod(Method enclosingMethod) {
866
ClassWriter classWriter = ClassWriter.instance(context);
867
classWriter.setMethod(enclosingMethod);
868
}
869
870
protected void write(Attribute value) {
871
AttributeWriter attrWriter = AttributeWriter.instance(context);
872
ClassWriter classWriter = ClassWriter.instance(context);
873
ClassFile cf = classWriter.getClassFile();
874
attrWriter.write(cf, value, cf.constant_pool);
875
}
876
877
protected void write(Attributes attrs) {
878
AttributeWriter attrWriter = AttributeWriter.instance(context);
879
ClassWriter classWriter = ClassWriter.instance(context);
880
ClassFile cf = classWriter.getClassFile();
881
attrWriter.write(cf, attrs, cf.constant_pool);
882
}
883
884
protected void write(ConstantPool constant_pool) {
885
ConstantWriter constantWriter = ConstantWriter.instance(context);
886
constantWriter.writeConstantPool(constant_pool);
887
}
888
889
protected void write(ConstantPool constant_pool, int value) {
890
ConstantWriter constantWriter = ConstantWriter.instance(context);
891
constantWriter.write(value);
892
}
893
894
protected void write(ConstantPool.CPInfo value) {
895
ConstantWriter constantWriter = ConstantWriter.instance(context);
896
constantWriter.println(value);
897
}
898
899
protected void write(Field value) {
900
ClassWriter classWriter = ClassWriter.instance(context);
901
classWriter.writeField(value);
902
}
903
904
protected void write(Method value) {
905
ClassWriter classWriter = ClassWriter.instance(context);
906
classWriter.writeMethod(value);
907
}
908
909
private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
910
if (defaultFileManager == null)
911
defaultFileManager = JavapFileManager.create(dl, log);
912
return defaultFileManager;
913
}
914
915
private JavaFileObject getClassFileObject(String className) throws IOException {
916
try {
917
JavaFileObject fo;
918
if (moduleLocation != null) {
919
fo = fileManager.getJavaFileForInput(moduleLocation, className, JavaFileObject.Kind.CLASS);
920
} else {
921
fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
922
if (fo == null)
923
fo = fileManager.getJavaFileForInput(StandardLocation.CLASS_PATH, className, JavaFileObject.Kind.CLASS);
924
}
925
return fo;
926
} catch (IllegalArgumentException e) {
927
return null;
928
}
929
}
930
931
private Location findModule(String moduleName) throws IOException {
932
Location[] locns = {
933
StandardLocation.UPGRADE_MODULE_PATH,
934
StandardLocation.SYSTEM_MODULES,
935
StandardLocation.MODULE_PATH
936
};
937
for (Location segment: locns) {
938
for (Set<Location> set: fileManager.listLocationsForModules(segment)) {
939
Location result = null;
940
for (Location l: set) {
941
String name = fileManager.inferModuleName(l);
942
if (name.equals(moduleName)) {
943
if (result == null)
944
result = l;
945
else
946
throw new IOException("multiple definitions found for " + moduleName);
947
}
948
}
949
if (result != null)
950
return result;
951
}
952
}
953
return null;
954
}
955
956
private void showHelp() {
957
printLines(getMessage("main.usage", progname));
958
for (Option o: recognizedOptions) {
959
String name = o.aliases[0].replaceAll("^-+", "").replaceAll("-+", "_"); // there must always be at least one name
960
if (name.startsWith("X") || name.equals("fullversion"))
961
continue;
962
printLines(getMessage("main.opt." + name));
963
}
964
965
String[] fmOptions = {
966
"--module-path", "--system",
967
"--class-path", "-classpath", "-cp",
968
"-bootclasspath",
969
"--multi-release"
970
};
971
972
for (String o: fmOptions) {
973
if (fileManager.isSupportedOption(o) == -1)
974
continue;
975
String name = o.replaceAll("^-+", "").replaceAll("-+", "_");
976
printLines(getMessage("main.opt." + name));
977
}
978
979
printLines(getMessage("main.usage.foot"));
980
}
981
982
private void showVersion(boolean full) {
983
printLines(version(full ? "full" : "release"));
984
}
985
986
private void printLines(String msg) {
987
log.println(msg.replace("\n", nl));
988
}
989
990
private static final String nl = System.getProperty("line.separator");
991
992
private static final String versionRBName = "com.sun.tools.javap.resources.version";
993
private static ResourceBundle versionRB;
994
995
private String version(String key) {
996
// key=version: mm.nn.oo[-milestone]
997
// key=full: mm.mm.oo[-milestone]-build
998
if (versionRB == null) {
999
try {
1000
versionRB = ResourceBundle.getBundle(versionRBName);
1001
} catch (MissingResourceException e) {
1002
return getMessage("version.resource.missing", System.getProperty("java.version"));
1003
}
1004
}
1005
try {
1006
return versionRB.getString(key);
1007
}
1008
catch (MissingResourceException e) {
1009
return getMessage("version.unknown", System.getProperty("java.version"));
1010
}
1011
}
1012
1013
private void reportError(String key, Object... args) {
1014
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
1015
}
1016
1017
private void reportNote(String key, Object... args) {
1018
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));
1019
}
1020
1021
private void reportWarning(String key, Object... args) {
1022
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));
1023
}
1024
1025
private Diagnostic<JavaFileObject> createDiagnostic(
1026
final Diagnostic.Kind kind, final String key, final Object... args) {
1027
return new Diagnostic<>() {
1028
public Kind getKind() {
1029
return kind;
1030
}
1031
1032
public JavaFileObject getSource() {
1033
return null;
1034
}
1035
1036
public long getPosition() {
1037
return Diagnostic.NOPOS;
1038
}
1039
1040
public long getStartPosition() {
1041
return Diagnostic.NOPOS;
1042
}
1043
1044
public long getEndPosition() {
1045
return Diagnostic.NOPOS;
1046
}
1047
1048
public long getLineNumber() {
1049
return Diagnostic.NOPOS;
1050
}
1051
1052
public long getColumnNumber() {
1053
return Diagnostic.NOPOS;
1054
}
1055
1056
public String getCode() {
1057
return key;
1058
}
1059
1060
public String getMessage(Locale locale) {
1061
return JavapTask.this.getMessage(locale, key, args);
1062
}
1063
1064
@Override
1065
public String toString() {
1066
return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
1067
}
1068
1069
};
1070
1071
}
1072
1073
public String getMessage(String key, Object... args) {
1074
return getMessage(task_locale, key, args);
1075
}
1076
1077
public String getMessage(Locale locale, String key, Object... args) {
1078
if (bundles == null) {
1079
// could make this a HashMap<Locale,SoftReference<ResourceBundle>>
1080
// and for efficiency, keep a hard reference to the bundle for the task
1081
// locale
1082
bundles = new HashMap<>();
1083
}
1084
1085
if (locale == null)
1086
locale = Locale.getDefault();
1087
1088
ResourceBundle b = bundles.get(locale);
1089
if (b == null) {
1090
try {
1091
b = ResourceBundle.getBundle("com.sun.tools.javap.resources.javap", locale);
1092
bundles.put(locale, b);
1093
} catch (MissingResourceException e) {
1094
throw new InternalError("Cannot find javap resource bundle for locale " + locale);
1095
}
1096
}
1097
1098
try {
1099
return MessageFormat.format(b.getString(key), args);
1100
} catch (MissingResourceException e) {
1101
throw new InternalError(e, key);
1102
}
1103
}
1104
1105
protected Context context;
1106
JavaFileManager fileManager;
1107
JavaFileManager defaultFileManager;
1108
PrintWriter log;
1109
DiagnosticListener<? super JavaFileObject> diagnosticListener;
1110
List<String> classes;
1111
Location moduleLocation;
1112
Options options;
1113
//ResourceBundle bundle;
1114
Locale task_locale;
1115
Map<Locale, ResourceBundle> bundles;
1116
protected Attribute.Factory attributeFactory;
1117
1118
private static final String progname = "javap";
1119
1120
private static class SizeInputStream extends FilterInputStream {
1121
SizeInputStream(InputStream in) {
1122
super(in);
1123
}
1124
1125
int size() {
1126
return size;
1127
}
1128
1129
@Override
1130
public int read(byte[] buf, int offset, int length) throws IOException {
1131
int n = super.read(buf, offset, length);
1132
if (n > 0)
1133
size += n;
1134
return n;
1135
}
1136
1137
@Override
1138
public int read() throws IOException {
1139
int b = super.read();
1140
size += 1;
1141
return b;
1142
}
1143
1144
private int size;
1145
}
1146
}
1147
1148