duke@1: /* darcy@699: * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as duke@1: * published by the Free Software Foundation. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: /* duke@1: * @test duke@1: * @bug 6380018 6453386 6457283 duke@1: * @summary Test that the constraints guaranteed by the Filer and maintained duke@1: * @author Joseph D. Darcy darcy@1466: * @library /tools/javac/lib duke@1: * @build TestFilerConstraints duke@1: * @compile -encoding iso-8859-1 -processor TestFilerConstraints -proc:only TestFilerConstraints.java duke@1: */ duke@1: duke@1: import java.util.Set; duke@1: import javax.annotation.processing.*; duke@1: import javax.lang.model.SourceVersion; duke@1: import static javax.lang.model.SourceVersion.*; duke@1: import javax.lang.model.element.*; duke@1: import javax.lang.model.util.*; duke@1: import static javax.lang.model.util.ElementFilter.*; duke@1: import static javax.tools.Diagnostic.Kind.*; duke@1: import static javax.tools.StandardLocation.*; duke@1: duke@1: import java.io.*; duke@1: import java.nio.charset.Charset; duke@1: duke@1: /** duke@1: * A processor that verifies the explicit and implicit constraints in duke@1: * the Filer contract are maintained: duke@1: * duke@1: *
duke@1: * duke@1: * During each run of an annotation processing tool, a file with a duke@1: * given pathname may be created only once. If that file already duke@1: * exists before the first attempt to create it, the old contents duke@1: * will be deleted. Any subsequent attempt to create the same file duke@1: * during a run will throw a FilerException, as will attempting to duke@1: * open both a class file and source file for the same type name. duke@1: * duke@1: *
duke@1: * duke@1: * Specific checks will include: duke@1: * duke@1: * duke@1: */ darcy@699: public class TestFilerConstraints extends JavacTestingAbstractProcessor { duke@1: private int round = 0; duke@1: duke@1: private PrintWriter pw_src1 = null; duke@1: private PrintWriter pw_src2 = null; duke@1: private OutputStream os_classFile1 = null; duke@1: private Writer pw_classFile2 = null; duke@1: duke@1: public boolean process(Set annotations, duke@1: RoundEnvironment roundEnv) { duke@1: round++; duke@1: duke@1: try { duke@1: switch(round) { duke@1: // Open two source files duke@1: case 1: duke@1: pw_src1 = new PrintWriter(filer.createSourceFile("Src1").openWriter()); duke@1: pw_src1.println("class Src1 {}"); duke@1: pw_src1.close(); duke@1: duke@1: // Hold open across rounds duke@1: pw_src2 = new PrintWriter(new OutputStreamWriter(filer.createSourceFile("Src2").openOutputStream())); duke@1: break; duke@1: duke@1: case 2: duke@1: testExpectedType(roundEnv, "Src1"); duke@1: duke@1: // Close Src1 a second time duke@1: pw_src1.close(); duke@1: duke@1: pw_src2.println("class Src2 {}"); duke@1: pw_src2.close(); duke@1: duke@1: break; duke@1: duke@1: case 3: duke@1: testExpectedType(roundEnv, "Src2"); duke@1: duke@1: // Close Src2 a second time duke@1: pw_src2.close(); duke@1: duke@1: os_classFile1 = filer.createClassFile("ClassFile1").openOutputStream(); duke@1: for (int value : classFile1Bytes) duke@1: os_classFile1.write((byte)value); duke@1: os_classFile1.close(); duke@1: duke@1: break; duke@1: duke@1: case 4: duke@1: testExpectedType(roundEnv, "ClassFile1"); duke@1: duke@1: // Close a second time duke@1: os_classFile1.close(); duke@1: duke@1: testReopening(); duke@1: duke@1: pw_classFile2 = new PrintWriter(filer.createClassFile("ClassFile2", duke@1: (Element[])null).openWriter()); duke@1: duke@1: for(int byteVal : classFile2Bytes) { duke@1: // int value = (0xff00 & (classFile2Bytes[i]<<8)) | classFile2Bytes[i+1]; duke@1: // System.out.print(Integer.toHexString(value)); duke@1: //if ((i % 4) == 0) duke@1: // System.out.println(); duke@1: pw_classFile2.write((char) (0xff & byteVal)); duke@1: } duke@1: pw_classFile2.close(); duke@1: duke@1: break; duke@1: duke@1: duke@1: duke@1: case 5: duke@1: testExpectedType(roundEnv, "ClassFile2"); duke@1: // Close a second time duke@1: pw_classFile2.close(); duke@1: duke@1: duke@1: break; duke@1: duke@1: case 6: duke@1: if (!roundEnv.processingOver() && !roundEnv.errorRaised()) duke@1: throw new RuntimeException("Bad round state: " + roundEnv); duke@1: break; duke@1: duke@1: default: duke@1: throw new RuntimeException("Unexpected round number!"); duke@1: } duke@1: } catch (IOException ioe) { duke@1: throw new RuntimeException(ioe); duke@1: } duke@1: duke@1: return true; duke@1: } duke@1: duke@1: /** duke@1: * Test that the single expected expected type, name, is the root duke@1: * element. duke@1: */ duke@1: private void testExpectedType(RoundEnvironment roundEnv, String name) { duke@1: if (!roundEnv.getRootElements().isEmpty()) { duke@1: for(TypeElement type : typesIn(roundEnv.getRootElements())) { duke@1: if (!name.contentEquals(type.getSimpleName())) duke@1: throw new RuntimeException("Unexpected type " + type.getSimpleName()); duke@1: } duke@1: } else duke@1: throw new RuntimeException("Unexpected empty root elements."); duke@1: } duke@1: duke@1: private void testReopening() throws IOException { duke@1: String[] names = {"Src1", "Src2", "ClassFile1"}; duke@1: for (String name : names) { duke@1: try { duke@1: filer.createSourceFile(name); duke@1: throw new RuntimeException("Opened a source file for type " + name); duke@1: } catch (FilerException fe) {;} duke@1: duke@1: try { duke@1: filer.createClassFile(name); duke@1: throw new RuntimeException("Opened a class file for type " + name); duke@1: } catch (FilerException fe) {;} duke@1: } duke@1: duke@1: // Try to open a resource over a source file duke@1: try { duke@1: filer.createResource(SOURCE_OUTPUT, "", "Src1.java"); duke@1: throw new RuntimeException("Opened a text file over Src1.java!"); duke@1: } catch (FilerException fe) {;} duke@1: duke@1: // Try to open a resource over a class file duke@1: try { duke@1: filer.createResource(CLASS_OUTPUT, "", "ClassFile1.class"); duke@1: throw new RuntimeException("Opened a text file over Src1.java!"); duke@1: } catch (FilerException fe) {;} duke@1: duke@1: } duke@1: duke@1: private int[] classFile1Bytes = duke@1: {202, 254, 186, 190, 0, 0, 0, 50, duke@1: 0, 13, 10, 0, 3, 0, 10, 7, duke@1: 0, 11, 7, 0, 12, 1, 0, 6, duke@1: 60, 105, 110, 105, 116, 62, 1, 0, duke@1: 3, 40, 41, 86, 1, 0, 4, 67, duke@1: 111, 100, 101, 1, 0, 15, 76, 105, duke@1: 110, 101, 78, 117, 109, 98, 101, 114, duke@1: 84, 97, 98, 108, 101, 1, 0, 10, duke@1: 83, 111, 117, 114, 99, 101, 70, 105, duke@1: 108, 101, 1, 0, 15, 67, 108, 97, duke@1: 115, 115, 70, 105, 108, 101, 49, 46, duke@1: 106, 97, 118, 97, 12, 0, 4, 0, duke@1: 5, 1, 0, 10, 67, 108, 97, 115, duke@1: 115, 70, 105, 108, 101, 49, 1, 0, duke@1: 16, 106, 97, 118, 97, 47, 108, 97, duke@1: 110, 103, 47, 79, 98, 106, 101, 99, duke@1: 116, 0, 33, 0, 2, 0, 3, 0, duke@1: 0, 0, 0, 0, 1, 0, 1, 0, duke@1: 4, 0, 5, 0, 1, 0, 6, 0, duke@1: 0, 0, 29, 0, 1, 0, 1, 0, duke@1: 0, 0, 5, 42, 183, 0, 1, 177, duke@1: 0, 0, 0, 1, 0, 7, 0, 0, duke@1: 0, 6, 0, 1, 0, 0, 0, 1, duke@1: 0, 1, 0, 8, 0, 0, 0, 2, duke@1: 0, 9,}; duke@1: duke@1: private int[] classFile2Bytes = duke@1: {202, 254, 186, 190, 0, 0, 0, 50, duke@1: 0, 13, 10, 0, 3, 0, 10, 7, duke@1: 0, 11, 7, 0, 12, 1, 0, 6, duke@1: 60, 105, 110, 105, 116, 62, 1, 0, duke@1: 3, 40, 41, 86, 1, 0, 4, 67, duke@1: 111, 100, 101, 1, 0, 15, 76, 105, duke@1: 110, 101, 78, 117, 109, 98, 101, 114, duke@1: 84, 97, 98, 108, 101, 1, 0, 10, duke@1: 83, 111, 117, 114, 99, 101, 70, 105, duke@1: 108, 101, 1, 0, 15, 67, 108, 97, duke@1: 115, 115, 70, 105, 108, 101, 50, 46, duke@1: 106, 97, 118, 97, 12, 0, 4, 0, duke@1: 5, 1, 0, 10, 67, 108, 97, 115, duke@1: 115, 70, 105, 108, 101, 50, 1, 0, duke@1: 16, 106, 97, 118, 97, 47, 108, 97, duke@1: 110, 103, 47, 79, 98, 106, 101, 99, duke@1: 116, 0, 33, 0, 2, 0, 3, 0, duke@1: 0, 0, 0, 0, 1, 0, 1, 0, duke@1: 4, 0, 5, 0, 1, 0, 6, 0, duke@1: 0, 0, 29, 0, 1, 0, 1, 0, duke@1: 0, 0, 5, 42, 183, 0, 1, 177, duke@1: 0, 0, 0, 1, 0, 7, 0, 0, duke@1: 0, 6, 0, 1, 0, 0, 0, 1, duke@1: 0, 1, 0, 8, 0, 0, 0, 2, duke@1: 0, 9,}; duke@1: }