/* * Copyright (c) 2012, 2014, 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. */ import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; import java.util.Iterator; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import javax.tools.ToolProvider; import com.sun.source.util.JavacTask; public class Helper { enum ContentVars { IMPORTCONTAINERSTMTS("\nimport java.lang.annotation.Repeatable;\n"), IMPORTDEPRECATED("import java.lang.Deprecated;\n"), IMPORTDOCUMENTED("import java.lang.annotation.Documented;\n"), IMPORTINHERITED("import java.lang.annotation.Inherited;\n"), IMPORTRETENTION("import java.lang.annotation.Retention;\n" + "\nimport java.lang.annotation.RetentionPolicy;\n"), IMPORTSTMTS("import java.lang.annotation.*;\n"), IMPORTEXPECTED("import expectedFiles.*;\n"), REPEATABLE("\n@Repeatable(FooContainer.class)\n"), CONTAINER("@interface FooContainer {\n" + " Foo[] value();\n}\n"), BASE("@interface Foo {int value() default Integer.MAX_VALUE;}\n"), BASEANNO("@Foo(0)"), LEGACYCONTAINER("@FooContainer(value = {@Foo(1), @Foo(2)})\n"), REPEATABLEANNO("\n@Foo(1) @Foo(2)"), DEPRECATED("\n@Deprecated"), DOCUMENTED("\n@Documented"), INHERITED("\n@Inherited"), TARGET("\n@Target(#VAL)\n"), RETENTION("@Retention(RetentionPolicy.#VAL)\n"), RETENTIONRUNTIME("@Retention(RetentionPolicy.RUNTIME)\n"); private String val; private ContentVars(String val) { this.val = val; } public String getVal() { return val; } } // Create and compile FileObject using values for className and contents public static boolean compileCode(String className, String contents, DiagnosticCollector<JavaFileObject> diagnostics) { boolean ok = false; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new RuntimeException("can't get javax.tools.JavaCompiler!"); } JavaFileObject file = getFile(className, contents); Iterable<? extends JavaFileObject> compilationUnit = Arrays.asList(file); CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnit); ok = task.call(); return ok; } // Compile a list of FileObjects // Used when packages are needed and classes need to be loaded at runtime static File destDir = new File(System.getProperty("user.dir")); public static boolean compileCode(DiagnosticCollector<JavaFileObject> diagnostics, Iterable<? extends JavaFileObject> files) { boolean ok = false; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new RuntimeException("can't get javax.tools.JavaCompiler!"); } try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { // Assuming filesCount can maximum be 2 and if true, one file is package-info.java if (isPkgInfoPresent(files)) { JavacTask task = (JavacTask) compiler.getTask(null, fm, diagnostics, null, null, files); try { fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); task.generate(); } catch (IOException ioe) { throw new RuntimeException("Compilation failed for package level tests", ioe); } int err = 0; for (Diagnostic<? extends JavaFileObject> d : diagnostics.getDiagnostics()) { if(d.getKind() == Diagnostic.Kind.ERROR) { err++; } } ok = (err == 0); } else { CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, files); ok = task.call(); } return ok; } catch (IOException e) { throw new Error(e); } } static private boolean isPkgInfoPresent(Iterable<? extends JavaFileObject> files) { Iterator<? extends JavaFileObject> itr = files.iterator(); while (itr.hasNext()) { String name = itr.next().getName(); if (name.contains("package-info")) { return true; } } return false; } /* String template where /*<TYPE>*/ /*gets replaced by repeating anno * Used to generate test src for combo tests * - BasicSyntaxCombo.java * - TargetAnnoCombo.java */ public static final String template = "/*PACKAGE*/\n" + "//pkg test;\n\n" + "/*ANNODATA*/\n" // import statements, declaration of Foo/FooContainer + "/*TYPE*/ //class\n" + "class #ClassName {\n" + " /*FIELD*/ //instance var\n" + " public int x = 0;\n\n" + " /*FIELD*/ //Enum constants\n" + " TestEnum testEnum;\n\n" + " /*FIELD*/ // Static field\n" + " public static int num;\n\n" + " /*STATIC_INI*/\n" + " static { \n" + "num = 10; \n }\n\n" + " /*CONSTRUCTOR*/\n" + " #ClassName() {}\n\n" + " /*INSTANCE_INI*/\n" + " { \n x = 10; \n }" + " /*INNER_CLASS*/\n" + " class innerClass {}\n" + " /*METHOD*/\n" + " void bar(/*PARAMETER*/ int baz) {\n" + " /*LOCAL_VARIABLE*/\n" + " int y = 0;\n" + " }\n" + "}\n\n" + "/*TYPE*/ //Enum\n" + "enum TestEnum {}\n\n" + "/*TYPE*/ //Interface\n" + "interface TestInterface {}\n\n" + "/*TYPE*/\n" + "/*ANNOTATION_TYPE*/\n" + "@interface TestAnnotationType{}\n" + "class TestPkg {}\n" + "class TestTypeAnno </*TYPE_PARAMETER*/ T extends Object> {\n" + " String /*TYPE_USE*/[] arr;\n" + "}"; static JavaFileObject getFile(String name, String code) { JavaFileObject o = null; try { o = new JavaStringFileObject(name, code); } catch (URISyntaxException e) { throw new RuntimeException(e); } return o; } static class JavaStringFileObject extends SimpleJavaFileObject { final String theCode; public JavaStringFileObject(String fileName, String theCode) throws URISyntaxException { super(new URI("string:///" + fileName.replace('.', '/') + ".java"), Kind.SOURCE); this.theCode = theCode; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return theCode; } } }