changeset 1245:e974e82abe51 jdk8-b29

Merge
author lana
date Mon, 05 Mar 2012 17:04:48 -0800
parents 7e777fcd4d39 3d3350aea968
children a1af4b95c287 83352b2e2ebc
files test/tools/javac/apt.sh
diffstat 15 files changed, 1003 insertions(+), 334 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/source/tree/MemberReferenceTree.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/source/tree/MemberReferenceTree.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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
@@ -37,7 +37,7 @@
  *   <em>expression</em> # <em>[ identifier | new ]</em>
  * </pre>
  *
- * @see JSR 292
+ * @since 1.8
  */
 public interface MemberReferenceTree extends ExpressionTree {
 
--- a/src/share/classes/com/sun/source/util/JavacTask.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/source/util/JavacTask.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -25,9 +25,9 @@
 
 package com.sun.source.util;
 
-import com.sun.source.tree.CompilationUnitTree;
-import com.sun.source.tree.Tree;
 import java.io.IOException;
+
+import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.Element;
 import javax.lang.model.type.TypeMirror;
 import javax.lang.model.util.Elements;
@@ -35,6 +35,12 @@
 import javax.tools.JavaCompiler.CompilationTask;
 import javax.tools.JavaFileObject;
 
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.Tree;
+import com.sun.tools.javac.api.BasicJavacTask;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
+
 /**
  * Provides access to functionality specific to the JDK Java Compiler, javac.
  *
@@ -45,10 +51,29 @@
 public abstract class JavacTask implements CompilationTask {
 
     /**
+     * Get the {@code JavacTask} for a {@code ProcessingEnvironment}.
+     * If the compiler is being invoked using a
+     * {@link javax.tools.JavaCompiler.CompilationTask CompilationTask},
+     * then that task will be returned.
+     * @param processingEnvironment
+     * @return the {@code JavacTask} for a {@code ProcessingEnvironment}
+     * @since 1.8
+     */
+    public static JavacTask instance(ProcessingEnvironment processingEnvironment) {
+        if (!processingEnvironment.getClass().getName().equals(
+                "com.sun.tools.javac.processing.JavacProcessingEnvironment"))
+            throw new IllegalArgumentException();
+        Context c = ((JavacProcessingEnvironment) processingEnvironment).getContext();
+        JavacTask t = c.get(JavacTask.class);
+        return (t != null) ? t : new BasicJavacTask(c, true);
+    }
+
+    /**
      * Parse the specified files returning a list of abstract syntax trees.
      *
      * @return a list of abstract syntax trees
      * @throws IOException if an unhandled I/O error occurred in the compiler.
+     * @throws IllegalStateException if the operation cannot be performed at this time.
      */
     public abstract Iterable<? extends CompilationUnitTree> parse()
         throws IOException;
@@ -58,6 +83,7 @@
      *
      * @return a list of elements that were analyzed
      * @throws IOException if an unhandled I/O error occurred in the compiler.
+     * @throws IllegalStateException if the operation cannot be performed at this time.
      */
     public abstract Iterable<? extends Element> analyze() throws IOException;
 
@@ -66,17 +92,51 @@
      *
      * @return a list of files that were generated
      * @throws IOException if an unhandled I/O error occurred in the compiler.
+     * @throws IllegalStateException if the operation cannot be performed at this time.
      */
     public abstract Iterable<? extends JavaFileObject> generate() throws IOException;
 
     /**
-     * The specified listener will receive events describing the progress of
-     * this compilation task.
+     * The specified listener will receive notification of events
+     * describing the progress of this compilation task.
+     *
+     * If another listener is receiving notifications as a result of a prior
+     * call of this method, then that listener will no longer receive notifications.
+     *
+     * Informally, this method is equivalent to calling {@code removeTaskListener} for
+     * any listener that has been previously set, followed by {@code addTaskListener}
+     * for the new listener.
+     *
+     * @throws IllegalStateException if the specified listener has already been added.
      */
     public abstract void setTaskListener(TaskListener taskListener);
 
     /**
+     * The specified listener will receive notification of events
+     * describing the progress of this compilation task.
+     *
+     * This method may be called at any time before or during the compilation.
+     *
+     * @throws IllegalStateException if the specified listener has already been added.
+     * @since 1.8
+     */
+    public abstract void addTaskListener(TaskListener taskListener);
+
+    /**
+     * The specified listener will no longer receive notification of events
+     * describing the progress of this compilation task.
+     *
+     * This method may be called at any time before or during the compilation.
+     *
+     * @since 1.8
+     */
+    public abstract void removeTaskListener(TaskListener taskListener);
+
+    /**
      * Get a type mirror of the tree node determined by the specified path.
+     * This method has been superceded by methods on
+     * {@link com.sun.source.util.Trees Trees}.
+     * @see com.sun.source.util.Trees#getTypeMirror
      */
     public abstract TypeMirror getTypeMirror(Iterable<? extends Tree> path);
     /**
--- a/src/share/classes/com/sun/tools/doclets/package.html	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/doclets/package.html	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 <!--
- Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2003, 2012, 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
@@ -29,6 +29,6 @@
 </head>
 <body bgcolor="white">
         As of JDK version 1.5, replaced by 
-        {@link com.sun.tools.doclets.internal.toolkit.util}.
+        {@code com.sun.tools.doclets.internal.toolkit.util}.
     </body>
 </html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/api/BasicJavacTask.java	Mon Mar 05 17:04:48 2012 -0800
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2005, 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.api;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import javax.annotation.processing.Processor;
+import javax.lang.model.element.Element;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import javax.tools.JavaFileObject;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.Context;
+import java.util.Collection;
+
+/**
+ * Provides basic functionality for implementations of JavacTask.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own
+ * risk.  This code and its internal interfaces are subject to change
+ * or deletion without notice.</b></p>
+ */
+public class BasicJavacTask extends JavacTask {
+    protected Context context;
+    private TaskListener taskListener;
+
+    public BasicJavacTask(Context c, boolean register) {
+        context = c;
+        if (register)
+            context.put(JavacTask.class, this);
+    }
+
+    @Override
+    public Iterable<? extends CompilationUnitTree> parse() throws IOException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public Iterable<? extends Element> analyze() throws IOException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public Iterable<? extends JavaFileObject> generate() throws IOException {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public void setTaskListener(TaskListener tl) {
+        MultiTaskListener mtl = MultiTaskListener.instance(context);
+        if (taskListener != null)
+            mtl.remove(taskListener);
+        if (tl != null)
+            mtl.add(tl);
+        taskListener = tl;
+    }
+
+    @Override
+    public void addTaskListener(TaskListener taskListener) {
+        MultiTaskListener mtl = MultiTaskListener.instance(context);
+        mtl.add(taskListener);
+    }
+
+    @Override
+    public void removeTaskListener(TaskListener taskListener) {
+        MultiTaskListener mtl = MultiTaskListener.instance(context);
+        mtl.remove(taskListener);
+    }
+
+    public Collection<TaskListener> getTaskListeners() {
+        MultiTaskListener mtl = MultiTaskListener.instance(context);
+        return mtl.getTaskListeners();
+    }
+
+    @Override
+    public TypeMirror getTypeMirror(Iterable<? extends Tree> path) {
+        // TODO: Should complete attribution if necessary
+        Tree last = null;
+        for (Tree node : path)
+            last = node;
+        return ((JCTree)last).type;
+    }
+
+    @Override
+    public Elements getElements() {
+        return JavacElements.instance(context);
+    }
+
+    @Override
+    public Types getTypes() {
+        return JavacTypes.instance(context);
+    }
+
+    public void setProcessors(Iterable<? extends Processor> processors) {
+        throw new IllegalStateException();
+    }
+
+    public void setLocale(Locale locale) {
+        throw new IllegalStateException();
+    }
+
+    public Boolean call() {
+        throw new IllegalStateException();
+    }
+
+}
--- a/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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
@@ -31,8 +31,13 @@
 import java.io.OutputStream;
 import java.io.Reader;
 import java.io.Writer;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -41,25 +46,21 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.lang.model.element.Modifier;
 import javax.lang.model.element.NestingKind;
 import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
 
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import javax.lang.model.element.Modifier;
-import javax.tools.DiagnosticListener;
-import javax.tools.JavaFileObject.Kind;
 
 /**
  *  Wrap objects to enable unchecked exceptions to be caught and handled.
@@ -160,6 +161,20 @@
         return new WrappedTaskListener(tl);
     }
 
+    TaskListener unwrap(TaskListener l) {
+        if (l instanceof WrappedTaskListener)
+            return ((WrappedTaskListener) l).clientTaskListener;
+        else
+            return l;
+    }
+
+    Collection<TaskListener> unwrap(Collection<? extends TaskListener> listeners) {
+        Collection<TaskListener> c = new ArrayList<TaskListener>(listeners.size());
+        for (TaskListener l: listeners)
+            c.add(unwrap(l));
+        return c;
+    }
+
     @SuppressWarnings("unchecked")
     private <T> Diagnostic<T> unwrap(final Diagnostic<T> diagnostic) {
         if (diagnostic instanceof JCDiagnostic) {
@@ -181,6 +196,10 @@
         return trusted;
     }
 
+    private String wrappedToString(Class<?> wrapperClass, Object wrapped) {
+        return wrapperClass.getSimpleName() + "[" + wrapped + "]";
+    }
+
     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
 
     // FIXME: all these classes should be converted to use multi-catch when
@@ -361,6 +380,11 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override
+        public String toString() {
+            return wrappedToString(getClass(), clientJavaFileManager);
+        }
     }
 
     protected class WrappedFileObject implements FileObject {
@@ -486,6 +510,11 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override
+        public String toString() {
+            return wrappedToString(getClass(), clientFileObject);
+        }
     }
 
     protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
@@ -544,6 +573,11 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override
+        public String toString() {
+            return wrappedToString(getClass(), clientFileObject);
+        }
     }
 
     protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
@@ -565,6 +599,11 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override
+        public String toString() {
+            return wrappedToString(getClass(), clientDiagnosticListener);
+        }
     }
 
     public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
@@ -610,6 +649,7 @@
             return d.getMessage(locale);
         }
 
+        @Override
         public String toString() {
             return d.toString();
         }
@@ -647,6 +687,11 @@
                 throw new ClientCodeException(e);
             }
         }
+
+        @Override
+        public String toString() {
+            return wrappedToString(getClass(), clientTaskListener);
+        }
     }
 
     // </editor-fold>
--- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -44,6 +44,7 @@
 import com.sun.tools.javac.comp.*;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.main.*;
+import com.sun.tools.javac.main.JavaCompiler;
 import com.sun.tools.javac.model.*;
 import com.sun.tools.javac.parser.Parser;
 import com.sun.tools.javac.parser.ParserFactory;
@@ -51,7 +52,6 @@
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.main.JavaCompiler;
 
 /**
  * Provides access to functionality specific to the JDK Java Compiler, javac.
@@ -64,18 +64,16 @@
  * @author Peter von der Ah&eacute;
  * @author Jonathan Gibbons
  */
-public class JavacTaskImpl extends JavacTask {
+public class JavacTaskImpl extends BasicJavacTask {
     private ClientCodeWrapper ccw;
     private Main compilerMain;
     private JavaCompiler compiler;
     private Locale locale;
     private String[] args;
     private String[] classNames;
-    private Context context;
     private List<JavaFileObject> fileObjects;
     private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
     private ListBuffer<Env<AttrContext>> genList;
-    private TaskListener taskListener;
     private AtomicBoolean used = new AtomicBoolean();
     private Iterable<? extends Processor> processors;
 
@@ -86,6 +84,7 @@
                 String[] classNames,
                 Context context,
                 List<JavaFileObject> fileObjects) {
+        super(null, false);
         this.ccw = ClientCodeWrapper.instance(context);
         this.compilerMain = compilerMain;
         this.args = args;
@@ -190,11 +189,7 @@
     }
 
     private void initContext() {
-        context.put(JavacTaskImpl.class, this);
-        if (context.get(TaskListener.class) != null)
-            context.put(TaskListener.class, (TaskListener)null);
-        if (taskListener != null)
-            context.put(TaskListener.class, ccw.wrap(taskListener));
+        context.put(JavacTask.class, this);
         //initialize compiler's default locale
         context.put(Locale.class, locale);
     }
@@ -224,10 +219,6 @@
         return fm.getRegularFile(file);
     }
 
-    public void setTaskListener(TaskListener taskListener) {
-        this.taskListener = taskListener;
-    }
-
     /**
      * Parse the specified files returning a list of abstract syntax trees.
      *
--- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -26,7 +26,7 @@
 package com.sun.tools.javac.api;
 
 import java.io.IOException;
-import java.util.Map;
+
 import javax.annotation.processing.ProcessingEnvironment;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.AnnotationValue;
@@ -44,13 +44,14 @@
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.Scope;
 import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
 import com.sun.source.util.SourcePositions;
 import com.sun.source.util.TreePath;
 import com.sun.source.util.Trees;
 import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.TypeSymbol;
-import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type.UnionClassType;
 import com.sun.tools.javac.comp.Attr;
 import com.sun.tools.javac.comp.AttrContext;
@@ -61,8 +62,8 @@
 import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.parser.EndPosTable;
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.TreeCopier;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.tree.TreeMaker;
@@ -95,12 +96,14 @@
     private JavacElements elements;
     private JavacTaskImpl javacTaskImpl;
 
+    // called reflectively from Trees.instance(CompilationTask task)
     public static JavacTrees instance(JavaCompiler.CompilationTask task) {
         if (!(task instanceof JavacTaskImpl))
             throw new IllegalArgumentException();
         return instance(((JavacTaskImpl)task).getContext());
     }
 
+    // called reflectively from Trees.instance(ProcessingEnvironment env)
     public static JavacTrees instance(ProcessingEnvironment env) {
         if (!(env instanceof JavacProcessingEnvironment))
             throw new IllegalArgumentException();
@@ -131,7 +134,10 @@
         resolve = Resolve.instance(context);
         treeMaker = TreeMaker.instance(context);
         memberEnter = MemberEnter.instance(context);
-        javacTaskImpl = context.get(JavacTaskImpl.class);
+
+        JavacTask t = context.get(JavacTask.class);
+        if (t instanceof JavacTaskImpl)
+            javacTaskImpl = (JavacTaskImpl) t;
     }
 
     public SourcePositions getSourcePositions() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/api/MultiTaskListener.java	Mon Mar 05 17:04:48 2012 -0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011, 2012, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.api;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.util.Context;
+
+/**
+ * TODO.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class MultiTaskListener implements TaskListener {
+    /** The context key for the MultiTaskListener. */
+    public static final Context.Key<MultiTaskListener> taskListenerKey =
+        new Context.Key<MultiTaskListener>();
+
+    /** Get the MultiTaskListener instance for this context. */
+    public static MultiTaskListener instance(Context context) {
+        MultiTaskListener instance = context.get(taskListenerKey);
+        if (instance == null)
+            instance = new MultiTaskListener(context);
+        return instance;
+    }
+
+    protected MultiTaskListener(Context context) {
+        context.put(taskListenerKey, this);
+        ccw = ClientCodeWrapper.instance(context);
+    }
+
+    /**
+     * The current set of registered listeners.
+     * This is a mutable reference to an immutable array.
+     */
+    TaskListener[] listeners = { };
+
+    ClientCodeWrapper ccw;
+
+    public Collection<TaskListener> getTaskListeners() {
+        return Arrays.asList(listeners);
+    }
+
+    public boolean isEmpty() {
+        return (listeners.length == 0);
+    }
+
+    public void add(TaskListener listener) {
+        for (TaskListener l: listeners) {
+            if (ccw.unwrap(l) == listener)
+                throw new IllegalStateException();
+        }
+        TaskListener[] newListeners = new TaskListener[listeners.length + 1];
+        System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
+        newListeners[newListeners.length - 1] = ccw.wrap(listener);
+        listeners = newListeners;
+    }
+
+    public void remove(TaskListener listener) {
+        for (int i = 0; i < listeners.length; i++) {
+            if (ccw.unwrap(listeners[i]) == listener) {
+                TaskListener[] newListeners = new TaskListener[listeners.length - 1];
+                System.arraycopy(listeners, 0, newListeners, 0, i);
+                System.arraycopy(listeners, i + 1, newListeners, i, newListeners.length - i);
+                listeners = newListeners;
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void started(TaskEvent e) {
+        // guard against listeners being updated by a listener
+        TaskListener[] ll = this.listeners;
+        for (TaskListener l: ll)
+            l.started(e);
+    }
+
+    @Override
+    public void finished(TaskEvent e) {
+        // guard against listeners being updated by a listener
+        TaskListener[] ll = this.listeners;
+        for (TaskListener l: ll)
+            l.finished(e);
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(listeners);
+    }
+}
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1146,7 +1146,8 @@
 
     void checkAutoCloseable(DiagnosticPosition pos, Env<AttrContext> env, Type resource) {
         if (!resource.isErroneous() &&
-                types.asSuper(resource, syms.autoCloseableType.tsym) != null) {
+            types.asSuper(resource, syms.autoCloseableType.tsym) != null &&
+            !types.isSameType(resource, syms.autoCloseableType)) { // Don't emit warning for AutoCloseable itself
             Symbol close = syms.noSymbol;
             boolean prevDeferDiags = log.deferDiagnostics;
             Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
--- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -28,8 +28,8 @@
 import java.io.*;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.Queue;
@@ -41,13 +41,13 @@
 
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
+import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileObject;
-import javax.tools.DiagnosticListener;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-
+import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Symbol.*;
@@ -60,8 +60,6 @@
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.Log.WriterKind;
-
-import static javax.tools.StandardLocation.CLASS_OUTPUT;
 import static com.sun.tools.javac.main.Option.*;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
 import static com.sun.tools.javac.util.ListBuffer.lb;
@@ -289,9 +287,9 @@
      */
     protected ParserFactory parserFactory;
 
-    /** Optional listener for progress events
+    /** Broadcasting listener for progress events
      */
-    protected TaskListener taskListener;
+    protected MultiTaskListener taskListener;
 
     /**
      * Annotation processing may require and provide a new instance
@@ -356,7 +354,7 @@
         lower = Lower.instance(context);
         annotate = Annotate.instance(context);
         types = Types.instance(context);
-        taskListener = context.get(TaskListener.class);
+        taskListener = MultiTaskListener.instance(context);
 
         reader.sourceCompleter = this;
 
@@ -592,7 +590,7 @@
             if (verbose) {
                 log.printVerbose("parsing.started", filename);
             }
-            if (taskListener != null) {
+            if (!taskListener.isEmpty()) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename);
                 taskListener.started(e);
             }
@@ -605,7 +603,7 @@
 
         tree.sourcefile = filename;
 
-        if (content != null && taskListener != null) {
+        if (content != null && !taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
             taskListener.finished(e);
         }
@@ -751,14 +749,14 @@
             log.useSource(prev);
         }
 
-        if (taskListener != null) {
+        if (!taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
             taskListener.started(e);
         }
 
         enter.complete(List.of(tree), c);
 
-        if (taskListener != null) {
+        if (!taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
             taskListener.finished(e);
         }
@@ -924,7 +922,7 @@
      */
     public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {
         //enter symbols for all files
-        if (taskListener != null) {
+        if (!taskListener.isEmpty()) {
             for (JCCompilationUnit unit: roots) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
                 taskListener.started(e);
@@ -933,7 +931,7 @@
 
         enter.main(roots);
 
-        if (taskListener != null) {
+        if (!taskListener.isEmpty()) {
             for (JCCompilationUnit unit: roots) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
                 taskListener.finished(e);
@@ -1002,7 +1000,7 @@
                 reader.saveParameterNames = true;
                 keepComments = true;
                 genEndPos = true;
-                if (taskListener != null)
+                if (!taskListener.isEmpty())
                     taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
                 log.deferDiagnostics = true;
             } else { // free resources
@@ -1017,7 +1015,7 @@
     }
 
     /**
-     * Process any anotations found in the specifed compilation units.
+     * Process any annotations found in the specified compilation units.
      * @param roots a list of compilation units
      * @return an instance of the compiler in which to complete the compilation
      */
@@ -1176,7 +1174,7 @@
         if (verbose)
             log.printVerbose("checking.attribution", env.enclClass.sym);
 
-        if (taskListener != null) {
+        if (!taskListener.isEmpty()) {
             TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
             taskListener.started(e);
         }
@@ -1259,7 +1257,7 @@
             }
         }
         finally {
-            if (taskListener != null) {
+            if (!taskListener.isEmpty()) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym);
                 taskListener.finished(e);
             }
@@ -1440,7 +1438,7 @@
                                + " " + cdef.sym + "]");
             }
 
-            if (taskListener != null) {
+            if (!taskListener.isEmpty()) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
                 taskListener.started(e);
             }
@@ -1464,7 +1462,7 @@
                 log.useSource(prev);
             }
 
-            if (taskListener != null) {
+            if (!taskListener.isEmpty()) {
                 TaskEvent e = new TaskEvent(TaskEvent.Kind.GENERATE, env.toplevel, cdef.sym);
                 taskListener.finished(e);
             }
--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -25,34 +25,33 @@
 
 package com.sun.tools.javac.processing;
 
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.regex.*;
-
-import java.net.URL;
 import java.io.Closeable;
 import java.io.File;
 import java.io.PrintWriter;
-import java.io.IOException;
 import java.io.StringWriter;
 import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import java.util.regex.*;
 
 import javax.annotation.processing.*;
 import javax.lang.model.SourceVersion;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.PackageElement;
 import javax.lang.model.util.*;
+import javax.tools.DiagnosticListener;
 import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
-import javax.tools.JavaFileObject;
-import javax.tools.DiagnosticListener;
+import static javax.tools.StandardLocation.*;
 
+import com.sun.source.util.JavacTask;
 import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
 import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.api.JavacTrees;
+import com.sun.tools.javac.api.MultiTaskListener;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.file.FSInfo;
@@ -71,19 +70,16 @@
 import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.Convert;
-import com.sun.tools.javac.util.FatalError;
 import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JavacMessages;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
-import com.sun.tools.javac.util.JavacMessages;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Options;
-
-import static javax.tools.StandardLocation.*;
+import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
+import static com.sun.tools.javac.main.Option.*;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
-import static com.sun.tools.javac.main.Option.*;
-import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
 
 /**
  * Objects of this class hold and manage the state needed to support
@@ -157,6 +153,8 @@
      */
     private JavacMessages messages;
 
+    private MultiTaskListener taskListener;
+
     private Context context;
 
     public JavacProcessingEnvironment(Context context, Iterable<? extends Processor> processors) {
@@ -185,6 +183,7 @@
         processorOptions = initProcessorOptions(context);
         unmatchedProcessorOptions = initUnmatchedProcessorOptions();
         messages = JavacMessages.instance(context);
+        taskListener = MultiTaskListener.instance(context);
         initProcessorIterator(context, processors);
     }
 
@@ -976,8 +975,7 @@
         void run(boolean lastRound, boolean errorStatus) {
             printRoundInfo(lastRound);
 
-            TaskListener taskListener = context.get(TaskListener.class);
-            if (taskListener != null)
+            if (!taskListener.isEmpty())
                 taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
 
             try {
@@ -993,7 +991,7 @@
                     discoverAndRunProcs(context, annotationsPresent, topLevelClasses, packageInfoFiles);
                 }
             } finally {
-                if (taskListener != null)
+                if (!taskListener.isEmpty())
                     taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
             }
 
@@ -1051,9 +1049,9 @@
             if (dl != null)
                 next.put(DiagnosticListener.class, dl);
 
-            TaskListener tl = context.get(TaskListener.class);
-            if (tl != null)
-                next.put(TaskListener.class, tl);
+            MultiTaskListener mtl = context.get(MultiTaskListener.taskListenerKey);
+            if (mtl != null)
+                next.put(MultiTaskListener.taskListenerKey, mtl);
 
             FSInfo fsInfo = context.get(FSInfo.class);
             if (fsInfo != null)
@@ -1086,9 +1084,9 @@
             elementUtils.setContext(next);
             typeUtils.setContext(next);
 
-            JavacTaskImpl task = context.get(JavacTaskImpl.class);
+            JavacTaskImpl task = (JavacTaskImpl) context.get(JavacTask.class);
             if (task != null) {
-                next.put(JavacTaskImpl.class, task);
+                next.put(JavacTask.class, task);
                 task.updateContext(next);
             }
 
@@ -1110,8 +1108,6 @@
                                      List<JCCompilationUnit> roots,
                                      List<ClassSymbol> classSymbols,
                                      Iterable<? extends PackageSymbol> pckSymbols) {
-
-        TaskListener taskListener = context.get(TaskListener.class);
         log = Log.instance(context);
 
         Set<PackageSymbol> specifiedPackages = new LinkedHashSet<PackageSymbol>();
@@ -1182,7 +1178,7 @@
         // Free resources
         this.close();
 
-        if (taskListener != null)
+        if (!taskListener.isEmpty())
             taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
 
         if (errorStatus) {
--- a/src/share/classes/com/sun/tools/javac/util/Names.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/src/share/classes/com/sun/tools/javac/util/Names.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -47,108 +47,127 @@
         return instance;
     }
 
-    public final Name slash;
+    // operators and punctuation
+    public final Name asterisk;
+    public final Name comma;
+    public final Name empty;
     public final Name hyphen;
-    public final Name T;
-    public final Name slashequals;
-    public final Name deprecated;
-    public final Name init;
-    public final Name clinit;
-    public final Name error;
-    public final Name any;
-    public final Name empty;
     public final Name one;
     public final Name period;
-    public final Name comma;
     public final Name semicolon;
-    public final Name asterisk;
+    public final Name slash;
+    public final Name slashequals;
+
+    // keywords
+    public final Name _class;
+    public final Name _default;
+    public final Name _super;
     public final Name _this;
-    public final Name _super;
-    public final Name _default;
-    public final Name _class;
-    public final Name java_lang;
-    public final Name java_lang_Object;
+
+    // field and method names
+    public final Name _name;
+    public final Name addSuppressed;
+    public final Name any;
+    public final Name append;
+    public final Name clinit;
+    public final Name clone;
+    public final Name close;
+    public final Name compareTo;
+    public final Name desiredAssertionStatus;
+    public final Name equals;
+    public final Name error;
+    public final Name family;
+    public final Name finalize;
+    public final Name forName;
+    public final Name getClass;
+    public final Name getClassLoader;
+    public final Name getComponentType;
+    public final Name getDeclaringClass;
+    public final Name getMessage;
+    public final Name hasNext;
+    public final Name hashCode;
+    public final Name init;
+    public final Name initCause;
+    public final Name iterator;
+    public final Name length;
+    public final Name next;
+    public final Name ordinal;
+    public final Name serialVersionUID;
+    public final Name toString;
+    public final Name value;
+    public final Name valueOf;
+    public final Name values;
+
+    // class names
+    public final Name java_io_Serializable;
+    public final Name java_lang_AutoCloseable;
     public final Name java_lang_Class;
     public final Name java_lang_Cloneable;
-    public final Name java_io_Serializable;
-    public final Name serialVersionUID;
     public final Name java_lang_Enum;
+    public final Name java_lang_Object;
     public final Name java_lang_invoke_MethodHandle;
-    public final Name package_info;
+
+    // names of builtin classes
+    public final Name Array;
+    public final Name Bound;
+    public final Name Method;
+
+    // package names
+    public final Name java_lang;
+
+    // attribute names
+    public final Name Annotation;
+    public final Name AnnotationDefault;
+    public final Name Bridge;
+    public final Name CharacterRangeTable;
+    public final Name Code;
+    public final Name CompilationID;
     public final Name ConstantValue;
+    public final Name Deprecated;
+    public final Name EnclosingMethod;
+    public final Name Enum;
+    public final Name Exceptions;
+    public final Name InnerClasses;
     public final Name LineNumberTable;
     public final Name LocalVariableTable;
     public final Name LocalVariableTypeTable;
-    public final Name CharacterRangeTable;
+    public final Name RuntimeInvisibleAnnotations;
+    public final Name RuntimeInvisibleParameterAnnotations;
+    public final Name RuntimeInvisibleTypeAnnotations;
+    public final Name RuntimeVisibleAnnotations;
+    public final Name RuntimeVisibleParameterAnnotations;
+    public final Name RuntimeVisibleTypeAnnotations;
+    public final Name Signature;
+    public final Name SourceFile;
+    public final Name SourceID;
     public final Name StackMap;
     public final Name StackMapTable;
-    public final Name SourceID;
-    public final Name CompilationID;
-    public final Name Code;
-    public final Name Exceptions;
-    public final Name SourceFile;
-    public final Name InnerClasses;
     public final Name Synthetic;
-    public final Name Bridge;
-    public final Name Deprecated;
-    public final Name Enum;
-    public final Name _name;
-    public final Name Signature;
+    public final Name Value;
     public final Name Varargs;
-    public final Name Annotation;
-    public final Name RuntimeVisibleAnnotations;
-    public final Name RuntimeInvisibleAnnotations;
-    public final Name RuntimeVisibleTypeAnnotations;
-    public final Name RuntimeInvisibleTypeAnnotations;
-    public final Name RuntimeVisibleParameterAnnotations;
-    public final Name RuntimeInvisibleParameterAnnotations;
-    public final Name Value;
-    public final Name EnclosingMethod;
-    public final Name desiredAssertionStatus;
-    public final Name append;
-    public final Name family;
-    public final Name forName;
-    public final Name toString;
-    public final Name length;
-    public final Name valueOf;
-    public final Name value;
-    public final Name getMessage;
-    public final Name getClass;
+
+    // members of java.lang.annotation.ElementType
+    public final Name ANNOTATION_TYPE;
+    public final Name CONSTRUCTOR;
+    public final Name FIELD;
+    public final Name LOCAL_VARIABLE;
+    public final Name METHOD;
+    public final Name PACKAGE;
+    public final Name PARAMETER;
     public final Name TYPE;
+    public final Name TYPE_PARAMETER;
     public final Name TYPE_USE;
-    public final Name TYPE_PARAMETER;
-    public final Name FIELD;
-    public final Name METHOD;
-    public final Name PARAMETER;
-    public final Name CONSTRUCTOR;
-    public final Name LOCAL_VARIABLE;
-    public final Name ANNOTATION_TYPE;
-    public final Name PACKAGE;
-    public final Name SOURCE;
+
+    // members of java.lang.annotation.RetentionPolicy
     public final Name CLASS;
     public final Name RUNTIME;
-    public final Name Array;
-    public final Name Method;
-    public final Name Bound;
-    public final Name clone;
-    public final Name getComponentType;
-    public final Name getClassLoader;
-    public final Name initCause;
-    public final Name values;
-    public final Name iterator;
-    public final Name hasNext;
-    public final Name next;
-    public final Name AnnotationDefault;
-    public final Name ordinal;
-    public final Name equals;
-    public final Name hashCode;
-    public final Name compareTo;
-    public final Name getDeclaringClass;
+    public final Name SOURCE;
+
+    // other identifiers
+    public final Name T;
+    public final Name deprecated;
     public final Name ex;
-    public final Name finalize;
-    public final Name java_lang_AutoCloseable;
-    public final Name close;
-    public final Name addSuppressed;
+    public final Name package_info;
 
     public final Name.Table table;
 
@@ -156,116 +175,127 @@
         Options options = Options.instance(context);
         table = createTable(options);
 
-        slash = fromString("/");
+        // operators and punctuation
+        asterisk = fromString("*");
+        comma = fromString(",");
+        empty = fromString("");
         hyphen = fromString("-");
-        T = fromString("T");
-        slashequals = fromString("/=");
-        deprecated = fromString("deprecated");
-
-        init = fromString("<init>");
-        clinit = fromString("<clinit>");
-        error = fromString("<error>");
-        any = fromString("<any>");
-        empty = fromString("");
         one = fromString("1");
         period = fromString(".");
-        comma = fromString(",");
         semicolon = fromString(";");
-        asterisk = fromString("*");
+        slash = fromString("/");
+        slashequals = fromString("/=");
+
+        // keywords
+        _class = fromString("class");
+        _default = fromString("default");
+        _super = fromString("super");
         _this = fromString("this");
-        _super = fromString("super");
-        _default = fromString("default");
 
-        _class = fromString("class");
-        java_lang = fromString("java.lang");
-        java_lang_Object = fromString("java.lang.Object");
+        // field and method names
+        _name = fromString("name");
+        addSuppressed = fromString("addSuppressed");
+        any = fromString("<any>");
+        append = fromString("append");
+        clinit = fromString("<clinit>");
+        clone = fromString("clone");
+        close = fromString("close");
+        compareTo = fromString("compareTo");
+        desiredAssertionStatus = fromString("desiredAssertionStatus");
+        equals = fromString("equals");
+        error = fromString("<error>");
+        family = fromString("family");
+        finalize = fromString("finalize");
+        forName = fromString("forName");
+        getClass = fromString("getClass");
+        getClassLoader = fromString("getClassLoader");
+        getComponentType = fromString("getComponentType");
+        getDeclaringClass = fromString("getDeclaringClass");
+        getMessage = fromString("getMessage");
+        hasNext = fromString("hasNext");
+        hashCode = fromString("hashCode");
+        init = fromString("<init>");
+        initCause = fromString("initCause");
+        iterator = fromString("iterator");
+        length = fromString("length");
+        next = fromString("next");
+        ordinal = fromString("ordinal");
+        serialVersionUID = fromString("serialVersionUID");
+        toString = fromString("toString");
+        value = fromString("value");
+        valueOf = fromString("valueOf");
+        values = fromString("values");
+
+        // class names
+        java_io_Serializable = fromString("java.io.Serializable");
+        java_lang_AutoCloseable = fromString("java.lang.AutoCloseable");
         java_lang_Class = fromString("java.lang.Class");
         java_lang_Cloneable = fromString("java.lang.Cloneable");
-        java_io_Serializable = fromString("java.io.Serializable");
         java_lang_Enum = fromString("java.lang.Enum");
+        java_lang_Object = fromString("java.lang.Object");
         java_lang_invoke_MethodHandle = fromString("java.lang.invoke.MethodHandle");
-        package_info = fromString("package-info");
-        serialVersionUID = fromString("serialVersionUID");
+
+        // names of builtin classes
+        Array = fromString("Array");
+        Bound = fromString("Bound");
+        Method = fromString("Method");
+
+        // package names
+        java_lang = fromString("java.lang");
+
+        // attribute names
+        Annotation = fromString("Annotation");
+        AnnotationDefault = fromString("AnnotationDefault");
+        Bridge = fromString("Bridge");
+        CharacterRangeTable = fromString("CharacterRangeTable");
+        Code = fromString("Code");
+        CompilationID = fromString("CompilationID");
         ConstantValue = fromString("ConstantValue");
+        Deprecated = fromString("Deprecated");
+        EnclosingMethod = fromString("EnclosingMethod");
+        Enum = fromString("Enum");
+        Exceptions = fromString("Exceptions");
+        InnerClasses = fromString("InnerClasses");
         LineNumberTable = fromString("LineNumberTable");
         LocalVariableTable = fromString("LocalVariableTable");
         LocalVariableTypeTable = fromString("LocalVariableTypeTable");
-        CharacterRangeTable = fromString("CharacterRangeTable");
+        RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
+        RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
+        RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
+        RuntimeVisibleAnnotations = fromString("RuntimeVisibleAnnotations");
+        RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations");
+        RuntimeVisibleTypeAnnotations = fromString("RuntimeVisibleTypeAnnotations");
+        Signature = fromString("Signature");
+        SourceFile = fromString("SourceFile");
+        SourceID = fromString("SourceID");
         StackMap = fromString("StackMap");
         StackMapTable = fromString("StackMapTable");
-        SourceID = fromString("SourceID");
-        CompilationID = fromString("CompilationID");
-        Code = fromString("Code");
-        Exceptions = fromString("Exceptions");
-        SourceFile = fromString("SourceFile");
-        InnerClasses = fromString("InnerClasses");
         Synthetic = fromString("Synthetic");
-        Bridge = fromString("Bridge");
-        Deprecated = fromString("Deprecated");
-        Enum = fromString("Enum");
-        _name = fromString("name");
-        Signature = fromString("Signature");
+        Value = fromString("Value");
         Varargs = fromString("Varargs");
-        Annotation = fromString("Annotation");
-        RuntimeVisibleAnnotations = fromString("RuntimeVisibleAnnotations");
-        RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
-        RuntimeVisibleTypeAnnotations = fromString("RuntimeVisibleTypeAnnotations");
-        RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
-        RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations");
-        RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
-        Value = fromString("Value");
-        EnclosingMethod = fromString("EnclosingMethod");
 
-        desiredAssertionStatus = fromString("desiredAssertionStatus");
+        // members of java.lang.annotation.ElementType
+        ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
+        CONSTRUCTOR = fromString("CONSTRUCTOR");
+        FIELD = fromString("FIELD");
+        LOCAL_VARIABLE = fromString("LOCAL_VARIABLE");
+        METHOD = fromString("METHOD");
+        PACKAGE = fromString("PACKAGE");
+        PARAMETER = fromString("PARAMETER");
+        TYPE = fromString("TYPE");
+        TYPE_PARAMETER = fromString("TYPE_PARAMETER");
+        TYPE_USE = fromString("TYPE_USE");
 
-        append = fromString("append");
-        family = fromString("family");
-        forName = fromString("forName");
-        toString = fromString("toString");
-        length = fromString("length");
-        valueOf = fromString("valueOf");
-        value = fromString("value");
-        getMessage = fromString("getMessage");
-        getClass = fromString("getClass");
-
-        TYPE = fromString("TYPE");
-        TYPE_USE = fromString("TYPE_USE");
-        TYPE_PARAMETER = fromString("TYPE_PARAMETER");
-        FIELD = fromString("FIELD");
-        METHOD = fromString("METHOD");
-        PARAMETER = fromString("PARAMETER");
-        CONSTRUCTOR = fromString("CONSTRUCTOR");
-        LOCAL_VARIABLE = fromString("LOCAL_VARIABLE");
-        ANNOTATION_TYPE = fromString("ANNOTATION_TYPE");
-        PACKAGE = fromString("PACKAGE");
-
-        SOURCE = fromString("SOURCE");
+        // members of java.lang.annotation.RetentionPolicy
         CLASS = fromString("CLASS");
         RUNTIME = fromString("RUNTIME");
+        SOURCE = fromString("SOURCE");
 
-        Array = fromString("Array");
-        Method = fromString("Method");
-        Bound = fromString("Bound");
-        clone = fromString("clone");
-        getComponentType = fromString("getComponentType");
-        getClassLoader = fromString("getClassLoader");
-        initCause = fromString("initCause");
-        values = fromString("values");
-        iterator = fromString("iterator");
-        hasNext = fromString("hasNext");
-        next = fromString("next");
-        AnnotationDefault = fromString("AnnotationDefault");
-        ordinal = fromString("ordinal");
-        equals = fromString("equals");
-        hashCode = fromString("hashCode");
-        compareTo = fromString("compareTo");
-        getDeclaringClass = fromString("getDeclaringClass");
+        // other identifiers
+        T = fromString("T");
+        deprecated = fromString("deprecated");
         ex = fromString("ex");
-        finalize = fromString("finalize");
-
-        java_lang_AutoCloseable = fromString("java.lang.AutoCloseable");
-        close = fromString("close");
-        addSuppressed = fromString("addSuppressed");
+        package_info = fromString("package-info");
     }
 
     protected Name.Table createTable(Options options) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/taskListeners/TestSimpleAddRemove.java	Mon Mar 05 17:04:48 2012 -0800
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2011, 2012, 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     7093891
+ * @summary support multiple task listeners
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.TypeElement;
+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;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.api.JavacTool;
+
+public class TestSimpleAddRemove {
+    enum AddKind {
+        SET_IN_TASK,
+        ADD_IN_TASK,
+        ADD_IN_PROCESSOR,
+        ADD_IN_LISTENER;
+    }
+
+    enum RemoveKind {
+        REMOVE_IN_TASK,
+        REMOVE_IN_PROCESSOR,
+        REMOVE_IN_LISTENER,
+    }
+
+    enum CompileKind {
+        CALL {
+            void run(JavacTask t) {
+                if (!t.call()) throw new Error("compilation failed");
+            }
+        },
+        GENERATE {
+            void run(JavacTask t) throws IOException {
+                t.generate();
+            }
+        };
+        abstract void run(JavacTask t) throws IOException;
+    }
+
+    static class EventKindCounter extends EnumMap<TaskEvent.Kind, EventKindCounter.Count> {
+        static class Count {
+            int started;
+            int finished;
+
+            @Override
+            public String toString() {
+                return started + ":" + finished;
+            }
+        }
+
+        EventKindCounter() {
+            super(TaskEvent.Kind.class);
+        }
+
+        void inc(TaskEvent.Kind k, boolean started) {
+            Count c = get(k);
+            if (c == null)
+                put(k, c = new Count());
+
+            if (started)
+                c.started++;
+            else
+                c.finished++;
+        }
+    }
+
+    static class TestListener implements TaskListener {
+        EventKindCounter counter;
+
+        TestListener(EventKindCounter c) {
+            counter = c;
+        }
+
+        public void started(TaskEvent e) {
+            counter.inc(e.getKind(), true);
+        }
+
+        public void finished(TaskEvent e) {
+            counter.inc(e.getKind(), false);
+        }
+    }
+
+    static void addInListener(final JavacTask task, final TaskEvent.Kind kind, final TaskListener listener) {
+        task.addTaskListener(new TaskListener() {
+            public void started(TaskEvent e) {
+                if (e.getKind() == kind) {
+                    task.addTaskListener(listener);
+                    task.removeTaskListener(this);
+                }
+            }
+
+            public void finished(TaskEvent e) { }
+        });
+    }
+
+    static void removeInListener(final JavacTask task, final TaskEvent.Kind kind, final TaskListener listener) {
+        task.addTaskListener(new TaskListener() {
+            public void started(TaskEvent e) {
+                if (e.getKind() == kind) {
+                    task.removeTaskListener(listener);
+                    task.removeTaskListener(this);
+                }
+            }
+
+            public void finished(TaskEvent e) { }
+        });
+    }
+
+    @SupportedAnnotationTypes("*")
+    class TestProcessor extends AbstractProcessor {
+        AddKind ak;
+        RemoveKind rk;
+        TaskListener listener;
+
+        TestProcessor(AddKind ak, RemoveKind rk, TaskListener listener) {
+            this.ak = ak;
+            this.rk = rk;
+            this.listener = listener;
+        }
+
+        int round = 0;
+
+        @Override
+        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+//            System.err.println("TestProcessor.process " + roundEnv);
+            JavacTask task = JavacTask.instance(processingEnv);
+            if (++round == 1) {
+                switch (ak) {
+                    case ADD_IN_PROCESSOR:
+                        task.addTaskListener(listener);
+                        break;
+                    case ADD_IN_LISTENER:
+                        addInListener(task, TaskEvent.Kind.ANALYZE, listener);
+                        break;
+                }
+            } else if (roundEnv.processingOver()) {
+                switch (rk) {
+                    case REMOVE_IN_PROCESSOR:
+                        task.removeTaskListener(listener);
+                        break;
+                    case REMOVE_IN_LISTENER:
+                        removeInListener(task, TaskEvent.Kind.GENERATE, listener);
+                        break;
+                }
+            }
+            return true;
+        }
+    }
+
+    static class TestSource extends SimpleJavaFileObject {
+        public TestSource() {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return "class Test { }";
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        new TestSimpleAddRemove().run();
+    }
+
+    JavacTool tool = (JavacTool) ToolProvider.getSystemJavaCompiler();
+    StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+
+    void run() throws Exception {
+        for (CompileKind ck: CompileKind.values()) {
+            for (AddKind ak: AddKind.values()) {
+                for (RemoveKind rk: RemoveKind.values()) {
+                    test(ck, ak, rk);
+                }
+            }
+        }
+        if (errors > 0)
+            throw new Exception(errors + " errors occurred");
+    }
+
+    void test(CompileKind ck, AddKind ak, RemoveKind rk) throws IOException {
+        System.err.println("Test: " + ck + " " + ak + " " + rk);
+
+        File tmpDir = new File(ck + "-" + ak + "-" + rk);
+        tmpDir.mkdirs();
+        fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tmpDir));
+
+        List<String> options = new ArrayList<String>();
+        Iterable<? extends JavaFileObject> files = Arrays.asList(new TestSource());
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        JavacTask task = tool.getTask(pw, fm, null, options, null, files);
+
+        EventKindCounter ec = new EventKindCounter();
+        TaskListener listener = new TestListener(ec);
+        boolean needProcessor = false;
+
+        switch (ak) {
+            case SET_IN_TASK:
+                task.setTaskListener(listener);
+                break;
+            case ADD_IN_TASK:
+                task.addTaskListener(listener);
+                break;
+            case ADD_IN_PROCESSOR:
+            case ADD_IN_LISTENER:
+                needProcessor = true;
+        }
+
+        switch (rk) {
+            case REMOVE_IN_TASK:
+                task.removeTaskListener(listener);
+                break;
+            case REMOVE_IN_PROCESSOR:
+            case REMOVE_IN_LISTENER:
+                needProcessor = true;
+        }
+
+        if (needProcessor)
+            task.setProcessors(Arrays.asList(new TestProcessor(ak, rk, listener)));
+
+        ck.run(task);
+        System.err.println(ec);
+
+        check(ck, ak, rk, ec);
+
+        System.err.println();
+    }
+
+    void check(CompileKind ck, AddKind ak, RemoveKind rk, EventKindCounter ec) {
+        // All results should be independent of ck, so we can ignore that
+
+        // Quick way to compare expected values of ec, by comparing ec.toString()
+        String expect = ec.toString();
+        String found;
+
+        switch (ak) {
+            // Add/set in task should record all events until the listener is removed
+            case SET_IN_TASK:
+            case ADD_IN_TASK:
+                switch (rk) {
+                    case REMOVE_IN_TASK:
+                        // Remove will succeed, meaning no events will be recorded
+                        found = "{}";
+                        break;
+                    case REMOVE_IN_PROCESSOR:
+                        found = "{PARSE=1:1, ENTER=2:2, ANNOTATION_PROCESSING=1:0, ANNOTATION_PROCESSING_ROUND=2:1}";
+                        break;
+                    case REMOVE_IN_LISTENER:
+                        found = "{PARSE=1:1, ENTER=3:3, ANALYZE=1:1, GENERATE=1:0, ANNOTATION_PROCESSING=1:1, ANNOTATION_PROCESSING_ROUND=2:2}";
+                        break;
+                    default:
+                        throw new IllegalStateException();
+                }
+                break;
+
+            // "Add in processor" should skip initial PARSE/ENTER events
+            case ADD_IN_PROCESSOR:
+                switch (rk) {
+                    // Remove will fail (too early), so events to end will be recorded
+                    case REMOVE_IN_TASK:
+                        found = "{ENTER=2:2, ANALYZE=1:1, GENERATE=1:1, ANNOTATION_PROCESSING=0:1, ANNOTATION_PROCESSING_ROUND=1:2}";
+                        break;
+                    case REMOVE_IN_PROCESSOR:
+                        found = "{ENTER=1:1, ANNOTATION_PROCESSING_ROUND=1:1}";
+                        break;
+                    case REMOVE_IN_LISTENER:
+                        found = "{ENTER=2:2, ANALYZE=1:1, GENERATE=1:0, ANNOTATION_PROCESSING=0:1, ANNOTATION_PROCESSING_ROUND=1:2}";
+                        break;
+                    default:
+                        throw new IllegalStateException();
+                }
+                break;
+
+            // "Add in listener" will occur during "ANALYSE.started" event
+            case ADD_IN_LISTENER:
+                switch (rk) {
+                    // Remove will fail (too early, so events to end will be recorded
+                    case REMOVE_IN_TASK:
+                    case REMOVE_IN_PROCESSOR:
+                        found = "{ANALYZE=0:1, GENERATE=1:1}";
+                        break;
+                    // Remove will succeed during "GENERATE.finished" event
+                    case REMOVE_IN_LISTENER:
+                        found = "{ANALYZE=0:1, GENERATE=1:0}";
+                        break;
+                    default:
+                        throw new IllegalStateException();
+                }
+                break;
+            default:
+                throw new IllegalStateException();
+        }
+
+        if (!found.equals(expect)) {
+            System.err.println("Expected: " + expect);
+            System.err.println("   Found: " + found);
+            error("unexpected value found");
+        }
+    }
+
+    int errors;
+
+    void error(String message) {
+        System.err.println("Error: " + message);
+        errors++;
+    }
+}
--- a/test/tools/javac/apt.sh	Thu Mar 01 12:23:33 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#! /bin/sh -f
-
-#
-# Copyright (c) 2005, 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.
-#
-
-# 
-# Usage:
-#  @run apt.sh <apt-args>
-#
-# This script is to run apt for a regression test
-
-if [ "${TESTJAVA}" = "" ]
-then
-  echo "TESTJAVA not set.  Test cannot execute.  Failed."
-  exit 1
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  SunOS | Linux )
-    NULL=/dev/null
-    PS=":"
-    FS="/"
-    ;;
-  Windows* )
-    NULL=NUL
-    PS=";"
-    FS="\\"
-    ;;
-  * )
-    echo "Unrecognized system!"
-    exit 1;
-    ;;
-esac
-
-CLASSPATH="${TESTCLASSES}${PS}${TESTJAVA}${FS}lib${FS}tools.jar" "${TESTJAVA}${FS}bin${FS}apt" ${TESTTOOLVMOPTS} $*
-result=$?
-
-if [ $result -eq 0 ]
-then
-  echo "Passed"
-else
-  echo "Failed"
-fi
-exit $result
-
-
--- a/test/tools/javac/processing/loader/testClose/TestClose.java	Thu Mar 01 12:23:33 2012 -0800
+++ b/test/tools/javac/processing/loader/testClose/TestClose.java	Mon Mar 05 17:04:48 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, 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
@@ -31,6 +31,7 @@
 import com.sun.source.util.TaskEvent;
 import com.sun.source.util.TaskListener;
 import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
+import com.sun.tools.javac.api.BasicJavacTask;
 import com.sun.tools.javac.api.JavacTool;
 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
 import com.sun.tools.javac.util.Context;
@@ -89,10 +90,10 @@
         "                public void run() {\n" +
         "                    System.out.println(getClass().getName() + \": run()\");\n" +
         "                    try {\n" +
-        "                    cl.loadClass(\"Callback\")\n" +
-        "                        .asSubclass(Runnable.class)\n" +
-        "                        .newInstance()\n" +
-        "                        .run();\n" +
+        "                        cl.loadClass(\"Callback\")\n" +
+        "                            .asSubclass(Runnable.class)\n" +
+        "                            .newInstance()\n" +
+        "                            .run();\n" +
         "                    } catch (ReflectiveOperationException e) {\n" +
         "                        throw new Error(e);\n" +
         "                    }\n" +
@@ -184,25 +185,24 @@
             throw new AssertionError();
     }
 
-
     public static void add(ProcessingEnvironment env, Runnable r) {
         try {
-            Context c = ((JavacProcessingEnvironment) env).getContext();
-            Object o = c.get(TaskListener.class);
+            JavacTask task = JavacTask.instance(env);
+            TaskListener l = ((BasicJavacTask) task).getTaskListeners().iterator().next();
             // The TaskListener is an instanceof TestClose, but when using the
             // default class loaders. the taskListener uses a different
             // instance of Class<TestClose> than the anno processor.
             // If you try to evaluate
-            //      TestClose tc = (TestClose) (o).
+            //      TestClose tc = (TestClose) (l).
             // you get the following somewhat confusing error:
             //   java.lang.ClassCastException: TestClose cannot be cast to TestClose
             // The workaround is to access the fields of TestClose with reflection.
-            Field f = o.getClass().getField("runnables");
+            Field f = l.getClass().getField("runnables");
             @SuppressWarnings("unchecked")
-            List<Runnable> runnables = (List<Runnable>) f.get(o);
+            List<Runnable> runnables = (List<Runnable>) f.get(l);
             runnables.add(r);
         } catch (Throwable t) {
-            System.err.println(t);
+            t.printStackTrace();
         }
     }