Thu, 29 Jul 2010 19:30:35 -0700
6966604: JavacFiler not correctly notified of lastRound
Reviewed-by: darcy
1 /*
2 * Copyright (c) 2006, 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 6380018 6453386 6457283
27 * @summary Test that the constraints guaranteed by the Filer and maintained
28 * @author Joseph D. Darcy
29 * @build TestFilerConstraints
30 * @compile -encoding iso-8859-1 -processor TestFilerConstraints -proc:only TestFilerConstraints.java
31 */
33 import java.util.Set;
34 import javax.annotation.processing.*;
35 import javax.lang.model.SourceVersion;
36 import static javax.lang.model.SourceVersion.*;
37 import javax.lang.model.element.*;
38 import javax.lang.model.util.*;
39 import static javax.lang.model.util.ElementFilter.*;
40 import static javax.tools.Diagnostic.Kind.*;
41 import static javax.tools.StandardLocation.*;
43 import java.io.*;
44 import java.nio.charset.Charset;
46 /**
47 * A processor that verifies the explicit and implicit constraints in
48 * the Filer contract are maintained:
49 *
50 * <blockquote>
51 *
52 * During each run of an annotation processing tool, a file with a
53 * given pathname may be created only once. If that file already
54 * exists before the first attempt to create it, the old contents
55 * will be deleted. Any subsequent attempt to create the same file
56 * during a run will throw a FilerException, as will attempting to
57 * open both a class file and source file for the same type name.
58 *
59 * </blockquote>
60 *
61 * Specific checks will include:
62 *
63 * <ul>
64 *
65 * <li> Source and class files can be written to from either a Writer or an OutputStream.
66 *
67 * <li> Calling close multiple times does not re-register the file for
68 * processing.
69 *
70 * </ul>
71 */
72 @SupportedAnnotationTypes("*")
73 public class TestFilerConstraints extends AbstractProcessor {
74 private int round = 0;
75 private Messager messager;
76 private Filer filer;
78 private PrintWriter pw_src1 = null;
79 private PrintWriter pw_src2 = null;
80 private OutputStream os_classFile1 = null;
81 private Writer pw_classFile2 = null;
83 public boolean process(Set<? extends TypeElement> annotations,
84 RoundEnvironment roundEnv) {
85 round++;
87 try {
88 switch(round) {
89 // Open two source files
90 case 1:
91 pw_src1 = new PrintWriter(filer.createSourceFile("Src1").openWriter());
92 pw_src1.println("class Src1 {}");
93 pw_src1.close();
95 // Hold open across rounds
96 pw_src2 = new PrintWriter(new OutputStreamWriter(filer.createSourceFile("Src2").openOutputStream()));
97 break;
99 case 2:
100 testExpectedType(roundEnv, "Src1");
102 // Close Src1 a second time
103 pw_src1.close();
105 pw_src2.println("class Src2 {}");
106 pw_src2.close();
108 break;
110 case 3:
111 testExpectedType(roundEnv, "Src2");
113 // Close Src2 a second time
114 pw_src2.close();
116 os_classFile1 = filer.createClassFile("ClassFile1").openOutputStream();
117 for (int value : classFile1Bytes)
118 os_classFile1.write((byte)value);
119 os_classFile1.close();
121 break;
123 case 4:
124 testExpectedType(roundEnv, "ClassFile1");
126 // Close a second time
127 os_classFile1.close();
129 testReopening();
131 pw_classFile2 = new PrintWriter(filer.createClassFile("ClassFile2",
132 (Element[])null).openWriter());
134 for(int byteVal : classFile2Bytes) {
135 // int value = (0xff00 & (classFile2Bytes[i]<<8)) | classFile2Bytes[i+1];
136 // System.out.print(Integer.toHexString(value));
137 //if ((i % 4) == 0)
138 // System.out.println();
139 pw_classFile2.write((char) (0xff & byteVal));
140 }
141 pw_classFile2.close();
143 break;
147 case 5:
148 testExpectedType(roundEnv, "ClassFile2");
149 // Close a second time
150 pw_classFile2.close();
153 break;
155 case 6:
156 if (!roundEnv.processingOver() && !roundEnv.errorRaised())
157 throw new RuntimeException("Bad round state: " + roundEnv);
158 break;
160 default:
161 throw new RuntimeException("Unexpected round number!");
162 }
163 } catch (IOException ioe) {
164 throw new RuntimeException(ioe);
165 }
167 return true;
168 }
170 public SourceVersion getSupportedSourceVersion() {
171 return SourceVersion.latest();
172 }
174 public void init(ProcessingEnvironment processingEnv) {
175 super.init(processingEnv);
176 messager = processingEnv.getMessager();
177 filer = processingEnv.getFiler();
179 }
181 /**
182 * Test that the single expected expected type, name, is the root
183 * element.
184 */
185 private void testExpectedType(RoundEnvironment roundEnv, String name) {
186 if (!roundEnv.getRootElements().isEmpty()) {
187 for(TypeElement type : typesIn(roundEnv.getRootElements())) {
188 if (!name.contentEquals(type.getSimpleName()))
189 throw new RuntimeException("Unexpected type " + type.getSimpleName());
190 }
191 } else
192 throw new RuntimeException("Unexpected empty root elements.");
193 }
195 private void testReopening() throws IOException {
196 String[] names = {"Src1", "Src2", "ClassFile1"};
197 for (String name : names) {
198 try {
199 filer.createSourceFile(name);
200 throw new RuntimeException("Opened a source file for type " + name);
201 } catch (FilerException fe) {;}
203 try {
204 filer.createClassFile(name);
205 throw new RuntimeException("Opened a class file for type " + name);
206 } catch (FilerException fe) {;}
207 }
209 // Try to open a resource over a source file
210 try {
211 filer.createResource(SOURCE_OUTPUT, "", "Src1.java");
212 throw new RuntimeException("Opened a text file over Src1.java!");
213 } catch (FilerException fe) {;}
215 // Try to open a resource over a class file
216 try {
217 filer.createResource(CLASS_OUTPUT, "", "ClassFile1.class");
218 throw new RuntimeException("Opened a text file over Src1.java!");
219 } catch (FilerException fe) {;}
221 }
223 private int[] classFile1Bytes =
224 {202, 254, 186, 190, 0, 0, 0, 50,
225 0, 13, 10, 0, 3, 0, 10, 7,
226 0, 11, 7, 0, 12, 1, 0, 6,
227 60, 105, 110, 105, 116, 62, 1, 0,
228 3, 40, 41, 86, 1, 0, 4, 67,
229 111, 100, 101, 1, 0, 15, 76, 105,
230 110, 101, 78, 117, 109, 98, 101, 114,
231 84, 97, 98, 108, 101, 1, 0, 10,
232 83, 111, 117, 114, 99, 101, 70, 105,
233 108, 101, 1, 0, 15, 67, 108, 97,
234 115, 115, 70, 105, 108, 101, 49, 46,
235 106, 97, 118, 97, 12, 0, 4, 0,
236 5, 1, 0, 10, 67, 108, 97, 115,
237 115, 70, 105, 108, 101, 49, 1, 0,
238 16, 106, 97, 118, 97, 47, 108, 97,
239 110, 103, 47, 79, 98, 106, 101, 99,
240 116, 0, 33, 0, 2, 0, 3, 0,
241 0, 0, 0, 0, 1, 0, 1, 0,
242 4, 0, 5, 0, 1, 0, 6, 0,
243 0, 0, 29, 0, 1, 0, 1, 0,
244 0, 0, 5, 42, 183, 0, 1, 177,
245 0, 0, 0, 1, 0, 7, 0, 0,
246 0, 6, 0, 1, 0, 0, 0, 1,
247 0, 1, 0, 8, 0, 0, 0, 2,
248 0, 9,};
250 private int[] classFile2Bytes =
251 {202, 254, 186, 190, 0, 0, 0, 50,
252 0, 13, 10, 0, 3, 0, 10, 7,
253 0, 11, 7, 0, 12, 1, 0, 6,
254 60, 105, 110, 105, 116, 62, 1, 0,
255 3, 40, 41, 86, 1, 0, 4, 67,
256 111, 100, 101, 1, 0, 15, 76, 105,
257 110, 101, 78, 117, 109, 98, 101, 114,
258 84, 97, 98, 108, 101, 1, 0, 10,
259 83, 111, 117, 114, 99, 101, 70, 105,
260 108, 101, 1, 0, 15, 67, 108, 97,
261 115, 115, 70, 105, 108, 101, 50, 46,
262 106, 97, 118, 97, 12, 0, 4, 0,
263 5, 1, 0, 10, 67, 108, 97, 115,
264 115, 70, 105, 108, 101, 50, 1, 0,
265 16, 106, 97, 118, 97, 47, 108, 97,
266 110, 103, 47, 79, 98, 106, 101, 99,
267 116, 0, 33, 0, 2, 0, 3, 0,
268 0, 0, 0, 0, 1, 0, 1, 0,
269 4, 0, 5, 0, 1, 0, 6, 0,
270 0, 0, 29, 0, 1, 0, 1, 0,
271 0, 0, 5, 42, 183, 0, 1, 177,
272 0, 0, 0, 1, 0, 7, 0, 0,
273 0, 6, 0, 1, 0, 0, 0, 1,
274 0, 1, 0, 8, 0, 0, 0, 2,
275 0, 9,};
276 }