Mon, 17 Oct 2011 12:57:36 +0100
7093325: Redundant entry in bytecode exception table
Summary: Inlining of finalizers does not update gaps list accordingly
Reviewed-by: jjg
jjg@483 | 1 | /* |
ohair@554 | 2 | * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. |
jjg@483 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jjg@483 | 4 | * |
jjg@483 | 5 | * This code is free software; you can redistribute it and/or modify it |
jjg@483 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jjg@483 | 7 | * published by the Free Software Foundation. |
jjg@483 | 8 | * |
jjg@483 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jjg@483 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jjg@483 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jjg@483 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
jjg@483 | 13 | * accompanied this code). |
jjg@483 | 14 | * |
jjg@483 | 15 | * You should have received a copy of the GNU General Public License version |
jjg@483 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
jjg@483 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jjg@483 | 18 | * |
ohair@554 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@554 | 20 | * or visit www.oracle.com if you need additional information or have any |
ohair@554 | 21 | * questions. |
jjg@483 | 22 | */ |
jjg@483 | 23 | |
jjg@483 | 24 | /* |
jjg@483 | 25 | * @test |
jjg@483 | 26 | * @bug 6920317 |
jjg@483 | 27 | * @summary package-info.java file has to be specified on the javac cmdline, else it will not be avail |
darcy@699 | 28 | * @library ../lib |
jjg@483 | 29 | */ |
jjg@483 | 30 | |
jjg@483 | 31 | import java.io.*; |
jjg@483 | 32 | import java.util.*; |
jjg@483 | 33 | import javax.annotation.processing.*; |
jjg@483 | 34 | import javax.lang.model.*; |
jjg@483 | 35 | import javax.lang.model.element.*; |
jjg@483 | 36 | import javax.lang.model.util.*; |
jjg@483 | 37 | import javax.tools.*; |
jjg@483 | 38 | |
jjg@483 | 39 | /** |
jjg@483 | 40 | * The test exercises different ways of providing annotations for a package. |
jjg@483 | 41 | * Each way provides an annotation with a unique argument. For each test |
jjg@483 | 42 | * case, the test verifies that the annotation with the correct argument is |
jjg@483 | 43 | * found by the compiler. |
jjg@483 | 44 | */ |
jjg@483 | 45 | public class T6920317 { |
jjg@483 | 46 | public static void main(String... args) throws Exception { |
jjg@483 | 47 | new T6920317().run(args); |
jjg@483 | 48 | } |
jjg@483 | 49 | |
jjg@483 | 50 | // Used to describe properties of files to be put on command line, source path, class path |
jjg@483 | 51 | enum Kind { |
jjg@483 | 52 | /** File is not used. */ |
jjg@483 | 53 | NONE, |
jjg@483 | 54 | /** File is used. */ |
jjg@483 | 55 | OLD, |
jjg@483 | 56 | /** Only applies to files on classpath/sourcepath, when there is another file on the |
jjg@483 | 57 | * other path of type OLD, in which case, this file must be newer than the other one. */ |
jjg@483 | 58 | NEW, |
jjg@483 | 59 | /** Only applies to files on classpath/sourcepath, when there is no file in any other |
jjg@483 | 60 | * location, in which case, this file will be generated by the annotation processor. */ |
jjg@483 | 61 | GEN |
jjg@483 | 62 | } |
jjg@483 | 63 | |
jjg@483 | 64 | void run(String... args) throws Exception { |
jjg@483 | 65 | // if no args given, all test cases are run |
jjg@483 | 66 | // if args given, they indicate the test cases to be run |
jjg@483 | 67 | for (int i = 0; i < args.length; i++) { |
jjg@483 | 68 | tests.add(Integer.valueOf(args[i])); |
jjg@483 | 69 | } |
jjg@483 | 70 | |
jjg@483 | 71 | setup(); |
jjg@483 | 72 | |
jjg@483 | 73 | // Run tests for all combinations of files on command line, source path and class path. |
jjg@483 | 74 | // Invalid combinations are skipped in the test method |
jjg@483 | 75 | for (Kind cmdLine: EnumSet.of(Kind.NONE, Kind.OLD)) { |
jjg@483 | 76 | for (Kind srcPath: Kind.values()) { |
jjg@483 | 77 | for (Kind clsPath: Kind.values()) { |
jjg@483 | 78 | try { |
jjg@483 | 79 | test(cmdLine, srcPath, clsPath); |
jjg@483 | 80 | } catch (Exception e) { |
jjg@483 | 81 | e.printStackTrace(); |
jjg@483 | 82 | error("Exception " + e); |
jjg@483 | 83 | // uncomment to stop on first failed test case |
jjg@483 | 84 | // throw e; |
jjg@483 | 85 | } |
jjg@483 | 86 | } |
jjg@483 | 87 | } |
jjg@483 | 88 | } |
jjg@483 | 89 | |
jjg@483 | 90 | if (errors > 0) |
jjg@483 | 91 | throw new Exception(errors + " errors occurred"); |
jjg@483 | 92 | } |
jjg@483 | 93 | |
jjg@483 | 94 | /** One time setup for files and directories to be used in the various test cases. */ |
jjg@483 | 95 | void setup() throws Exception { |
jjg@483 | 96 | // Annotation used in test cases to annotate package. This file is |
jjg@483 | 97 | // given on the command line in test cases. |
jjg@483 | 98 | test_java = writeFile("Test.java", "package p; @interface Test { String value(); }"); |
jjg@483 | 99 | // Compile the annotation for use later in setup |
jjg@483 | 100 | File tmpClasses = new File("tmp.classes"); |
jjg@483 | 101 | compile(tmpClasses, new String[] { }, test_java); |
jjg@483 | 102 | |
jjg@483 | 103 | // package-info file to use on the command line when requied |
jjg@483 | 104 | cl_pkgInfo_java = writeFile("cl/p/package-info.java", "@Test(\"CL\") package p;"); |
jjg@483 | 105 | |
jjg@483 | 106 | // source path containing package-info |
jjg@483 | 107 | sp_old = new File("src.old"); |
jjg@483 | 108 | writeFile("src.old/p/package-info.java", "@Test(\"SP_OLD\") package p;"); |
jjg@483 | 109 | |
jjg@483 | 110 | // class path containing package-info |
jjg@483 | 111 | cp_old = new File("classes.old"); |
jjg@483 | 112 | compile(cp_old, new String[] { "-classpath", tmpClasses.getPath() }, |
jjg@483 | 113 | writeFile("tmp.old/p/package-info.java", "@Test(\"CP_OLD\") package p;")); |
jjg@483 | 114 | |
jjg@483 | 115 | // source path containing package-info which is newer than the one in cp-old |
jjg@483 | 116 | sp_new = new File("src.new"); |
jjg@483 | 117 | File old_class = new File(cp_old, "p/package-info.class"); |
jjg@483 | 118 | writeFile("src.new/p/package-info.java", "@Test(\"SP_NEW\") package p;", old_class); |
jjg@483 | 119 | |
jjg@483 | 120 | // class path containing package-info which is newer than the one in sp-old |
jjg@483 | 121 | cp_new = new File("classes.new"); |
jjg@483 | 122 | File old_java = new File(sp_old, "p/package-info.java"); |
jjg@483 | 123 | compile(cp_new, new String[] { "-classpath", tmpClasses.getPath() }, |
jjg@483 | 124 | writeFile("tmp.new/p/package-info.java", "@Test(\"CP_NEW\") package p;", old_java)); |
jjg@483 | 125 | |
jjg@483 | 126 | // directory containing package-info.java to be "generated" later by annotation processor |
jjg@483 | 127 | sp_gen = new File("src.gen"); |
jjg@483 | 128 | writeFile("src.gen/p/package-info.java", "@Test(\"SP_GEN\") package p;"); |
jjg@483 | 129 | |
jjg@483 | 130 | // directory containing package-info.class to be "generated" later by annotation processor |
jjg@483 | 131 | cp_gen = new File("classes.gen"); |
jjg@483 | 132 | compile(cp_gen, new String[] { "-classpath", tmpClasses.getPath() }, |
jjg@483 | 133 | writeFile("tmp.gen/p/package-info.java", "@Test(\"CP_GEN\") package p;")); |
jjg@483 | 134 | } |
jjg@483 | 135 | |
jjg@483 | 136 | void test(Kind cl, Kind sp, Kind cp) throws Exception { |
jjg@483 | 137 | if (skip(cl, sp, cp)) |
jjg@483 | 138 | return; |
jjg@483 | 139 | |
jjg@483 | 140 | ++count; |
jjg@483 | 141 | // if test cases specified, skip this test case if not selected |
jjg@483 | 142 | if (tests.size() > 0 && !tests.contains(count)) |
jjg@483 | 143 | return; |
jjg@483 | 144 | |
jjg@483 | 145 | System.err.println("Test " + count + " cl:" + cl + " sp:" + sp + " cp:" + cp); |
jjg@483 | 146 | |
jjg@483 | 147 | // test specific tmp directory |
jjg@483 | 148 | File test_tmp = new File("tmp.test" + count); |
jjg@483 | 149 | test_tmp.mkdirs(); |
jjg@483 | 150 | |
jjg@483 | 151 | // build up list of options and files to be compiled |
jjg@483 | 152 | List<String> opts = new ArrayList<String>(); |
jjg@483 | 153 | List<File> files = new ArrayList<File>(); |
jjg@483 | 154 | |
jjg@483 | 155 | // expected value for annotation |
jjg@483 | 156 | String expect = null; |
jjg@483 | 157 | |
jjg@483 | 158 | opts.add("-processorpath"); |
jjg@483 | 159 | opts.add(System.getProperty("test.classes")); |
jjg@483 | 160 | opts.add("-processor"); |
jjg@483 | 161 | opts.add(Processor.class.getName()); |
jjg@483 | 162 | opts.add("-proc:only"); |
jjg@483 | 163 | opts.add("-d"); |
jjg@483 | 164 | opts.add(test_tmp.getPath()); |
jjg@483 | 165 | //opts.add("-verbose"); |
jjg@483 | 166 | files.add(test_java); |
jjg@483 | 167 | |
jjg@483 | 168 | /* |
jjg@483 | 169 | * Analyze each of cl, cp, sp, building up the options and files to |
jjg@483 | 170 | * be compiled, and determining the expected outcome fo the test case. |
jjg@483 | 171 | */ |
jjg@483 | 172 | |
jjg@483 | 173 | // command line file: either omitted or given |
jjg@483 | 174 | if (cl == Kind.OLD) { |
jjg@483 | 175 | files.add(cl_pkgInfo_java); |
jjg@483 | 176 | // command line files always supercede files on paths |
jjg@483 | 177 | expect = "CL"; |
jjg@483 | 178 | } |
jjg@483 | 179 | |
jjg@483 | 180 | // source path: |
jjg@483 | 181 | switch (sp) { |
jjg@483 | 182 | case NONE: |
jjg@483 | 183 | break; |
jjg@483 | 184 | |
jjg@483 | 185 | case OLD: |
jjg@483 | 186 | opts.add("-sourcepath"); |
jjg@483 | 187 | opts.add(sp_old.getPath()); |
jjg@483 | 188 | if (expect == null && cp == Kind.NONE) { |
jjg@483 | 189 | assert cl == Kind.NONE && cp == Kind.NONE; |
jjg@483 | 190 | expect = "SP_OLD"; |
jjg@483 | 191 | } |
jjg@483 | 192 | break; |
jjg@483 | 193 | |
jjg@483 | 194 | case NEW: |
jjg@483 | 195 | opts.add("-sourcepath"); |
jjg@483 | 196 | opts.add(sp_new.getPath()); |
jjg@483 | 197 | if (expect == null) { |
jjg@483 | 198 | assert cl == Kind.NONE && cp == Kind.OLD; |
jjg@483 | 199 | expect = "SP_NEW"; |
jjg@483 | 200 | } |
jjg@483 | 201 | break; |
jjg@483 | 202 | |
jjg@483 | 203 | case GEN: |
jjg@483 | 204 | opts.add("-Agen=" + new File(sp_gen, "p/package-info.java")); |
jjg@483 | 205 | assert cl == Kind.NONE && cp == Kind.NONE; |
jjg@483 | 206 | expect = "SP_GEN"; |
jjg@483 | 207 | break; |
jjg@483 | 208 | } |
jjg@483 | 209 | |
jjg@483 | 210 | // class path: |
jjg@483 | 211 | switch (cp) { |
jjg@483 | 212 | case NONE: |
jjg@483 | 213 | break; |
jjg@483 | 214 | |
jjg@483 | 215 | case OLD: |
jjg@483 | 216 | opts.add("-classpath"); |
jjg@483 | 217 | opts.add(cp_old.getPath()); |
jjg@483 | 218 | if (expect == null && sp == Kind.NONE) { |
jjg@483 | 219 | assert cl == Kind.NONE && sp == Kind.NONE; |
jjg@483 | 220 | expect = "CP_OLD"; |
jjg@483 | 221 | } |
jjg@483 | 222 | break; |
jjg@483 | 223 | |
jjg@483 | 224 | case NEW: |
jjg@483 | 225 | opts.add("-classpath"); |
jjg@483 | 226 | opts.add(cp_new.getPath()); |
jjg@483 | 227 | if (expect == null) { |
jjg@483 | 228 | assert cl == Kind.NONE && sp == Kind.OLD; |
jjg@483 | 229 | expect = "CP_NEW"; |
jjg@483 | 230 | } |
jjg@483 | 231 | break; |
jjg@483 | 232 | |
jjg@483 | 233 | case GEN: |
jjg@483 | 234 | opts.add("-Agen=" + new File(cp_gen, "p/package-info.class")); |
jjg@483 | 235 | assert cl == Kind.NONE && sp == Kind.NONE; |
jjg@483 | 236 | expect = "CP_GEN"; |
jjg@483 | 237 | break; |
jjg@483 | 238 | } |
jjg@483 | 239 | |
jjg@483 | 240 | // pass expected value to annotation processor |
jjg@483 | 241 | assert expect != null; |
jjg@483 | 242 | opts.add("-Aexpect=" + expect); |
jjg@483 | 243 | |
jjg@483 | 244 | // compile the files with the options that have been built up |
jjg@483 | 245 | compile(opts, files); |
jjg@483 | 246 | } |
jjg@483 | 247 | |
jjg@483 | 248 | /** |
jjg@483 | 249 | * Return true if this combination of parameters does not identify a useful test case. |
jjg@483 | 250 | */ |
jjg@483 | 251 | boolean skip(Kind cl, Kind sp, Kind cp) { |
jjg@483 | 252 | // skip if no package files required |
jjg@483 | 253 | if (cl == Kind.NONE && sp == Kind.NONE && cp == Kind.NONE) |
jjg@483 | 254 | return true; |
jjg@483 | 255 | |
jjg@483 | 256 | // skip if both sp and sp are OLD, since results may be indeterminate |
jjg@483 | 257 | if (sp == Kind.OLD && cp == Kind.OLD) |
jjg@483 | 258 | return true; |
jjg@483 | 259 | |
jjg@483 | 260 | // skip if sp or cp is NEW but the other is not OLD |
jjg@483 | 261 | if ((sp == Kind.NEW && cp != Kind.OLD) || (cp == Kind.NEW && sp != Kind.OLD)) |
jjg@483 | 262 | return true; |
jjg@483 | 263 | |
jjg@483 | 264 | // only use GEN if no other package-info files present |
jjg@483 | 265 | if (sp == Kind.GEN && !(cl == Kind.NONE && cp == Kind.NONE) || |
jjg@483 | 266 | cp == Kind.GEN && !(cl == Kind.NONE && sp == Kind.NONE)) { |
jjg@483 | 267 | return true; |
jjg@483 | 268 | } |
jjg@483 | 269 | |
jjg@483 | 270 | // remaining combinations are valid |
jjg@483 | 271 | return false; |
jjg@483 | 272 | } |
jjg@483 | 273 | |
jjg@483 | 274 | /** Write a file with a given body. */ |
jjg@483 | 275 | File writeFile(String path, String body) throws Exception { |
jjg@483 | 276 | File f = new File(path); |
jjg@483 | 277 | if (f.getParentFile() != null) |
jjg@483 | 278 | f.getParentFile().mkdirs(); |
jjg@483 | 279 | Writer out = new FileWriter(path); |
jjg@483 | 280 | try { |
jjg@483 | 281 | out.write(body); |
jjg@483 | 282 | } finally { |
jjg@483 | 283 | out.close(); |
jjg@483 | 284 | } |
jjg@483 | 285 | return f; |
jjg@483 | 286 | } |
jjg@483 | 287 | |
jjg@483 | 288 | /** Write a file with a given body, ensuring that the file is newer than a reference file. */ |
jjg@483 | 289 | File writeFile(String path, String body, File ref) throws Exception { |
jjg@483 | 290 | for (int i = 0; i < 5; i++) { |
jjg@483 | 291 | File f = writeFile(path, body); |
jjg@483 | 292 | if (f.lastModified() > ref.lastModified()) |
jjg@483 | 293 | return f; |
jjg@483 | 294 | Thread.sleep(2000); |
jjg@483 | 295 | } |
jjg@483 | 296 | throw new Exception("cannot create file " + path + " newer than " + ref); |
jjg@483 | 297 | } |
jjg@483 | 298 | |
jjg@483 | 299 | /** Compile a file to a given directory, with options provided. */ |
jjg@483 | 300 | void compile(File dir, String[] opts, File src) throws Exception { |
jjg@483 | 301 | dir.mkdirs(); |
jjg@483 | 302 | List<String> opts2 = new ArrayList<String>(); |
jjg@483 | 303 | opts2.addAll(Arrays.asList("-d", dir.getPath())); |
jjg@483 | 304 | opts2.addAll(Arrays.asList(opts)); |
jjg@483 | 305 | compile(opts2, Collections.singletonList(src)); |
jjg@483 | 306 | } |
jjg@483 | 307 | |
jjg@483 | 308 | /** Compile files with options provided. */ |
jjg@483 | 309 | void compile(List<String> opts, List<File> files) throws Exception { |
jjg@483 | 310 | System.err.println("javac: " + opts + " " + files); |
jjg@483 | 311 | List<String> args = new ArrayList<String>(); |
jjg@483 | 312 | args.addAll(opts); |
jjg@483 | 313 | for (File f: files) |
jjg@483 | 314 | args.add(f.getPath()); |
jjg@483 | 315 | StringWriter sw = new StringWriter(); |
jjg@483 | 316 | PrintWriter pw = new PrintWriter(sw); |
jjg@483 | 317 | int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); |
jjg@483 | 318 | pw.flush(); |
jjg@483 | 319 | if (sw.getBuffer().length() > 0) |
jjg@483 | 320 | System.err.println(sw.toString()); |
jjg@483 | 321 | if (rc != 0) |
jjg@483 | 322 | throw new Exception("compilation failed: rc=" + rc); |
jjg@483 | 323 | } |
jjg@483 | 324 | |
jjg@483 | 325 | /** Report an error. */ |
jjg@483 | 326 | void error(String msg) { |
jjg@483 | 327 | System.err.println("Error: " + msg); |
jjg@483 | 328 | errors++; |
jjg@483 | 329 | } |
jjg@483 | 330 | |
jjg@483 | 331 | /** Test case counter. */ |
jjg@483 | 332 | int count; |
jjg@483 | 333 | |
jjg@483 | 334 | /** Number of errors found. */ |
jjg@483 | 335 | int errors; |
jjg@483 | 336 | |
jjg@483 | 337 | /** Optional set of test cases to be run; empty implies all test cases. */ |
jjg@483 | 338 | Set<Integer> tests = new HashSet<Integer>(); |
jjg@483 | 339 | |
jjg@483 | 340 | /* Files created by setup. */ |
jjg@483 | 341 | File test_java; |
jjg@483 | 342 | File sp_old; |
jjg@483 | 343 | File sp_new; |
jjg@483 | 344 | File sp_gen; |
jjg@483 | 345 | File cp_old; |
jjg@483 | 346 | File cp_new; |
jjg@483 | 347 | File cp_gen; |
jjg@483 | 348 | File cl_pkgInfo_java; |
jjg@483 | 349 | |
jjg@483 | 350 | /** Annotation processor used to verify the expected value for the |
jjg@483 | 351 | package annotations found by javac. */ |
jjg@483 | 352 | @SupportedOptions({ "gen", "expect" }) |
darcy@699 | 353 | public static class Processor extends JavacTestingAbstractProcessor { |
jjg@483 | 354 | public boolean process(Set<? extends TypeElement> annots, RoundEnvironment renv) { |
jjg@483 | 355 | round++; |
jjg@483 | 356 | System.err.println("Round " + round + " annots:" + annots + " rootElems:" + renv.getRootElements()); |
jjg@483 | 357 | |
jjg@483 | 358 | // if this is the first round and the gen option is given, use the filer to create |
jjg@483 | 359 | // a copy of the file specified by the gen option. |
jjg@483 | 360 | String gen = getOption("gen"); |
jjg@483 | 361 | if (round == 1 && gen != null) { |
jjg@483 | 362 | try { |
jjg@483 | 363 | Filer filer = processingEnv.getFiler(); |
jjg@483 | 364 | JavaFileObject f; |
jjg@483 | 365 | if (gen.endsWith(".java")) |
jjg@483 | 366 | f = filer.createSourceFile("p.package-info"); |
jjg@483 | 367 | else |
jjg@483 | 368 | f = filer.createClassFile("p.package-info"); |
jjg@483 | 369 | System.err.println("copy " + gen + " to " + f.getName()); |
jjg@483 | 370 | write(f, read(new File(gen))); |
jjg@483 | 371 | } catch (IOException e) { |
jjg@483 | 372 | error("Cannot create package-info file: " + e); |
jjg@483 | 373 | } |
jjg@483 | 374 | } |
jjg@483 | 375 | |
jjg@483 | 376 | // if annotation processing is complete, verify the package annotation |
jjg@483 | 377 | // found by the compiler. |
jjg@483 | 378 | if (renv.processingOver()) { |
jjg@483 | 379 | System.err.println("final round"); |
jjg@483 | 380 | Elements eu = processingEnv.getElementUtils(); |
jjg@483 | 381 | TypeElement te = eu.getTypeElement("p.Test"); |
jjg@483 | 382 | PackageElement pe = eu.getPackageOf(te); |
jjg@483 | 383 | System.err.println("final: te:" + te + " pe:" + pe); |
jjg@483 | 384 | List<? extends AnnotationMirror> annos = pe.getAnnotationMirrors(); |
jjg@483 | 385 | System.err.println("final: annos:" + annos); |
jjg@483 | 386 | if (annos.size() == 1) { |
jjg@483 | 387 | String expect = "@" + te + "(\"" + getOption("expect") + "\")"; |
jjg@483 | 388 | String actual = annos.get(0).toString(); |
jjg@483 | 389 | checkEqual("package annotations", actual, expect); |
jjg@483 | 390 | } else { |
jjg@483 | 391 | error("Wrong number of annotations found: (" + annos.size() + ") " + annos); |
jjg@483 | 392 | } |
jjg@483 | 393 | } |
jjg@483 | 394 | |
jjg@483 | 395 | return true; |
jjg@483 | 396 | } |
jjg@483 | 397 | |
jjg@483 | 398 | /** Get an option given to the annotation processor. */ |
jjg@483 | 399 | String getOption(String name) { |
jjg@483 | 400 | return processingEnv.getOptions().get(name); |
jjg@483 | 401 | } |
jjg@483 | 402 | |
jjg@483 | 403 | /** Read a file. */ |
jjg@483 | 404 | byte[] read(File file) { |
jjg@483 | 405 | byte[] bytes = new byte[(int) file.length()]; |
jjg@483 | 406 | DataInputStream in = null; |
jjg@483 | 407 | try { |
jjg@483 | 408 | in = new DataInputStream(new FileInputStream(file)); |
jjg@483 | 409 | in.readFully(bytes); |
jjg@483 | 410 | } catch (IOException e) { |
jjg@483 | 411 | error("Error reading file: " + e); |
jjg@483 | 412 | } finally { |
jjg@483 | 413 | if (in != null) { |
jjg@483 | 414 | try { |
jjg@483 | 415 | in.close(); |
jjg@483 | 416 | } catch (IOException e) { |
jjg@483 | 417 | error("Error closing file: " + e); |
jjg@483 | 418 | } |
jjg@483 | 419 | } |
jjg@483 | 420 | } |
jjg@483 | 421 | return bytes; |
jjg@483 | 422 | } |
jjg@483 | 423 | |
jjg@483 | 424 | /** Write a file. */ |
jjg@483 | 425 | void write(JavaFileObject file, byte[] bytes) { |
jjg@483 | 426 | OutputStream out = null; |
jjg@483 | 427 | try { |
jjg@483 | 428 | out = file.openOutputStream(); |
jjg@483 | 429 | out.write(bytes, 0, bytes.length); |
jjg@483 | 430 | } catch (IOException e) { |
jjg@483 | 431 | error("Error writing file: " + e); |
jjg@483 | 432 | } finally { |
jjg@483 | 433 | if (out != null) { |
jjg@483 | 434 | try { |
jjg@483 | 435 | out.close(); |
jjg@483 | 436 | } catch (IOException e) { |
jjg@483 | 437 | error("Error closing file: " + e); |
jjg@483 | 438 | } |
jjg@483 | 439 | } |
jjg@483 | 440 | } |
jjg@483 | 441 | } |
jjg@483 | 442 | |
jjg@483 | 443 | /** Check two strings are equal, and report an error if they are not. */ |
jjg@483 | 444 | private void checkEqual(String label, String actual, String expect) { |
jjg@483 | 445 | if (!actual.equals(expect)) { |
jjg@483 | 446 | error("Unexpected value for " + label + "; actual=" + actual + ", expected=" + expect); |
jjg@483 | 447 | } |
jjg@483 | 448 | } |
jjg@483 | 449 | |
jjg@483 | 450 | /** Report an error to the annotation processing system. */ |
jjg@483 | 451 | void error(String msg) { |
jjg@483 | 452 | Messager messager = processingEnv.getMessager(); |
jjg@483 | 453 | messager.printMessage(Diagnostic.Kind.ERROR, msg); |
jjg@483 | 454 | } |
jjg@483 | 455 | |
jjg@483 | 456 | int round; |
jjg@483 | 457 | } |
jjg@483 | 458 | } |