duke@1: /* ohair@554: * Copyright (c) 2004, 2007, 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: /* duke@1: * A utility used to invoke and test the apt tool. duke@1: * Tests should subclass Tester, and invoke run(). duke@1: * duke@1: * @author Scott Seligman duke@1: */ duke@1: duke@1: import java.io.*; duke@1: import java.util.*; duke@1: import com.sun.mirror.apt.*; duke@1: import com.sun.mirror.declaration.*; duke@1: duke@1: duke@1: public abstract class Tester { duke@1: duke@1: /** duke@1: * The declaration corresponding to this tester's class. Set by duke@1: * TestProcessorFactory after the constructor completes, and duke@1: * before init() is invoked. duke@1: */ duke@1: ClassDeclaration thisClassDecl; duke@1: duke@1: /** duke@1: * The environment for this apt run. Set by TestProcessorFactory duke@1: * after the constructor completes, and before init() is invoked. duke@1: */ duke@1: AnnotationProcessorEnvironment env; duke@1: duke@1: duke@1: // TestProcessorFactory looks here to find the tester that's running duke@1: // when it's invoked. duke@1: static Tester activeTester; duke@1: duke@1: private static final String[] DEFAULT_ARGS = { duke@1: "-nocompile", duke@1: "-XPrintAptRounds", duke@1: "-XListDeclarations", duke@1: }; duke@1: private static final String[] NO_STRINGS = {}; duke@1: duke@1: // Force processor and factory to be compiled duke@1: private static Class dummy = TestProcessorFactory.class; duke@1: duke@1: private final String testSrc = System.getProperty("test.src", "."); duke@1: private final String testClasses = System.getProperty("test.classes", "."); duke@1: duke@1: // apt command-line args duke@1: private String[] args; duke@1: duke@1: duke@1: static { duke@1: // Enable assertions in the unnamed package. duke@1: ClassLoader loader = Tester.class.getClassLoader(); duke@1: if (loader != null) { duke@1: loader.setPackageAssertionStatus(null, true); duke@1: } duke@1: } duke@1: duke@1: duke@1: protected Tester(String... additionalArgs) { duke@1: String sourceFile = testSrc + File.separator + duke@1: getClass().getName() + ".java"; duke@1: duke@1: ArrayList as = new ArrayList(); duke@1: Collections.addAll(as, DEFAULT_ARGS); duke@1: as.add("-sourcepath"); as.add(testSrc); duke@1: as.add("-factory"); as.add(TestProcessorFactory.class.getName()); duke@1: Collections.addAll(as, additionalArgs); duke@1: as.add(sourceFile); duke@1: args = as.toArray(NO_STRINGS); duke@1: } duke@1: duke@1: /** duke@1: * Run apt. duke@1: */ duke@1: protected void run() { duke@1: activeTester = this; duke@1: if (com.sun.tools.apt.Main.process(args) != 0) { duke@1: throw new Error("apt errors encountered."); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Called after thisClassDecl and env have been set, but before any duke@1: * tests are run, to allow the tester subclass to perform any duke@1: * needed initialization. duke@1: */ duke@1: protected void init() { duke@1: } duke@1: duke@1: /** duke@1: * Returns the declaration of a named method in this class. If this duke@1: * method name is overloaded, one method is chosen arbitrarily. duke@1: * Returns null if no method is found. duke@1: */ duke@1: protected MethodDeclaration getMethod(String methodName) { duke@1: for (MethodDeclaration m : thisClassDecl.getMethods()) { duke@1: if (methodName.equals(m.getSimpleName())) { duke@1: return m; duke@1: } duke@1: } duke@1: return null; duke@1: } duke@1: duke@1: /** duke@1: * Returns the declaration of a named field in this class. duke@1: * Returns null if no field is found. duke@1: */ duke@1: protected FieldDeclaration getField(String fieldName) { duke@1: for (FieldDeclaration f : thisClassDecl.getFields()) { duke@1: if (fieldName.equals(f.getSimpleName())) { duke@1: return f; duke@1: } duke@1: } duke@1: return null; duke@1: } duke@1: duke@1: /** duke@1: * Returns the annotation mirror of a given type on a named method duke@1: * in this class. If this method name is overloaded, one method is duke@1: * chosen arbitrarily. Returns null if no appropriate annotation duke@1: * is found. duke@1: */ duke@1: protected AnnotationMirror getAnno(String methodName, String annoType) { duke@1: MethodDeclaration m = getMethod(methodName); duke@1: if (m != null) { duke@1: TypeDeclaration at = env.getTypeDeclaration(annoType); duke@1: for (AnnotationMirror a : m.getAnnotationMirrors()) { duke@1: if (at == a.getAnnotationType().getDeclaration()) { duke@1: return a; duke@1: } duke@1: } duke@1: } duke@1: return null; duke@1: } duke@1: }