1 /* 2 * Copyright (c) 2006, 2015, 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 * @library /tools/javac/lib 30 * @modules java.compiler 31 * jdk.compiler 32 * @build TestFilerConstraints 33 * @compile -encoding iso-8859-1 -processor TestFilerConstraints -proc:only TestFilerConstraints.java 34 */ 35 36 import java.util.Set; 37 import javax.annotation.processing.*; 38 import javax.lang.model.SourceVersion; 39 import static javax.lang.model.SourceVersion.*; 40 import javax.lang.model.element.*; 41 import javax.lang.model.util.*; 42 import static javax.lang.model.util.ElementFilter.*; 43 import static javax.tools.Diagnostic.Kind.*; 44 import static javax.tools.StandardLocation.*; 45 46 import java.io.*; 47 import java.nio.charset.Charset; 48 49 /** 50 * A processor that verifies the explicit and implicit constraints in 51 * the Filer contract are maintained: 52 * 53 * <blockquote> 54 * 55 * During each run of an annotation processing tool, a file with a 56 * given pathname may be created only once. If that file already 57 * exists before the first attempt to create it, the old contents 58 * will be deleted. Any subsequent attempt to create the same file 59 * during a run will throw a FilerException, as will attempting to 60 * open both a class file and source file for the same type name. 61 * 62 * </blockquote> 63 * 64 * Specific checks will include: 65 * 66 * <ul> 67 * 68 * <li> Source and class files can be written to from either a Writer or an OutputStream. 69 * 70 * <li> Calling close multiple times does not re-register the file for 71 * processing. 72 * 73 * </ul> 74 */ 75 public class TestFilerConstraints extends JavacTestingAbstractProcessor { 76 private int round = 0; 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 process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)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 /** 171 * Test that the single expected expected type, name, is the root 172 * element. 173 */ testExpectedType(RoundEnvironment roundEnv, String name)174 private void testExpectedType(RoundEnvironment roundEnv, String name) { 175 if (!roundEnv.getRootElements().isEmpty()) { 176 for(TypeElement type : typesIn(roundEnv.getRootElements())) { 177 if (!name.contentEquals(type.getSimpleName())) 178 throw new RuntimeException("Unexpected type " + type.getSimpleName()); 179 } 180 } else 181 throw new RuntimeException("Unexpected empty root elements."); 182 } 183 testReopening()184 private void testReopening() throws IOException { 185 String[] names = {"Src1", "Src2", "ClassFile1"}; 186 for (String name : names) { 187 try { 188 filer.createSourceFile(name); 189 throw new RuntimeException("Opened a source file for type " + name); 190 } catch (FilerException fe) {;} 191 192 try { 193 filer.createClassFile(name); 194 throw new RuntimeException("Opened a class file for type " + name); 195 } catch (FilerException fe) {;} 196 } 197 198 // Try to open a resource over a source file 199 try { 200 filer.createResource(SOURCE_OUTPUT, "", "Src1.java"); 201 throw new RuntimeException("Opened a text file over Src1.java!"); 202 } catch (FilerException fe) {;} 203 204 // Try to open a resource over a class file 205 try { 206 filer.createResource(CLASS_OUTPUT, "", "ClassFile1.class"); 207 throw new RuntimeException("Opened a text file over Src1.java!"); 208 } catch (FilerException fe) {;} 209 210 } 211 212 private int[] classFile1Bytes = 213 {202, 254, 186, 190, 0, 0, 0, 50, 214 0, 13, 10, 0, 3, 0, 10, 7, 215 0, 11, 7, 0, 12, 1, 0, 6, 216 60, 105, 110, 105, 116, 62, 1, 0, 217 3, 40, 41, 86, 1, 0, 4, 67, 218 111, 100, 101, 1, 0, 15, 76, 105, 219 110, 101, 78, 117, 109, 98, 101, 114, 220 84, 97, 98, 108, 101, 1, 0, 10, 221 83, 111, 117, 114, 99, 101, 70, 105, 222 108, 101, 1, 0, 15, 67, 108, 97, 223 115, 115, 70, 105, 108, 101, 49, 46, 224 106, 97, 118, 97, 12, 0, 4, 0, 225 5, 1, 0, 10, 67, 108, 97, 115, 226 115, 70, 105, 108, 101, 49, 1, 0, 227 16, 106, 97, 118, 97, 47, 108, 97, 228 110, 103, 47, 79, 98, 106, 101, 99, 229 116, 0, 33, 0, 2, 0, 3, 0, 230 0, 0, 0, 0, 1, 0, 1, 0, 231 4, 0, 5, 0, 1, 0, 6, 0, 232 0, 0, 29, 0, 1, 0, 1, 0, 233 0, 0, 5, 42, 183, 0, 1, 177, 234 0, 0, 0, 1, 0, 7, 0, 0, 235 0, 6, 0, 1, 0, 0, 0, 1, 236 0, 1, 0, 8, 0, 0, 0, 2, 237 0, 9,}; 238 239 private int[] classFile2Bytes = 240 {202, 254, 186, 190, 0, 0, 0, 50, 241 0, 13, 10, 0, 3, 0, 10, 7, 242 0, 11, 7, 0, 12, 1, 0, 6, 243 60, 105, 110, 105, 116, 62, 1, 0, 244 3, 40, 41, 86, 1, 0, 4, 67, 245 111, 100, 101, 1, 0, 15, 76, 105, 246 110, 101, 78, 117, 109, 98, 101, 114, 247 84, 97, 98, 108, 101, 1, 0, 10, 248 83, 111, 117, 114, 99, 101, 70, 105, 249 108, 101, 1, 0, 15, 67, 108, 97, 250 115, 115, 70, 105, 108, 101, 50, 46, 251 106, 97, 118, 97, 12, 0, 4, 0, 252 5, 1, 0, 10, 67, 108, 97, 115, 253 115, 70, 105, 108, 101, 50, 1, 0, 254 16, 106, 97, 118, 97, 47, 108, 97, 255 110, 103, 47, 79, 98, 106, 101, 99, 256 116, 0, 33, 0, 2, 0, 3, 0, 257 0, 0, 0, 0, 1, 0, 1, 0, 258 4, 0, 5, 0, 1, 0, 6, 0, 259 0, 0, 29, 0, 1, 0, 1, 0, 260 0, 0, 5, 42, 183, 0, 1, 177, 261 0, 0, 0, 1, 0, 7, 0, 0, 262 0, 6, 0, 1, 0, 0, 0, 1, 263 0, 1, 0, 8, 0, 0, 0, 2, 264 0, 9,}; 265 } 266