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 */ 23 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 */ 32 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.*; 42 43 import java.io.*; 44 import java.nio.charset.Charset; 45 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; 77 78 private PrintWriter pw_src1 = null; 79 private PrintWriter pw_src2 = null; 80 private OutputStream os_classFile1 = null; 81 private Writer pw_classFile2 = null; 82 83 public boolean process(Set<? extends TypeElement> annotations, 84 RoundEnvironment roundEnv) { 85 round++; 86 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(); 94 95 // Hold open across rounds 96 pw_src2 = new PrintWriter(new OutputStreamWriter(filer.createSourceFile("Src2").openOutputStream())); 97 break; 98 99 case 2: 100 testExpectedType(roundEnv, "Src1"); 101 102 // Close Src1 a second time 103 pw_src1.close(); 104 105 pw_src2.println("class Src2 {}"); 106 pw_src2.close(); 107 108 break; 109 110 case 3: 111 testExpectedType(roundEnv, "Src2"); 112 113 // Close Src2 a second time 114 pw_src2.close(); 115 116 os_classFile1 = filer.createClassFile("ClassFile1").openOutputStream(); 117 for (int value : classFile1Bytes) 118 os_classFile1.write((byte)value); 119 os_classFile1.close(); 120 121 break; 122 123 case 4: 124 testExpectedType(roundEnv, "ClassFile1"); 125 126 // Close a second time 127 os_classFile1.close(); 128 129 testReopening(); 130 131 pw_classFile2 = new PrintWriter(filer.createClassFile("ClassFile2", 132 (Element[])null).openWriter()); 133 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(); 142 143 break; 144 145 146 147 case 5: 148 testExpectedType(roundEnv, "ClassFile2"); 149 // Close a second time 150 pw_classFile2.close(); 151 152 153 break; 154 155 case 6: 156 if (!roundEnv.processingOver() && !roundEnv.errorRaised()) 157 throw new RuntimeException("Bad round state: " + roundEnv); 158 break; 159 160 default: 161 throw new RuntimeException("Unexpected round number!"); 162 } 163 } catch (IOException ioe) { 164 throw new RuntimeException(ioe); 165 } 166 167 return true; 168 } 169 170 public SourceVersion getSupportedSourceVersion() { 171 return SourceVersion.latest(); 172 } 173 174 public void init(ProcessingEnvironment processingEnv) { 175 super.init(processingEnv); 176 messager = processingEnv.getMessager(); 177 filer = processingEnv.getFiler(); 178 179 } 180 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 } 194 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) {;} 202 203 try { 204 filer.createClassFile(name); 205 throw new RuntimeException("Opened a class file for type " + name); 206 } catch (FilerException fe) {;} 207 } 208 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) {;} 214 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) {;} 220 221 } 222 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,}; 249 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 }