aoqi@0: /* aoqi@0: * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 6437138 6482554 aoqi@0: * @summary JSR 199: Compiler doesn't diagnose crash in user code aoqi@0: * @library ../lib aoqi@0: * @build JavacTestingAbstractProcessor TestClientCodeWrapper aoqi@0: * @run main TestClientCodeWrapper aoqi@0: */ aoqi@0: aoqi@0: import java.io.*; aoqi@0: import java.lang.reflect.Method; aoqi@0: import java.net.URI; aoqi@0: import java.util.*; aoqi@0: import javax.annotation.processing.*; aoqi@0: import javax.lang.model.*; aoqi@0: import javax.lang.model.element.*; aoqi@0: import javax.tools.*; aoqi@0: import com.sun.source.util.*; aoqi@0: import com.sun.tools.javac.api.*; aoqi@0: import javax.tools.JavaFileObject.Kind; aoqi@0: aoqi@0: public class TestClientCodeWrapper extends JavacTestingAbstractProcessor { aoqi@0: public static void main(String... args) throws Exception { aoqi@0: new TestClientCodeWrapper().run(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Run a series of compilations, each with a different user-provided object aoqi@0: * configured to throw an exception when a specific method is invoked. aoqi@0: * Then, verify the exception is thrown as expected. aoqi@0: * aoqi@0: * Some methods are not invoked from the compiler, and are excluded from the test. aoqi@0: */ aoqi@0: void run() throws Exception { aoqi@0: JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); aoqi@0: defaultFileManager = compiler.getStandardFileManager(null, null, null); aoqi@0: aoqi@0: for (Method m: getMethodsExcept(JavaFileManager.class, "close", "getJavaFileForInput")) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: for (Method m: getMethodsExcept(FileObject.class, "delete")) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: for (Method m: getMethods(JavaFileObject.class)) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: for (Method m: getMethodsExcept(Processor.class, "getCompletions")) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: for (Method m: DiagnosticListener.class.getDeclaredMethods()) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: for (Method m: TaskListener.class.getDeclaredMethods()) { aoqi@0: test(m); aoqi@0: } aoqi@0: aoqi@0: if (errors > 0) aoqi@0: throw new Exception(errors + " errors occurred"); aoqi@0: } aoqi@0: aoqi@0: /** Get a sorted set of the methods declared on a class. */ aoqi@0: Set getMethods(Class clazz) { aoqi@0: return getMethodsExcept(clazz, new String[0]); aoqi@0: } aoqi@0: aoqi@0: /** Get a sorted set of the methods declared on a class, excluding aoqi@0: * specified methods by name. */ aoqi@0: Set getMethodsExcept(Class clazz, String... exclude) { aoqi@0: Set methods = new TreeSet(new Comparator() { aoqi@0: public int compare(Method m1, Method m2) { aoqi@0: return m1.toString().compareTo(m2.toString()); aoqi@0: } aoqi@0: }); aoqi@0: Set e = new HashSet(Arrays.asList(exclude)); aoqi@0: for (Method m: clazz.getDeclaredMethods()) { aoqi@0: if (!e.contains(m.getName())) aoqi@0: methods.add(m); aoqi@0: } aoqi@0: return methods; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Test a method in a user supplied component, to verify javac's handling aoqi@0: * of any exceptions thrown by that method. aoqi@0: */ aoqi@0: void test(Method m) throws Exception { aoqi@0: testNum++; aoqi@0: aoqi@0: File extDirs = new File("empty-extdirs"); aoqi@0: extDirs.mkdirs(); aoqi@0: aoqi@0: File testClasses = new File("test" + testNum); aoqi@0: testClasses.mkdirs(); aoqi@0: defaultFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(testClasses)); aoqi@0: aoqi@0: System.err.println("test " + testNum + ": " aoqi@0: + m.getDeclaringClass().getSimpleName() + "." + m.getName()); aoqi@0: aoqi@0: StringWriter sw = new StringWriter(); aoqi@0: PrintWriter pw = new PrintWriter(sw); aoqi@0: aoqi@0: List javacOptions = Arrays.asList( aoqi@0: "-extdirs", extDirs.getPath(), // for use by filemanager handleOption aoqi@0: "-processor", TestClientCodeWrapper.class.getName() aoqi@0: ); aoqi@0: aoqi@0: List classes = Collections.emptyList(); aoqi@0: aoqi@0: JavacTool tool = JavacTool.create(); aoqi@0: try { aoqi@0: JavacTask task = tool.getTask(pw, aoqi@0: getFileManager(m, defaultFileManager), aoqi@0: getDiagnosticListener(m, pw), aoqi@0: javacOptions, aoqi@0: classes, aoqi@0: getCompilationUnits(m)); aoqi@0: aoqi@0: if (isDeclaredIn(m, Processor.class)) aoqi@0: task.setProcessors(getProcessors(m)); aoqi@0: aoqi@0: if (isDeclaredIn(m, TaskListener.class)) aoqi@0: task.setTaskListener(getTaskListener(m, pw)); aoqi@0: aoqi@0: boolean ok = task.call(); aoqi@0: error("compilation " + (ok ? "succeeded" : "failed") + " unexpectedly"); aoqi@0: } catch (RuntimeException e) { aoqi@0: System.err.println("caught " + e); aoqi@0: if (e.getClass() == RuntimeException.class) { aoqi@0: Throwable cause = e.getCause(); aoqi@0: if (cause instanceof UserError) { aoqi@0: String expect = m.getName(); aoqi@0: String found = cause.getMessage(); aoqi@0: checkEqual("exception messaqe", expect, found); aoqi@0: } else { aoqi@0: cause.printStackTrace(System.err); aoqi@0: error("Unexpected exception: " + cause); aoqi@0: } aoqi@0: } else { aoqi@0: e.printStackTrace(System.err); aoqi@0: error("Unexpected exception: " + e); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: pw.close(); aoqi@0: String out = sw.toString(); aoqi@0: System.err.println(out); aoqi@0: } aoqi@0: aoqi@0: /** Get a file manager to use for the test compilation. */ aoqi@0: JavaFileManager getFileManager(Method m, JavaFileManager defaultFileManager) { aoqi@0: return isDeclaredIn(m, JavaFileManager.class, FileObject.class, JavaFileObject.class) aoqi@0: ? new UserFileManager(m, defaultFileManager) aoqi@0: : defaultFileManager; aoqi@0: } aoqi@0: aoqi@0: /** Get a diagnostic listener to use for the test compilation. */ aoqi@0: DiagnosticListener getDiagnosticListener(Method m, PrintWriter out) { aoqi@0: return isDeclaredIn(m, DiagnosticListener.class) aoqi@0: ? new UserDiagnosticListener(m, out) aoqi@0: : null; aoqi@0: } aoqi@0: aoqi@0: /** Get a set of file objects to use for the test compilation. */ aoqi@0: Iterable getCompilationUnits(Method m) { aoqi@0: File testSrc = new File(System.getProperty("test.src")); aoqi@0: File thisSrc = new File(testSrc, TestClientCodeWrapper.class.getName() + ".java"); aoqi@0: Iterable files = defaultFileManager.getJavaFileObjects(thisSrc); aoqi@0: if (isDeclaredIn(m, FileObject.class, JavaFileObject.class)) aoqi@0: return Arrays.asList(new UserFileObject(m, files.iterator().next())); aoqi@0: else aoqi@0: return files; aoqi@0: } aoqi@0: aoqi@0: /** Get a set of annotation processors to use for the test compilation. */ aoqi@0: Iterable getProcessors(Method m) { aoqi@0: return Arrays.asList(new UserProcessor(m)); aoqi@0: } aoqi@0: aoqi@0: /** Get a task listener to use for the test compilation. */ aoqi@0: TaskListener getTaskListener(Method m, PrintWriter out) { aoqi@0: return new UserTaskListener(m, out); aoqi@0: } aoqi@0: aoqi@0: /** Check if two values are .equal, and report an error if not. */ aoqi@0: void checkEqual(String label, T expect, T found) { aoqi@0: if (!expect.equals(found)) aoqi@0: error("Unexpected value for " + label + ": " + found + "; expected: " + expect); aoqi@0: } aoqi@0: aoqi@0: /** Report an error. */ aoqi@0: void error(String msg) { aoqi@0: System.err.println("Error: " + msg); aoqi@0: errors++; aoqi@0: } aoqi@0: aoqi@0: /** Check if a method is declared in any of a set of classes */ aoqi@0: static boolean isDeclaredIn(Method m, Class... classes) { aoqi@0: Class dc = m.getDeclaringClass(); aoqi@0: for (Class c: classes) { aoqi@0: if (c == dc) return true; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: /** Throw an intentional error if the method has a given name. */ aoqi@0: static void throwUserExceptionIfNeeded(Method m, String name) { aoqi@0: if (m != null && m.getName().equals(name)) aoqi@0: throw new UserError(name); aoqi@0: } aoqi@0: aoqi@0: StandardJavaFileManager defaultFileManager; aoqi@0: int testNum; aoqi@0: int errors; aoqi@0: aoqi@0: //-------------------------------------------------------------------------- aoqi@0: aoqi@0: /** aoqi@0: * Processor used to trigger use of methods not normally used by javac. aoqi@0: */ aoqi@0: @Override aoqi@0: public boolean process(Set annotations, RoundEnvironment roundEnv) { aoqi@0: boolean firstRound = false; aoqi@0: for (Element e: roundEnv.getRootElements()) { aoqi@0: if (e.getSimpleName().contentEquals(TestClientCodeWrapper.class.getSimpleName())) aoqi@0: firstRound = true; aoqi@0: } aoqi@0: if (firstRound) { aoqi@0: try { aoqi@0: FileObject f1 = filer.getResource(StandardLocation.CLASS_PATH, "", aoqi@0: TestClientCodeWrapper.class.getName() + ".java"); aoqi@0: f1.openInputStream().close(); aoqi@0: f1.openReader(false).close(); aoqi@0: aoqi@0: FileObject f2 = filer.createResource( aoqi@0: StandardLocation.CLASS_OUTPUT, "", "f2.txt", (Element[]) null); aoqi@0: f2.openOutputStream().close(); aoqi@0: aoqi@0: FileObject f3 = filer.createResource( aoqi@0: StandardLocation.CLASS_OUTPUT, "", "f3.txt", (Element[]) null); aoqi@0: f3.openWriter().close(); aoqi@0: aoqi@0: JavaFileObject f4 = filer.createSourceFile("f4", (Element[]) null); aoqi@0: f4.openWriter().close(); aoqi@0: f4.getNestingKind(); aoqi@0: f4.getAccessLevel(); aoqi@0: aoqi@0: messager.printMessage(Diagnostic.Kind.NOTE, "informational note", aoqi@0: roundEnv.getRootElements().iterator().next()); aoqi@0: aoqi@0: } catch (IOException e) { aoqi@0: throw new UserError(e); aoqi@0: } aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: //-------------------------------------------------------------------------- aoqi@0: aoqi@0: // aoqi@0: aoqi@0: static class UserError extends Error { aoqi@0: private static final long serialVersionUID = 1L; aoqi@0: UserError(String msg) { aoqi@0: super(msg); aoqi@0: } aoqi@0: UserError(Throwable t) { aoqi@0: super(t); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class UserFileManager extends ForwardingJavaFileManager { aoqi@0: Method fileManagerMethod; aoqi@0: Method fileObjectMethod; aoqi@0: aoqi@0: UserFileManager(Method m, JavaFileManager delegate) { aoqi@0: super(delegate); aoqi@0: if (isDeclaredIn(m, JavaFileManager.class)) { aoqi@0: fileManagerMethod = m; aoqi@0: } else if (isDeclaredIn(m, FileObject.class, JavaFileObject.class)) { aoqi@0: fileObjectMethod = m; aoqi@0: } else aoqi@0: assert false; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public ClassLoader getClassLoader(Location location) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "getClassLoader"); aoqi@0: return super.getClassLoader(location); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "list"); aoqi@0: return wrap(super.list(location, packageName, kinds, recurse)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String inferBinaryName(Location location, JavaFileObject file) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "inferBinaryName"); aoqi@0: return super.inferBinaryName(location, unwrap(file)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean isSameFile(FileObject a, FileObject b) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "isSameFile"); aoqi@0: return super.isSameFile(unwrap(a), unwrap(b)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean handleOption(String current, Iterator remaining) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "handleOption"); aoqi@0: return super.handleOption(current, remaining); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean hasLocation(Location location) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "hasLocation"); aoqi@0: return super.hasLocation(location); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "getJavaFileForInput"); aoqi@0: return wrap(super.getJavaFileForInput(location, className, kind)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "getJavaFileForOutput"); aoqi@0: return wrap(super.getJavaFileForOutput(location, className, kind, sibling)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "getFileForInput"); aoqi@0: return wrap(super.getFileForInput(location, packageName, relativeName)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "getFileForOutput"); aoqi@0: return wrap(super.getFileForOutput(location, packageName, relativeName, sibling)); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void flush() throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "flush"); aoqi@0: super.flush(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void close() throws IOException { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "close"); aoqi@0: super.close(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public int isSupportedOption(String option) { aoqi@0: throwUserExceptionIfNeeded(fileManagerMethod, "isSupportedOption"); aoqi@0: return super.isSupportedOption(option); aoqi@0: } aoqi@0: aoqi@0: public FileObject wrap(FileObject fo) { aoqi@0: if (fileObjectMethod == null) aoqi@0: return fo; aoqi@0: return new UserFileObject(fileObjectMethod, (JavaFileObject)fo); aoqi@0: } aoqi@0: aoqi@0: FileObject unwrap(FileObject fo) { aoqi@0: if (fo instanceof UserFileObject) aoqi@0: return ((UserFileObject) fo).unwrap(); aoqi@0: else aoqi@0: return fo; aoqi@0: } aoqi@0: aoqi@0: public JavaFileObject wrap(JavaFileObject fo) { aoqi@0: if (fileObjectMethod == null) aoqi@0: return fo; aoqi@0: return new UserFileObject(fileObjectMethod, fo); aoqi@0: } aoqi@0: aoqi@0: public Iterable wrap(Iterable list) { aoqi@0: List wrapped = new ArrayList(); aoqi@0: for (JavaFileObject fo : list) aoqi@0: wrapped.add(wrap(fo)); aoqi@0: return Collections.unmodifiableList(wrapped); aoqi@0: } aoqi@0: aoqi@0: JavaFileObject unwrap(JavaFileObject fo) { aoqi@0: if (fo instanceof UserFileObject) aoqi@0: return ((UserFileObject) fo).unwrap(); aoqi@0: else aoqi@0: return fo; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class UserFileObject extends ForwardingJavaFileObject { aoqi@0: Method method; aoqi@0: aoqi@0: UserFileObject(Method m, JavaFileObject delegate) { aoqi@0: super(delegate); aoqi@0: assert isDeclaredIn(m, FileObject.class, JavaFileObject.class); aoqi@0: this.method = m; aoqi@0: } aoqi@0: aoqi@0: JavaFileObject unwrap() { aoqi@0: return fileObject; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Kind getKind() { aoqi@0: throwUserExceptionIfNeeded(method, "getKind"); aoqi@0: return super.getKind(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean isNameCompatible(String simpleName, Kind kind) { aoqi@0: throwUserExceptionIfNeeded(method, "isNameCompatible"); aoqi@0: return super.isNameCompatible(simpleName, kind); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public NestingKind getNestingKind() { aoqi@0: throwUserExceptionIfNeeded(method, "getNestingKind"); aoqi@0: return super.getNestingKind(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Modifier getAccessLevel() { aoqi@0: throwUserExceptionIfNeeded(method, "getAccessLevel"); aoqi@0: return super.getAccessLevel(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public URI toUri() { aoqi@0: throwUserExceptionIfNeeded(method, "toUri"); aoqi@0: return super.toUri(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String getName() { aoqi@0: throwUserExceptionIfNeeded(method, "getName"); aoqi@0: return super.getName(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public InputStream openInputStream() throws IOException { aoqi@0: throwUserExceptionIfNeeded(method, "openInputStream"); aoqi@0: return super.openInputStream(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public OutputStream openOutputStream() throws IOException { aoqi@0: throwUserExceptionIfNeeded(method, "openOutputStream"); aoqi@0: return super.openOutputStream(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Reader openReader(boolean ignoreEncodingErrors) throws IOException { aoqi@0: throwUserExceptionIfNeeded(method, "openReader"); aoqi@0: return super.openReader(ignoreEncodingErrors); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { aoqi@0: throwUserExceptionIfNeeded(method, "getCharContent"); aoqi@0: return super.getCharContent(ignoreEncodingErrors); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Writer openWriter() throws IOException { aoqi@0: throwUserExceptionIfNeeded(method, "openWriter"); aoqi@0: return super.openWriter(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public long getLastModified() { aoqi@0: throwUserExceptionIfNeeded(method, "getLastModified"); aoqi@0: return super.getLastModified(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean delete() { aoqi@0: throwUserExceptionIfNeeded(method, "delete"); aoqi@0: return super.delete(); aoqi@0: } aoqi@0: aoqi@0: } aoqi@0: aoqi@0: static class UserProcessor extends JavacTestingAbstractProcessor { aoqi@0: Method method; aoqi@0: aoqi@0: UserProcessor(Method m) { aoqi@0: assert isDeclaredIn(m, Processor.class); aoqi@0: method = m; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Set getSupportedOptions() { aoqi@0: throwUserExceptionIfNeeded(method, "getSupportedOptions"); aoqi@0: return super.getSupportedOptions(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Set getSupportedAnnotationTypes() { aoqi@0: throwUserExceptionIfNeeded(method, "getSupportedAnnotationTypes"); aoqi@0: return super.getSupportedAnnotationTypes(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public SourceVersion getSupportedSourceVersion() { aoqi@0: throwUserExceptionIfNeeded(method, "getSupportedSourceVersion"); aoqi@0: return super.getSupportedSourceVersion(); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void init(ProcessingEnvironment processingEnv) { aoqi@0: throwUserExceptionIfNeeded(method, "init"); aoqi@0: super.init(processingEnv); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public boolean process(Set annotations, RoundEnvironment roundEnv) { aoqi@0: throwUserExceptionIfNeeded(method, "process"); aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) { aoqi@0: throwUserExceptionIfNeeded(method, "getCompletions"); aoqi@0: return super.getCompletions(element, annotation, member, userText); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class UserDiagnosticListener implements DiagnosticListener { aoqi@0: Method method; aoqi@0: PrintWriter out; aoqi@0: aoqi@0: UserDiagnosticListener(Method m, PrintWriter out) { aoqi@0: assert isDeclaredIn(m, DiagnosticListener.class); aoqi@0: this.method = m; aoqi@0: this.out = out; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void report(Diagnostic diagnostic) { aoqi@0: throwUserExceptionIfNeeded(method, "report"); aoqi@0: out.println("report: " + diagnostic); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class UserTaskListener implements TaskListener { aoqi@0: Method method; aoqi@0: PrintWriter out; aoqi@0: aoqi@0: UserTaskListener(Method m, PrintWriter out) { aoqi@0: assert isDeclaredIn(m, TaskListener.class); aoqi@0: this.method = m; aoqi@0: this.out = out; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void started(TaskEvent e) { aoqi@0: throwUserExceptionIfNeeded(method, "started"); aoqi@0: out.println("started: " + e); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public void finished(TaskEvent e) { aoqi@0: throwUserExceptionIfNeeded(method, "finished"); aoqi@0: out.println("finished: " + e); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // aoqi@0: }