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