Fri, 29 Apr 2011 16:05:29 +0100
7039937: Improved catch analysis fails to handle a common idiom in the libraries
Summary: Disable generation of 'unreachable catch' warnings for catch statements catching Exception/Throwable
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2010, 2011, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24 /**
25 * @test
26 * @bug 6968063
27 * @summary provide examples of code that generate diagnostics
28 * @build ArgTypeCompilerFactory Example HTMLWriter RunExamples
29 * @run main RunExamples
30 */
32 import java.io.*;
33 import java.text.SimpleDateFormat;
34 import java.util.*;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
38 /**
39 * Utility to run selected or all examples, writing results to
40 * stdout, a plain text file or an HTML file. This program can be
41 * run standalone, or as a jtreg test.
42 *
43 * Options:
44 * -examples dir directory of examples. Defaults to ${test.src}/examples
45 * -raw run examples with -XDrawDiagnostics
46 * -showFiles include text of source files in the output
47 * -verbose verbose output
48 * -o file write output to file: format will be HTML if
49 * file has .html extension; otherwise it will be plain text.
50 * default is to stdout
51 * -title string specify a title, only applies to HTML output
52 */
53 public class RunExamples {
54 public static void main(String... args) throws Exception {
55 jtreg = (System.getProperty("test.src") != null);
56 File tmpDir;
57 if (jtreg) {
58 // use standard jtreg scratch directory: the current directory
59 tmpDir = new File(System.getProperty("user.dir"));
60 } else {
61 tmpDir = new File(System.getProperty("java.io.tmpdir"),
62 RunExamples.class.getName()
63 + (new SimpleDateFormat("yyMMddHHmmss")).format(new Date()));
64 }
65 Example.setTempDir(tmpDir);
67 RunExamples r = new RunExamples();
69 try {
70 if (r.run(args))
71 return;
72 } finally {
73 /* VERY IMPORTANT NOTE. In jtreg mode, tmpDir is set to the
74 * jtreg scratch directory, which is the current directory.
75 * In case someone is faking jtreg mode, make sure to only
76 * clean tmpDir when it is reasonable to do so.
77 */
78 if (tmpDir.isDirectory() &&
79 tmpDir.getName().startsWith(RunExamples.class.getName())) {
80 if (clean(tmpDir))
81 tmpDir.delete();
82 }
83 }
85 if (jtreg)
86 throw new Exception(r.errors + " errors occurred");
87 else
88 System.exit(1);
89 }
91 boolean run(String... args) {
92 Set<String> selectedKeys = new TreeSet<String>();
93 Set<Example> selectedExamples = new TreeSet<Example>();
94 File testSrc = new File(System.getProperty("test.src", "."));
95 File examplesDir = new File(testSrc, "examples");
96 File outFile = null;
97 boolean raw = false;
98 boolean showFiles = false;
99 boolean verbose = false;
100 boolean argTypes = false;
101 String title = null;
103 for (int i = 0; i < args.length; i++) {
104 String arg = args[i];
105 if (arg.equals("-k") && (i + 1) < args.length)
106 selectedKeys.add(args[++i]);
107 else if (arg.equals("-examples") && (i + 1) < args.length)
108 examplesDir = new File(args[++i]);
109 else if (arg.equals("-raw"))
110 raw = true;
111 else if (arg.equals("-showFiles"))
112 showFiles = true;
113 else if (arg.equals("-verbose"))
114 verbose = true;
115 else if (arg.equals("-o") && (i + 1) < args.length)
116 outFile = new File(args[++i]);
117 else if (arg.equals("-title") && (i + 1) < args.length)
118 title = args[++i];
119 else if (arg.equals("-argtypes"))
120 argTypes = true;
121 else if (arg.startsWith("-")) {
122 error("unknown option: " + arg);
123 return false;
124 } else {
125 while (i < args.length) {
126 File f = new File(examplesDir, args[i]);
127 selectedExamples.add(new Example(f));
128 i++;
129 }
130 }
131 }
133 // special mode to show message keys and the types of the args that
134 // are used.
135 if (argTypes)
136 Example.Compiler.factory = new ArgTypeCompilerFactory();
138 if (selectedKeys.size() > 0) {
139 Set<Example> examples = getExamples(examplesDir);
140 nextKey:
141 for (String k: selectedKeys) {
142 for (Example e: examples) {
143 if (e.getDeclaredKeys().contains(k))
144 continue nextKey;
145 }
146 error("Key " + k + ": no examples found");
147 }
148 } else {
149 if (selectedExamples.isEmpty())
150 selectedExamples = getExamples(examplesDir);
151 }
153 try {
154 Runner r;
155 if (outFile == null) {
156 PrintWriter out = new PrintWriter(System.out);
157 r = new TextRunner(out, showFiles, raw, verbose);
158 } else if (outFile.getName().endsWith(".html"))
159 r = new HTMLRunner(outFile, showFiles, raw, verbose, title);
160 else
161 r = new TextRunner(outFile, showFiles, raw, verbose);
162 r.run(selectedExamples);
163 r.close();
164 } catch (IOException e) {
165 error("Error writing output: " + e);
166 }
168 return (errors == 0);
169 }
171 /**
172 * Get the complete set of examples to be checked.
173 */
174 Set<Example> getExamples(File examplesDir) {
175 Set<Example> results = new TreeSet<Example>();
176 for (File f: examplesDir.listFiles()) {
177 if (isValidExample(f))
178 results.add(new Example(f));
179 }
180 return results;
181 }
183 boolean isValidExample(File f) {
184 return (f.isDirectory() && (!jtreg || f.list().length > 0)) ||
185 (f.isFile() && f.getName().endsWith(".java"));
186 }
188 /**
189 * Report an error.
190 */
191 void error(String msg) {
192 System.err.println("Error: " + msg);
193 errors++;
194 }
196 static boolean jtreg;
198 int errors;
200 /**
201 * Clean the contents of a directory.
202 */
203 static boolean clean(File dir) {
204 boolean ok = true;
205 for (File f: dir.listFiles()) {
206 if (f.isDirectory())
207 ok &= clean(f);
208 ok &= f.delete();
209 }
210 return ok;
211 }
213 static abstract class Runner {
214 Runner(boolean showFiles, boolean raw, boolean verbose) {
215 this.showFiles = showFiles;
216 this.raw = raw;
217 this.verbose = verbose;
218 }
220 void close() throws IOException { }
222 void run(Collection<Example> examples) throws IOException {
223 for (Example e: examples) {
224 startExample(e);
225 if (showFiles) {
226 showFile(e, e.infoFile);
227 Set<File> srcFiles = new TreeSet<File>(e.srcFiles);
228 srcFiles.remove(e.infoFile);
229 showFiles(e, srcFiles);
230 showFiles(e, e.srcPathFiles);
231 showFiles(e, e.procFiles);
232 showFiles(e, e.supportFiles);
233 }
234 run(e);
235 }
236 }
238 void showFiles(Example e, Collection<File> files) throws IOException {
239 for (File f: files)
240 showFile(e, f);
241 }
243 abstract void startExample(Example e) throws IOException;
245 abstract void showFile(Example e, File f) throws IOException;
247 abstract void run(Example e) throws IOException;
249 protected String read(File f) throws IOException {
250 byte[] bytes = new byte[(int) f.length()];
251 DataInputStream in = new DataInputStream(new FileInputStream(f));
252 try {
253 in.readFully(bytes);
254 } finally {
255 in.close();
256 }
257 return new String(bytes);
258 }
260 protected Pattern copyrightHeaderPat =
261 Pattern.compile("(?s)(/\\*.*?Copyright.*?\\*/\n)\\s*(.*)");
262 protected Pattern infoHeaderPat =
263 Pattern.compile("(?s)((?://\\s*[a-z]+:[^\n]*\n)+)\\s*(.*)");
265 protected boolean showFiles;
266 protected boolean raw;
267 protected boolean verbose;
268 }
270 static class TextRunner extends Runner {
271 TextRunner(File file, boolean showFiles, boolean raw, boolean verbose)
272 throws IOException {
273 super(showFiles, raw, verbose);
274 this.file = file;
275 out = new PrintWriter(new FileWriter(file));
276 }
278 TextRunner(PrintWriter out, boolean showFiles, boolean raw, boolean verbose)
279 throws IOException {
280 super(showFiles, raw, verbose);
281 this.out = out;
282 }
284 @Override
285 void close() {
286 if (file != null)
287 out.close();
288 }
290 @Override
291 void startExample(Example e) {
292 out.println("----- " + e.getName() + " --------------------");
293 out.println();
294 }
296 @Override
297 void showFile(Example e, File f) {
298 out.println("--- " + f);
299 String text;
300 try {
301 text = read(f);
302 } catch (IOException ex) {
303 text = "Error reading " + f + "; " + ex;
304 }
305 Matcher m = copyrightHeaderPat.matcher(text);
306 if (m.matches()) {
307 out.println("(Copyright)");
308 writeLines(m.group(2));
309 } else {
310 writeLines(text);
311 }
312 out.println();
313 }
315 @Override
316 void run(Example e) {
317 // only show Output: header if also showing files
318 if (showFiles)
319 out.println("--- Output:");
320 e.run(out, raw, verbose);
321 out.println();
322 }
324 void writeLines(String text) {
325 for (String line: text.split("\n"))
326 out.println(line);
327 }
329 File file;
330 PrintWriter out;
331 }
333 static class HTMLRunner extends Runner {
334 HTMLRunner(File file, boolean showFiles, boolean raw, boolean verbose, String title)
335 throws IOException {
336 super(showFiles, raw, verbose);
337 this.file = file;
338 PrintWriter out = new PrintWriter(new FileWriter(file));
339 html = new HTMLWriter(out);
340 html.startTag(HTMLWriter.HEAD);
341 if (title != null) {
342 html.startTag(HTMLWriter.TITLE);
343 html.write(title);
344 html.endTag(HTMLWriter.TITLE);
345 }
346 html.startTag(HTMLWriter.STYLE);
347 html.newLine();
348 html.writeLine("div.file { background-color:#e0ffe0; margin-left:30px; margin-right:30px;\n"
349 + " padding: 3px; border: thin solid silver; }");
350 html.writeLine("p.file { white-space: pre-wrap; font-family:monospace; margin: 0; }");
351 html.writeLine("div.output { background-color:#e0e0ff; margin-left:30px; margin-right:30px;\n"
352 + " padding: 3px; border: thin solid silver; }");
353 html.writeLine("p.output { white-space: pre-wrap; font-family:monospace; margin: 0; }");
354 html.writeLine("table.index { border: thin solid silver; }");
355 html.writeLine(".copyright { font-size: x-small }");
356 html.writeLine(".hidden { display:none }");
357 html.writeLine(".unhidden { display:block }");
358 html.writeLine(".odd { background-color: #e0e0e0 }");
359 html.writeLine(".even { background-color: white }");
360 html.endTag(HTMLWriter.STYLE);
361 html.startTag(HTMLWriter.SCRIPT);
362 html.writeAttr(HTMLWriter.TYPE, HTMLWriter.TEXT_JAVASCRIPT);
363 html.writeLine("\nfunction unhide(id) {\n"
364 + " var item = document.getElementById(id);\n"
365 + " if (item) {\n"
366 + " item.className=(item.className=='hidden')?'unhidden':'hidden';\n"
367 + " }\n"
368 + "}");
369 html.endTag(HTMLWriter.SCRIPT);
370 html.endTag(HTMLWriter.HEAD);
371 html.startTag(HTMLWriter.BODY);
372 if (title != null) {
373 html.startTag(TITLE_HEADER);
374 html.write(title);
375 html.endTag(TITLE_HEADER);
376 }
377 }
379 @Override
380 void close() throws IOException {
381 html.endTag(HTMLWriter.BODY);
382 html.newLine();
383 html.flush();
384 }
386 @Override
387 void run(Collection<Example> examples) throws IOException {
388 if (examples.size() > 1)
389 writeIndex(examples);
390 super.run(examples);
391 }
393 void writeIndex(Collection<Example> examples) throws IOException {
394 Map<String, Set<Example>> index = new TreeMap<String, Set<Example>>();
395 Set<String> initials = new HashSet<String>();
396 for (Example e: examples) {
397 for (String k: e.getDeclaredKeys()) {
398 Set<Example> s = index.get(k);
399 if (s == null)
400 index.put(k, s = new TreeSet<Example>());
401 s.add(e);
402 }
403 initials.add(e.getName().substring(0, 1).toUpperCase());
404 }
407 if (INDEX_HEADER != null) {
408 html.startTag(INDEX_HEADER);
409 html.write("Index");
410 html.endTag(INDEX_HEADER);
411 }
413 html.startTag(HTMLWriter.P);
414 html.writeLine("Examples: ");
415 for (char initial = 'A'; initial <= 'Z'; initial++) {
416 String s = String.valueOf(initial);
417 if (initials.contains(s)) {
418 html.writeLink("#" + s, s);
419 } else {
420 html.write(s);
421 }
422 html.newLine();
423 }
424 html.endTag(HTMLWriter.P);
426 html.startTag(HTMLWriter.TABLE);
427 html.writeAttr(HTMLWriter.CLASS, "index");
428 html.newLine();
429 int row = 0;
430 for (Map.Entry<String, Set<Example>> entry: index.entrySet()) {
431 html.startTag(HTMLWriter.TR);
432 html.writeAttr(HTMLWriter.CLASS,
433 (row++ % 2 == 0 ? "even" : "odd"));
434 html.startTag(HTMLWriter.TD);
435 html.writeAttr("valign", "top");
436 html.write(entry.getKey());
437 html.endTag(HTMLWriter.TD);
438 html.newLine();
439 html.startTag(HTMLWriter.TD);
440 html.writeAttr(HTMLWriter.ALIGN, "top");
441 String sep = "";
442 for (Example e: entry.getValue()) {
443 html.write(sep);
444 html.writeLink('#' + e.getName(), e.getName());
445 sep = ", ";
446 }
447 html.endTag(HTMLWriter.TD);
448 html.endTag(HTMLWriter.TR);
449 html.newLine();
450 }
451 html.endTag(HTMLWriter.TABLE);
452 }
454 @Override
455 void startExample(Example e) throws IOException {
456 String name = e.getName();
457 String initial = name.substring(0, 1).toUpperCase();
458 if (!initial.equals(currInitial)) {
459 html.writeLinkDestination(initial, "");
460 currInitial = initial;
461 }
462 html.writeLinkDestination(name, "");
463 html.startTag(EXAMPLE_HEADER);
464 html.write(e.getName());
465 html.endTag(EXAMPLE_HEADER);
466 }
468 @Override
469 void showFile(Example e, File f) throws IOException {
470 String text;
471 try {
472 text = read(f);
473 } catch (IOException ex) {
474 text = "Error reading " + f + ": " + ex;
475 }
476 if (!f.equals(e.file)) {
477 html.startTag(FILE_HEADER);
478 html.write(e.file.toURI().relativize(f.toURI()).toString());
479 html.endTag(FILE_HEADER);
480 }
481 html.startTag(HTMLWriter.DIV);
482 html.writeAttr(CLASS, FILE);
484 String legalHeader;
485 Matcher m1 = copyrightHeaderPat.matcher(text);
486 if (m1.matches()) {
487 legalHeader = m1.group(1);
488 text = m1.group(2);
489 } else
490 legalHeader = null;
492 String infoHeader;
493 Matcher m2 = infoHeaderPat.matcher(text);
494 if (m2.matches()) {
495 infoHeader = m2.group(1);
496 text = m2.group(2);
497 } else
498 infoHeader = null;
500 String legalId = null, infoId = null;
501 if (legalHeader != null || infoHeader != null) {
502 String sep = "";
503 html.startTag(HTMLWriter.SPAN);
504 html.writeStyleAttr("float: right");
505 if (legalHeader != null) {
506 legalId = nextId();
507 html.startTag(HTMLWriter.A);
508 html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + legalId + "');");
509 //html.writeEntity("©");
510 html.write("Copyright");
511 html.endTag(HTMLWriter.A);
512 sep = ", ";
513 }
514 if (infoHeader != null) {
515 html.write(sep);
516 infoId = nextId();
517 html.startTag(HTMLWriter.A);
518 html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + infoId + "');");
519 html.write("Info");
520 html.endTag(HTMLWriter.A);
521 sep = ", ";
522 }
523 html.endTag(HTMLWriter.SPAN);
524 }
526 html.startTag(HTMLWriter.P);
527 html.writeAttr(CLASS, FILE);
528 if (legalHeader != null) {
529 html.startTag(HTMLWriter.SPAN);
530 html.writeAttr(HTMLWriter.CLASS, "hidden");
531 html.writeAttr(HTMLWriter.ID, legalId);
532 html.write(legalHeader);
533 html.newLine();
534 html.endTag(HTMLWriter.SPAN);
535 }
536 if (infoHeader != null) {
537 html.startTag(HTMLWriter.SPAN);
538 html.writeAttr(HTMLWriter.CLASS, "hidden");
539 html.writeAttr(HTMLWriter.ID, infoId);
540 html.write(infoHeader);
541 html.newLine();
542 html.endTag(HTMLWriter.SPAN);
543 }
544 html.write(text);
545 html.endTag(HTMLWriter.P);
547 html.endTag(HTMLWriter.DIV);
548 }
550 @Override
551 void run(Example e) throws IOException {
552 StringWriter sw = new StringWriter();
553 PrintWriter pw = new PrintWriter(sw);
554 e.run(pw, raw, verbose);
555 pw.flush();
557 // only show Output: header if also showing files
558 if (showFiles) {
559 html.startTag(OUTPUT_HEADER);
560 html.write("Output:");
561 html.endTag(OUTPUT_HEADER);
562 }
564 html.startTag(HTMLWriter.DIV);
565 html.writeAttr(CLASS, OUTPUT);
566 html.startTag(HTMLWriter.P);
567 html.writeAttr(CLASS, OUTPUT);
568 String[] lines = sw.toString().split("\n");
569 for (String line: lines) {
570 html.write(line);
571 html.newLine();
572 }
573 html.endTag(HTMLWriter.P);
574 html.endTag(HTMLWriter.DIV);
575 }
577 String nextId() {
578 return "id" + (nextId++);
579 }
581 File file;
582 HTMLWriter html;
583 int nextId;
584 String currInitial = "";
586 static final String TITLE_HEADER = HTMLWriter.H3;
587 static final String INDEX_HEADER = HTMLWriter.H4;
588 static final String EXAMPLE_HEADER = HTMLWriter.H4;
589 static final String FILE_HEADER = HTMLWriter.H5;
590 static final String OUTPUT_HEADER = HTMLWriter.H5;
591 static final String CLASS = "class";
592 static final String FILE = "file";
593 static final String OUTPUT = "output";
594 }
595 }