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