6493690: javadoc should have a javax.tools.Tool service provider installed in tools.jar
authorjjg
Thu, 15 Nov 2012 23:07:24 -0800
changeset 14545 2e7bab0639b8
parent 14544 d71d992cb905
child 14546 7e2a1569de76
6493690: javadoc should have a javax.tools.Tool service provider installed in tools.jar Reviewed-by: darcy
langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java
langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java
langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java
langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java
langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java
langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java
langtools/src/share/classes/com/sun/tools/javadoc/Messager.java
langtools/src/share/classes/com/sun/tools/javadoc/Start.java
langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java
langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java
langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties
langtools/src/share/classes/javax/tools/DocumentationTool.java
langtools/src/share/classes/javax/tools/JavaCompiler.java
langtools/src/share/classes/javax/tools/ToolProvider.java
langtools/test/tools/javadoc/CheckResourceKeys.java
langtools/test/tools/javadoc/api/basic/APITest.java
langtools/test/tools/javadoc/api/basic/DocletPathTest.java
langtools/test/tools/javadoc/api/basic/GetSourceVersionsTest.java
langtools/test/tools/javadoc/api/basic/GetTask_DiagListenerTest.java
langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java
langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java
langtools/test/tools/javadoc/api/basic/GetTask_FileObjectsTest.java
langtools/test/tools/javadoc/api/basic/GetTask_OptionsTest.java
langtools/test/tools/javadoc/api/basic/GetTask_WriterTest.java
langtools/test/tools/javadoc/api/basic/IsSupportedOptionTest.java
langtools/test/tools/javadoc/api/basic/JavadocTaskImplTest.java
langtools/test/tools/javadoc/api/basic/RunTest.java
langtools/test/tools/javadoc/api/basic/TagletPathTest.java
langtools/test/tools/javadoc/api/basic/Task_reuseTest.java
langtools/test/tools/javadoc/api/basic/pkg/C.java
langtools/test/tools/javadoc/api/basic/taglets/UnderlineTaglet.java
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Thu Nov 15 23:07:24 2012 -0800
@@ -517,9 +517,14 @@
      */
     @Override
     public JavaFileManager getFileManager() {
-        if (root instanceof com.sun.tools.javadoc.RootDocImpl)
-            return ((com.sun.tools.javadoc.RootDocImpl)root).getFileManager();
-        else
-            return new JavacFileManager(new Context(), false, null);
+        if (fileManager == null) {
+            if (root instanceof com.sun.tools.javadoc.RootDocImpl)
+                fileManager = ((com.sun.tools.javadoc.RootDocImpl)root).getFileManager();
+            else
+                fileManager = new JavacFileManager(new Context(), false, null);
+        }
+        return fileManager;
     }
+
+    private JavaFileManager fileManager;
 }
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java	Thu Nov 15 23:07:24 2012 -0800
@@ -78,7 +78,7 @@
 
     /**
      * This is true if option "-serialwarn" is used. Defualt value is false to
-     * supress excessive warnings about serial tag.
+     * suppress excessive warnings about serial tag.
      */
     public boolean serialwarn = false;
 
@@ -446,7 +446,7 @@
     /**
      * Initialize the taglet manager.  The strings to initialize the simple custom tags should
      * be in the following format:  "[tag name]:[location str]:[heading]".
-     * @param customTagStrs the set two dimentional arrays of strings.  These arrays contain
+     * @param customTagStrs the set two dimensional arrays of strings.  These arrays contain
      * either -tag or -taglet arguments.
      */
     private void initTagletManager(Set<String[]> customTagStrs) {
@@ -457,11 +457,11 @@
         for (Iterator<String[]> it = customTagStrs.iterator(); it.hasNext(); ) {
             args = it.next();
             if (args[0].equals("-taglet")) {
-                tagletManager.addCustomTag(args[1], tagletpath);
+                tagletManager.addCustomTag(args[1], getFileManager(), tagletpath);
                 continue;
             }
             String[] tokens = tokenize(args[1],
-                TagletManager.SIMPLE_TAGLET_OPT_SEPERATOR, 3);
+                TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
             if (tokens.length == 1) {
                 String tagName = args[1];
                 if (tagletManager.isKnownCustomTag(tagName)) {
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Thu Nov 15 23:07:24 2012 -0800
@@ -30,6 +30,9 @@
 import java.net.*;
 import java.util.*;
 
+import javax.tools.DocumentationTool;
+import javax.tools.JavaFileManager;
+
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.util.*;
 
@@ -48,16 +51,16 @@
 public class TagletManager {
 
     /**
-     * The default seperator for the simple tag option.
+     * The default separator for the simple tag option.
      */
-    public static final char SIMPLE_TAGLET_OPT_SEPERATOR = ':';
+    public static final char SIMPLE_TAGLET_OPT_SEPARATOR = ':';
 
     /**
-     * The alternate seperator for simple tag options.  Use this
-     * with you want the default seperator to be in the name of the
+     * The alternate separator for simple tag options.  Use this
+     * when you want the default separator to be in the name of the
      * custom tag.
      */
-    public static final String ALT_SIMPLE_TAGLET_OPT_SEPERATOR = "-";
+    public static final String ALT_SIMPLE_TAGLET_OPT_SEPARATOR = "-";
 
     /**
      * The map of custom tags.
@@ -200,18 +203,24 @@
      * @param classname  the name of the class representing the custom tag.
      * @param tagletPath  the path to the class representing the custom tag.
      */
-    public void addCustomTag(String classname, String tagletPath) {
+    public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) {
         try {
             Class<?> customTagClass = null;
             // construct class loader
             String cpString = null;   // make sure env.class.path defaults to dot
 
-            // do prepends to get correct ordering
-            cpString = appendPath(System.getProperty("env.class.path"), cpString);
-            cpString = appendPath(System.getProperty("java.class.path"), cpString);
-            cpString = appendPath(tagletPath, cpString);
-            URLClassLoader appClassLoader = new URLClassLoader(pathToURLs(cpString));
-            customTagClass = appClassLoader.loadClass(classname);
+            ClassLoader tagClassLoader;
+            if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.TAGLET_PATH)) {
+                tagClassLoader = fileManager.getClassLoader(DocumentationTool.Location.TAGLET_PATH);
+            } else {
+                // do prepends to get correct ordering
+                cpString = appendPath(System.getProperty("env.class.path"), cpString);
+                cpString = appendPath(System.getProperty("java.class.path"), cpString);
+                cpString = appendPath(tagletPath, cpString);
+                tagClassLoader = new URLClassLoader(pathToURLs(cpString));
+            }
+
+            customTagClass = tagClassLoader.loadClass(classname);
             Method meth = customTagClass.getMethod("register",
                                                    new Class<?>[] {java.util.Map.class});
             Object[] list = customTags.values().toArray();
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFile.java	Thu Nov 15 23:07:24 2012 -0800
@@ -25,10 +25,14 @@
 
 package com.sun.tools.doclets.internal.toolkit.util;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 
@@ -36,10 +40,6 @@
 import javax.tools.StandardLocation;
 
 import com.sun.tools.doclets.internal.toolkit.Configuration;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
 
 /**
  * Abstraction for handling files, which may be specified directly
@@ -115,7 +115,8 @@
     /**
      * Open an output stream for the file.
      * The file must have been created with a location of
-     * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+     * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT}
+     * and a corresponding relative path.
      */
     public abstract OutputStream openOutputStream() throws IOException, UnsupportedEncodingException;
 
@@ -123,7 +124,7 @@
      * Open an writer for the file, using the encoding (if any) given in the
      * doclet configuration.
      * The file must have been created with a location of
-     * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+     * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
      */
     public abstract Writer openWriter() throws IOException, UnsupportedEncodingException;
 
@@ -251,7 +252,8 @@
 
     /**
      * Resolve a relative file against the given output location.
-     * @param locn Currently, only SOURCE_OUTPUT is supported.
+     * @param locn Currently, only
+     * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
      */
-    public abstract DocFile resolveAgainst(StandardLocation locn);
+    public abstract DocFile resolveAgainst(Location locn);
 }
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/DocFileFactory.java	Thu Nov 15 23:07:24 2012 -0800
@@ -69,6 +69,7 @@
                     throw new IllegalStateException(t);
                 }
             }
+            factories.put(configuration, f);
         }
         return f;
     }
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Extern.java	Thu Nov 15 23:07:24 2012 -0800
@@ -30,7 +30,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.tools.StandardLocation;
+import javax.tools.DocumentationTool;
 
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.internal.toolkit.*;
@@ -253,7 +253,7 @@
             throws Fault {
         DocFile file = pkgListPath.resolve(DocPaths.PACKAGE_LIST);
         if (! (file.isAbsolute() || linkoffline)){
-            file = file.resolveAgainst(StandardLocation.CLASS_OUTPUT);
+            file = file.resolveAgainst(DocumentationTool.Location.DOCUMENTATION_OUTPUT);
         }
         try {
             if (file.exists() && file.canRead()) {
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java	Thu Nov 15 23:07:24 2012 -0800
@@ -42,6 +42,7 @@
 import java.util.List;
 import java.util.Set;
 
+import javax.tools.DocumentationTool;
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
@@ -70,17 +71,17 @@
         fileManager = (PathFileManager) configuration.getFileManager();
 
         if (!configuration.destDirName.isEmpty()
-                || !fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
+                || !fileManager.hasLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT)) {
             try {
                 String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName;
                 Path dir = fileManager.getDefaultFileSystem().getPath(dirName);
-                fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(dir));
+                fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir));
             } catch (IOException e) {
                 throw new DocletAbortException();
             }
         }
 
-        destDir = fileManager.getLocation(StandardLocation.CLASS_OUTPUT).iterator().next();
+        destDir = fileManager.getLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next();
     }
 
     public DocFile createFileForDirectory(String file) {
@@ -92,7 +93,7 @@
     }
 
     public DocFile createFileForOutput(DocPath path) {
-        return new StandardDocFile(StandardLocation.CLASS_OUTPUT, path);
+        return new StandardDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
     }
 
     @Override
@@ -137,10 +138,10 @@
         /**
          * Open an output stream for the file.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             OutputStream out = getFileObjectForOutput(path).openOutputStream();
@@ -151,10 +152,10 @@
          * Open an writer for the file, using the encoding (if any) given in the
          * doclet configuration.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public Writer openWriter() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             OutputStream out = getFileObjectForOutput(path).openOutputStream();
@@ -262,10 +263,11 @@
 
         /**
          * Resolve a relative file against the given output location.
-         * @param locn Currently, only SOURCE_OUTPUT is supported.
+         * @param locn Currently, only
+         * {@link DocumentationTool.Location.DOCUMENTATION_OUTPUT} is supported.
          */
-        public DocFile resolveAgainst(StandardLocation locn) {
-            if (locn != StandardLocation.CLASS_OUTPUT)
+        public DocFile resolveAgainst(Location locn) {
+            if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalArgumentException();
             return new StandardDocFile(destDir.resolve(file));
         }
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/SimpleDocFileFactory.java	Thu Nov 15 23:07:24 2012 -0800
@@ -43,6 +43,7 @@
 import java.util.List;
 import java.util.Set;
 
+import javax.tools.DocumentationTool;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.StandardLocation;
 
@@ -74,7 +75,7 @@
     }
 
     public DocFile createFileForOutput(DocPath path) {
-        return new SimpleDocFile(StandardLocation.CLASS_OUTPUT, path);
+        return new SimpleDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
     }
 
     @Override
@@ -121,10 +122,10 @@
         /**
          * Open an output stream for the file.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             createDirectoryForFile(file);
@@ -135,10 +136,10 @@
          * Open an writer for the file, using the encoding (if any) given in the
          * doclet configuration.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public Writer openWriter() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             createDirectoryForFile(file);
@@ -243,10 +244,11 @@
 
         /**
          * Resolve a relative file against the given output location.
-         * @param locn Currently, only SOURCE_OUTPUT is supported.
+         * @param locn Currently, only
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
          */
-        public DocFile resolveAgainst(StandardLocation locn) {
-            if (locn != StandardLocation.CLASS_OUTPUT)
+        public DocFile resolveAgainst(Location locn) {
+            if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalArgumentException();
             return new SimpleDocFile(
                     new File(configuration.destDirName, file.getPath()));
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/StandardDocFileFactory.java	Thu Nov 15 23:07:24 2012 -0800
@@ -41,6 +41,7 @@
 import java.util.List;
 import java.util.Set;
 
+import javax.tools.DocumentationTool;
 import javax.tools.FileObject;
 import javax.tools.JavaFileManager.Location;
 import javax.tools.JavaFileObject;
@@ -62,24 +63,29 @@
  */
 class StandardDocFileFactory extends DocFileFactory {
     private final StandardJavaFileManager fileManager;
-    private final File destDir;
+    private File destDir;
 
     public StandardDocFileFactory(Configuration configuration) {
         super(configuration);
         fileManager = (StandardJavaFileManager) configuration.getFileManager();
+    }
 
-        if (!configuration.destDirName.isEmpty()
-                || !fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
-            try {
-                String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName;
-                File dir = new File(dirName);
-                fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(dir));
-            } catch (IOException e) {
-                throw new DocletAbortException();
+    private File getDestDir() {
+        if (destDir == null) {
+            if (!configuration.destDirName.isEmpty()
+                    || !fileManager.hasLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT)) {
+                try {
+                    String dirName = configuration.destDirName.isEmpty() ? "." : configuration.destDirName;
+                    File dir = new File(dirName);
+                    fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir));
+                } catch (IOException e) {
+                    throw new DocletAbortException();
+                }
             }
+
+            destDir = fileManager.getLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT).iterator().next();
         }
-
-        destDir = fileManager.getLocation(StandardLocation.CLASS_OUTPUT).iterator().next();
+        return destDir;
     }
 
     public DocFile createFileForDirectory(String file) {
@@ -91,7 +97,7 @@
     }
 
     public DocFile createFileForOutput(DocPath path) {
-        return new StandardDocFile(StandardLocation.CLASS_OUTPUT, path);
+        return new StandardDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
     }
 
     @Override
@@ -100,13 +106,13 @@
             throw new IllegalArgumentException();
 
         Set<DocFile> files = new LinkedHashSet<DocFile>();
-        if (fileManager.hasLocation(location)) {
-            for (File f: fileManager.getLocation(location)) {
-                if (f.isDirectory()) {
-                    f = new File(f, path.getPath());
-                    if (f.exists())
-                        files.add(new StandardDocFile(f));
-                }
+        Location l = fileManager.hasLocation(StandardLocation.SOURCE_PATH)
+                ? StandardLocation.SOURCE_PATH : StandardLocation.CLASS_PATH;
+        for (File f: fileManager.getLocation(l)) {
+            if (f.isDirectory()) {
+                f = new File(f, path.getPath());
+                if (f.exists())
+                    files.add(new StandardDocFile(f));
             }
         }
         return files;
@@ -129,8 +135,8 @@
         /** Create a StandardDocFile for a given location and relative path. */
         private StandardDocFile(Location location, DocPath path) {
             super(configuration, location, path);
-            Assert.check(location == StandardLocation.CLASS_OUTPUT);
-            this.file = newFile(destDir, path.getPath());
+            Assert.check(location == DocumentationTool.Location.DOCUMENTATION_OUTPUT);
+            this.file = newFile(getDestDir(), path.getPath());
         }
 
         /** Open an input stream for the file. */
@@ -142,10 +148,10 @@
         /**
          * Open an output stream for the file.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public OutputStream openOutputStream() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             OutputStream out = getFileObjectForOutput(path).openOutputStream();
@@ -156,10 +162,10 @@
          * Open an writer for the file, using the encoding (if any) given in the
          * doclet configuration.
          * The file must have been created with a location of
-         * {@link StandardLocation#CLASS_OUTPUT} and a corresponding relative path.
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} and a corresponding relative path.
          */
         public Writer openWriter() throws IOException, UnsupportedEncodingException {
-            if (location != StandardLocation.CLASS_OUTPUT)
+            if (location != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalStateException();
 
             OutputStream out = getFileObjectForOutput(path).openOutputStream();
@@ -263,12 +269,13 @@
 
         /**
          * Resolve a relative file against the given output location.
-         * @param locn Currently, only SOURCE_OUTPUT is supported.
+         * @param locn Currently, only
+         * {@link DocumentationTool.Location#DOCUMENTATION_OUTPUT} is supported.
          */
-        public DocFile resolveAgainst(StandardLocation locn) {
-            if (locn != StandardLocation.CLASS_OUTPUT)
+        public DocFile resolveAgainst(Location locn) {
+            if (locn != DocumentationTool.Location.DOCUMENTATION_OUTPUT)
                 throw new IllegalArgumentException();
-            return new StandardDocFile(newFile(destDir, file.getPath()));
+            return new StandardDocFile(newFile(getDestDir(), file.getPath()));
         }
 
         /** Return a string to identify the contents of this object,
--- a/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java	Thu Nov 15 23:07:24 2012 -0800
@@ -149,7 +149,7 @@
             return fo;
     }
 
-    <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
+    public <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
         if (isTrusted(dl))
             return dl;
         return new WrappedDiagnosticListener<T>(dl);
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Thu Nov 15 23:07:24 2012 -0800
@@ -74,7 +74,7 @@
     private List<JavaFileObject> fileObjects;
     private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
     private ListBuffer<Env<AttrContext>> genList;
-    private AtomicBoolean used = new AtomicBoolean();
+    private final AtomicBoolean used = new AtomicBoolean();
     private Iterable<? extends Processor> processors;
 
     private Main.Result result = null;
@@ -99,11 +99,11 @@
     }
 
     JavacTaskImpl(Main compilerMain,
-                Iterable<String> flags,
+                Iterable<String> args,
                 Context context,
                 Iterable<String> classes,
                 Iterable<? extends JavaFileObject> fileObjects) {
-        this(compilerMain, toArray(flags), toArray(classes), context, toList(fileObjects));
+        this(compilerMain, toArray(args), toArray(classes), context, toList(fileObjects));
     }
 
     static private String[] toArray(Iterable<String> iter) {
--- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java	Thu Nov 15 23:07:24 2012 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -253,7 +253,8 @@
             for (File f: files)
                 pl.add(f.toPath());
         }
-        pathsForLocation.put(locn, pl);
+        if (!pl.isEmpty())
+            pathsForLocation.put(locn, pl);
     }
 
     private void lazyInitSearchPaths() {
@@ -513,7 +514,8 @@
     }
 
     private static String getRelativePath(String packageName, String relativeName) {
-        return packageName.replace(".", "/") + relativeName;
+        return packageName.isEmpty()
+                ? relativeName : packageName.replace(".", "/") + "/" + relativeName;
     }
 
     private static String getBaseName(String relativePath) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Nov 15 23:07:24 2012 -0800
@@ -31,6 +31,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.api.DiagnosticFormatter;
@@ -43,9 +44,8 @@
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Type.CapturedType;
+import com.sun.tools.javac.file.BaseFileObject;
 import com.sun.tools.javac.tree.JCTree.*;
-
-import com.sun.tools.javac.file.BaseFileObject;
 import com.sun.tools.javac.tree.Pretty;
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
 
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Thu Nov 15 23:07:24 2012 -0800
@@ -32,7 +32,12 @@
 import java.net.URL;
 import java.net.URLClassLoader;
 
+import javax.tools.DocumentationTool;
+import javax.tools.JavaFileManager;
+
 import com.sun.javadoc.*;
+import com.sun.tools.javac.file.Locations;
+import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.List;
 import static com.sun.javadoc.LanguageVersion.*;
 
@@ -57,6 +62,12 @@
 
     private final Messager messager;
 
+    /**
+     * In API mode, exceptions thrown while calling the doclet are
+     * propagated using ClientCodeException.
+     */
+    private final boolean apiMode;
+
     private static class DocletInvokeException extends Exception {
         private static final long serialVersionUID = 0;
     }
@@ -71,24 +82,38 @@
         }
     }
 
-    public DocletInvoker(Messager messager,
+    public DocletInvoker(Messager messager, Class<?> docletClass, boolean apiMode) {
+        this.messager = messager;
+        this.docletClass = docletClass;
+        docletClassName = docletClass.getName();
+        appClassLoader = null;
+        this.apiMode = apiMode;
+    }
+
+    public DocletInvoker(Messager messager, JavaFileManager fileManager,
                          String docletClassName, String docletPath,
-                         ClassLoader docletParentClassLoader) {
+                         ClassLoader docletParentClassLoader,
+                         boolean apiMode) {
         this.messager = messager;
         this.docletClassName = docletClassName;
+        this.apiMode = apiMode;
 
-        // construct class loader
-        String cpString = null;   // make sure env.class.path defaults to dot
+        if (fileManager != null && fileManager.hasLocation(DocumentationTool.Location.DOCLET_PATH)) {
+            appClassLoader = fileManager.getClassLoader(DocumentationTool.Location.DOCLET_PATH);
+        } else {
+            // construct class loader
+            String cpString = null;   // make sure env.class.path defaults to dot
 
-        // do prepends to get correct ordering
-        cpString = appendPath(System.getProperty("env.class.path"), cpString);
-        cpString = appendPath(System.getProperty("java.class.path"), cpString);
-        cpString = appendPath(docletPath, cpString);
-        URL[] urls = com.sun.tools.javac.file.Locations.pathToURLs(cpString);
-        if (docletParentClassLoader == null)
-            appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
-        else
-            appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
+            // do prepends to get correct ordering
+            cpString = appendPath(System.getProperty("env.class.path"), cpString);
+            cpString = appendPath(System.getProperty("java.class.path"), cpString);
+            cpString = appendPath(docletPath, cpString);
+            URL[] urls = Locations.pathToURLs(cpString);
+            if (docletParentClassLoader == null)
+                appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
+            else
+                appClassLoader = new URLClassLoader(urls, docletParentClassLoader);
+        }
 
         // attempt to find doclet
         Class<?> dc = null;
@@ -280,7 +305,8 @@
             ClassLoader savedCCL =
                 Thread.currentThread().getContextClassLoader();
             try {
-                Thread.currentThread().setContextClassLoader(appClassLoader);
+                if (appClassLoader != null) // will be null if doclet class provided via API
+                    Thread.currentThread().setContextClassLoader(appClassLoader);
                 return meth.invoke(null , params);
             } catch (IllegalArgumentException exc) {
                 messager.error(Messager.NOPOS, "main.internal_error_exception_thrown",
@@ -296,10 +322,12 @@
                 throw new DocletInvokeException();
             } catch (InvocationTargetException exc) {
                 Throwable err = exc.getTargetException();
+                if (apiMode)
+                    throw new ClientCodeException(err);
                 if (err instanceof java.lang.OutOfMemoryError) {
                     messager.error(Messager.NOPOS, "main.out.of.memory");
                 } else {
-                messager.error(Messager.NOPOS, "main.exception_thrown",
+                    messager.error(Messager.NOPOS, "main.exception_thrown",
                                docletClassName, methodName, exc.toString());
                     exc.getTargetException().printStackTrace();
                 }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java	Thu Nov 15 23:07:24 2012 -0800
@@ -119,6 +119,7 @@
                                       ModifierFilter filter,
                                       List<String> javaNames,
                                       List<String[]> options,
+                                      Iterable<? extends JavaFileObject> fileObjects,
                                       boolean breakiterator,
                                       List<String> subPackages,
                                       List<String> excludedPackages,
@@ -140,10 +141,11 @@
         ListBuffer<JCCompilationUnit> packTrees = new ListBuffer<JCCompilationUnit>();
 
         try {
-            StandardJavaFileManager fm = (StandardJavaFileManager) docenv.fileManager;
+            StandardJavaFileManager fm = docenv.fileManager instanceof StandardJavaFileManager
+                    ? (StandardJavaFileManager) docenv.fileManager : null;
             for (List<String> it = javaNames; it.nonEmpty(); it = it.tail) {
                 String name = it.head;
-                if (!docClasses && name.endsWith(".java") && new File(name).exists()) {
+                if (!docClasses && fm != null && name.endsWith(".java") && new File(name).exists()) {
                     JavaFileObject fo = fm.getJavaFileObjects(name).iterator().next();
                     docenv.notice("main.Loading_source_file", name);
                     JCCompilationUnit tree = parse(fo);
@@ -151,11 +153,19 @@
                 } else if (isValidPackageName(name)) {
                     names = names.append(name);
                 } else if (name.endsWith(".java")) {
+                    if (fm == null)
+                        throw new IllegalArgumentException();
+                    else
                         docenv.error(null, "main.file_not_found", name);
                 } else {
                     docenv.error(null, "main.illegal_package_name", name);
                 }
             }
+            for (JavaFileObject fo: fileObjects) {
+                docenv.notice("main.Loading_source_file", fo.getName());
+                JCCompilationUnit tree = parse(fo);
+                classTrees.append(tree);
+            }
 
             if (!docClasses) {
                 // Recursively search given subpackages.  If any packages
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java	Thu Nov 15 23:07:24 2012 -0800
@@ -33,6 +33,7 @@
 import com.sun.javadoc.*;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 import com.sun.tools.javac.util.JavacMessages;
 import com.sun.tools.javac.util.Log;
 
@@ -174,6 +175,11 @@
      * @param msg message to print
      */
     public void printError(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.ERROR, pos, msg);
+            return;
+        }
+
         if (nerrors < MaxErrors) {
             String prefix = (pos == null) ? programName : pos.toString();
             errWriter.println(prefix + ": " + getText("javadoc.error") + " - " + msg);
@@ -201,6 +207,11 @@
      * @param msg message to print
      */
     public void printWarning(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.WARNING, pos, msg);
+            return;
+        }
+
         if (nwarnings < MaxWarnings) {
             String prefix = (pos == null) ? programName : pos.toString();
             warnWriter.println(prefix +  ": " + getText("javadoc.warning") +" - " + msg);
@@ -227,6 +238,11 @@
      * @param msg message to print
      */
     public void printNotice(SourcePosition pos, String msg) {
+        if (diagListener != null) {
+            report(DiagnosticType.NOTE, pos, msg);
+            return;
+        }
+
         if (pos == null)
             noticeWriter.println(msg);
         else
@@ -295,4 +311,22 @@
     public void exit() {
         throw new ExitJavadoc();
     }
+
+    private void report(DiagnosticType type, SourcePosition pos, String msg) {
+        switch (type) {
+            case ERROR:
+            case WARNING:
+                Object prefix = (pos == null) ? programName : pos;
+                report(javadocDiags.create(type, null, null, "msg", prefix, msg));
+                break;
+
+            case NOTE:
+                String key = (pos == null) ? "msg" : "pos.msg";
+                report(javadocDiags.create(type, null, null, key, pos, msg));
+                break;
+
+            default:
+                throw new IllegalArgumentException(type.toString());
+        }
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Start.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/Start.java	Thu Nov 15 23:07:24 2012 -0800
@@ -29,9 +29,16 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
 
 import com.sun.javadoc.*;
 import com.sun.tools.javac.main.CommandLine;
+import com.sun.tools.javac.util.ClientCodeException;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -70,6 +77,12 @@
 
     private DocletInvoker docletInvoker;
 
+    /**
+     * In API mode, exceptions thrown while calling the doclet are
+     * propagated using ClientCodeException.
+     */
+    private boolean apiMode;
+
     Start(String programName,
           PrintWriter errWriter,
           PrintWriter warnWriter,
@@ -121,6 +134,7 @@
     public Start(Context context) {
         context.getClass(); // null check
         this.context = context;
+        apiMode = true;
         defaultDocletClassName = standardDocletClassName;
         docletParentClassLoader = null;
 
@@ -184,15 +198,29 @@
      * Main program - external wrapper
      */
     int begin(String... argv) {
+        boolean ok = begin(null, argv, Collections.<JavaFileObject> emptySet());
+        return ok ? 0 : 1;
+    }
+
+    public boolean begin(Class<?> docletClass, Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
+        Collection<String> opts = new ArrayList<String>();
+        for (String opt: options) opts.add(opt);
+        return begin(docletClass, opts.toArray(new String[opts.size()]), fileObjects);
+    }
+
+    private boolean begin(Class<?> docletClass, String[] options, Iterable<? extends JavaFileObject> fileObjects) {
         boolean failed = false;
 
         try {
-            failed = !parseAndExecute(argv);
+            failed = !parseAndExecute(docletClass, options, fileObjects);
         } catch (Messager.ExitJavadoc exc) {
             // ignore, we just exit this way
         } catch (OutOfMemoryError ee) {
             messager.error(Messager.NOPOS, "main.out.of.memory");
             failed = true;
+        } catch (ClientCodeException e) {
+            // simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl
+            throw e;
         } catch (Error ee) {
             ee.printStackTrace(System.err);
             messager.error(Messager.NOPOS, "main.fatal.error");
@@ -207,13 +235,16 @@
         }
         failed |= messager.nerrors() > 0;
         failed |= rejectWarnings && messager.nwarnings() > 0;
-        return failed ? 1 : 0;
+        return !failed;
     }
 
     /**
      * Main program - internal
      */
-    private boolean parseAndExecute(String... argv) throws IOException {
+    private boolean parseAndExecute(
+            Class<?> docletClass,
+            String[] argv,
+            Iterable<? extends JavaFileObject> fileObjects) throws IOException {
         long tm = System.currentTimeMillis();
 
         ListBuffer<String> javaNames = new ListBuffer<String>();
@@ -229,7 +260,9 @@
             exit();
         }
 
-        setDocletInvoker(argv);
+
+        JavaFileManager fileManager = context.get(JavaFileManager.class);
+        setDocletInvoker(docletClass, fileManager, argv);
 
         compOpts = Options.instance(context);
 
@@ -287,7 +320,7 @@
         }
         compOpts.notifyListeners();
 
-        if (javaNames.isEmpty() && subPackages.isEmpty()) {
+        if (javaNames.isEmpty() && subPackages.isEmpty() && isEmpty(fileObjects)) {
             usageError("main.No_packages_or_classes_specified");
         }
 
@@ -310,6 +343,7 @@
                 showAccess,
                 javaNames.toList(),
                 options.toList(),
+                fileObjects,
                 breakiterator,
                 subPackages.toList(),
                 excludedPackages.toList(),
@@ -334,21 +368,43 @@
         return ok;
     }
 
-    private void setDocletInvoker(String[] argv) {
+    private <T> boolean isEmpty(Iterable<T> iter) {
+        return !iter.iterator().hasNext();
+    }
+
+    /**
+     * Init the doclet invoker.
+     * The doclet class may be given explicitly, or via the -doclet option in
+     * argv.
+     * If the doclet class is not given explicitly, it will be loaded from
+     * the file manager's DOCLET_PATH location, if available, or via the
+     * -doclet path option in argv.
+     * @param docletClass The doclet class. May be null.
+     * @param fileManager The file manager used to get the class loader to load
+     * the doclet class if required. May be null.
+     * @param argv Args containing -doclet and -docletpath, in case they are required.
+     */
+    private void setDocletInvoker(Class<?> docletClass, JavaFileManager fileManager, String[] argv) {
+        if (docletClass != null) {
+            docletInvoker = new DocletInvoker(messager, docletClass, apiMode);
+            // TODO, check no -doclet, -docletpath
+            return;
+        }
+
         String docletClassName = null;
         String docletPath = null;
 
         // Parse doclet specifying arguments
         for (int i = 0 ; i < argv.length ; i++) {
             String arg = argv[i];
-            if (arg.equals("-doclet")) {
+            if (arg.equals(ToolOption.DOCLET.opt)) {
                 oneArg(argv, i++);
                 if (docletClassName != null) {
                     usageError("main.more_than_one_doclet_specified_0_and_1",
                                docletClassName, argv[i]);
                 }
                 docletClassName = argv[i];
-            } else if (arg.equals("-docletpath")) {
+            } else if (arg.equals(ToolOption.DOCLETPATH.opt)) {
                 oneArg(argv, i++);
                 if (docletPath == null) {
                     docletPath = argv[i];
@@ -363,9 +419,10 @@
         }
 
         // attempt to find doclet
-        docletInvoker = new DocletInvoker(messager,
-                                          docletClassName, docletPath,
-                                          docletParentClassLoader);
+        docletInvoker = new DocletInvoker(messager, fileManager,
+                docletClassName, docletPath,
+                docletParentClassLoader,
+                apiMode);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 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.javadoc.api;
+
+import com.sun.tools.javac.util.ClientCodeException;
+import java.util.Locale;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javadoc.Start;
+import java.util.Collections;
+
+/**
+ * Provides access to functionality specific to the JDK documentation tool,
+ * javadoc.
+ *
+ * <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 JavadocTaskImpl implements DocumentationTask {
+    private final AtomicBoolean used = new AtomicBoolean();
+
+    private final Context context;
+    private Class<?> docletClass;
+    private Iterable<String> options;
+    private Iterable<? extends JavaFileObject> fileObjects;
+    private Locale locale;
+
+    public JavadocTaskImpl(Context context, Class<?> docletClass,
+            Iterable<String> options, Iterable<? extends JavaFileObject> fileObjects) {
+        this.context = context;
+        this.docletClass = docletClass;
+
+        this.options = (options == null) ? Collections.<String>emptySet()
+                : nullCheck(options);
+        this.fileObjects = (fileObjects == null) ? Collections.<JavaFileObject>emptySet()
+                : nullCheck(fileObjects);
+        setLocale(Locale.getDefault());
+    }
+
+    public void setLocale(Locale locale) {
+        if (used.get())
+            throw new IllegalStateException();
+        this.locale = locale;
+    }
+
+    public Boolean call() {
+        if (!used.getAndSet(true)) {
+            initContext();
+            Start jdoc = new Start(context);
+            try {
+                return jdoc.begin(docletClass, options, fileObjects);
+            } catch (ClientCodeException e) {
+                throw new RuntimeException(e.getCause());
+            }
+        } else {
+            throw new IllegalStateException("multiple calls to method 'call'");
+        }
+    }
+
+    private void initContext() {
+        //initialize compiler's default locale
+        context.put(Locale.class, locale);
+    }
+
+    private static <T> Iterable<T> nullCheck(Iterable<T> items) {
+        for (T item: items) {
+            if (item == null)
+                throw new NullPointerException();
+        }
+        return items;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/api/JavadocTool.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 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.javadoc.api;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.lang.model.SourceVersion;
+import javax.tools.DiagnosticListener;
+import javax.tools.DocumentationTool;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.tools.javac.api.ClientCodeWrapper;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.ClientCodeException;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javadoc.ToolOption;
+
+/**
+ * Provides access to functionality specific to the JDK documentation tool,
+ * javadoc.
+ *
+ * <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 JavadocTool implements DocumentationTool {
+    @Override
+    public DocumentationTask getTask(
+            Writer out,
+            JavaFileManager fileManager,
+            DiagnosticListener<? super JavaFileObject> diagnosticListener,
+            Class<?> docletClass,
+            Iterable<String> options,
+            Iterable<? extends JavaFileObject> compilationUnits) {
+        Context context = new Context();
+        return getTask(out, fileManager, diagnosticListener,
+                docletClass, options, compilationUnits, context);
+    }
+
+    public DocumentationTask getTask(
+            Writer out,
+            JavaFileManager fileManager,
+            DiagnosticListener<? super JavaFileObject> diagnosticListener,
+            Class<?> docletClass,
+            Iterable<String> options,
+            Iterable<? extends JavaFileObject> compilationUnits,
+            Context context) {
+        try {
+            ClientCodeWrapper ccw = ClientCodeWrapper.instance(context);
+
+            if (options != null) {
+                for (String option : options)
+                    option.getClass(); // null check
+            }
+
+            if (compilationUnits != null) {
+                compilationUnits = ccw.wrapJavaFileObjects(compilationUnits); // implicit null check
+                for (JavaFileObject cu : compilationUnits) {
+                    if (cu.getKind() != JavaFileObject.Kind.SOURCE) {
+                        final String kindMsg = "All compilation units must be of SOURCE kind";
+                        throw new IllegalArgumentException(kindMsg);
+                    }
+                }
+            }
+
+            if (diagnosticListener != null)
+                context.put(DiagnosticListener.class, ccw.wrap(diagnosticListener));
+
+            if (out == null)
+                context.put(Log.outKey, new PrintWriter(System.err, true));
+            else if (out instanceof PrintWriter)
+                context.put(Log.outKey, ((PrintWriter) out));
+            else
+                context.put(Log.outKey, new PrintWriter(out, true));
+
+            if (fileManager == null)
+                fileManager = getStandardFileManager(diagnosticListener, null, null);
+            fileManager = ccw.wrap(fileManager);
+            context.put(JavaFileManager.class, fileManager);
+
+            return new JavadocTaskImpl(context, docletClass, options, compilationUnits);
+        } catch (ClientCodeException ex) {
+            throw new RuntimeException(ex.getCause());
+        }
+    }
+
+    // TODO: used shared static method in JavacFileManager
+    @Override
+    public StandardJavaFileManager getStandardFileManager(
+            DiagnosticListener<? super JavaFileObject> diagnosticListener,
+            Locale locale,
+            Charset charset) {
+        Context context = new Context();
+        context.put(Locale.class, locale);
+        if (diagnosticListener != null)
+            context.put(DiagnosticListener.class, diagnosticListener);
+        PrintWriter pw = (charset == null)
+                ? new PrintWriter(System.err, true)
+                : new PrintWriter(new OutputStreamWriter(System.err, charset), true);
+        context.put(Log.outKey, pw);
+        return new JavacFileManager(context, true, charset);
+    }
+
+    @Override
+    public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) {
+        PrintWriter err_pw = new PrintWriter(err, true);
+        PrintWriter out_pw = new PrintWriter(out);
+        try {
+            String standardDocletName = "com.sun.tools.doclets.standard.Standard";
+            return com.sun.tools.javadoc.Main.execute(
+                    "javadoc", err_pw, err_pw, out_pw, standardDocletName, arguments);
+        } finally {
+            err_pw.flush();
+            out_pw.flush();
+        }
+    }
+
+    @Override
+    public Set<SourceVersion> getSourceVersions() {
+        return Collections.unmodifiableSet(
+                EnumSet.range(SourceVersion.RELEASE_3, SourceVersion.latest()));
+    }
+
+    @Override
+    public int isSupportedOption(String option) {
+        if (option == null)
+            throw new NullPointerException();
+        for (ToolOption o: ToolOption.values()) {
+            if (o.opt.equals(option))
+                return o.hasArg ? 1 : 0;
+        }
+        return -1;
+    }
+
+}
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties	Thu Nov 15 23:07:24 2012 -0800
@@ -108,3 +108,8 @@
 javadoc.class_not_found=Class {0} not found.
 javadoc.error=error
 javadoc.warning=warning
+
+javadoc.error.msg={0}: error - {1}
+javadoc.warning.msg={0}: warning - {1}
+javadoc.note.msg = {1}
+javadoc.note.pos.msg= {0}: {1}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/javax/tools/DocumentationTool.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,183 @@
+/*
+ * 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 javax.tools;
+
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Locale;
+import java.util.concurrent.Callable;
+
+/**
+ * Interface to invoke Java&trade; programming language documentation tools from
+ * programs.
+ */
+public interface DocumentationTool extends Tool, OptionChecker {
+    /**
+     * Creates a future for a documentation task with the given
+     * components and arguments.  The task might not have
+     * completed as described in the DocumentationTask interface.
+     *
+     * <p>If a file manager is provided, it must be able to handle all
+     * locations defined in {@link DocumentationTool.Location},
+     * as well as
+     * {@link StandardLocation#SOURCE_PATH},
+     * {@link StandardLocation#CLASS_PATH}, and
+     * {@link StandardLocation#PLATFORM_CLASS_PATH}.
+     *
+     * @param out a Writer for additional output from the tool;
+     * use {@code System.err} if {@code null}
+     *
+     * @param fileManager a file manager; if {@code null} use the
+     * tool's standard filemanager
+     *
+     * @param diagnosticListener a diagnostic listener; if {@code null}
+     * use the tool's default method for reporting diagnostics
+     *
+     * @param docletClass a class providing the necessary methods required
+     * of a doclet
+     *
+     * @param options documentation tool options and doclet options,
+     * {@code null} means no options
+     *
+     * @param compilationUnits the compilation units to compile, {@code
+     * null} means no compilation units
+     *
+     * @return an object representing the compilation
+     *
+     * @throws RuntimeException if an unrecoverable error
+     * occurred in a user supplied component.  The
+     * {@linkplain Throwable#getCause() cause} will be the error in
+     * user code.
+     *
+     * @throws IllegalArgumentException if any of the given
+     * compilation units are of other kind than
+     * {@linkplain JavaFileObject.Kind#SOURCE source}
+     */
+    DocumentationTask getTask(Writer out,
+                            JavaFileManager fileManager,
+                            DiagnosticListener<? super JavaFileObject> diagnosticListener,
+                            Class<?> docletClass,
+                            Iterable<String> options,
+                            Iterable<? extends JavaFileObject> compilationUnits);
+
+    /**
+     * Gets a new instance of the standard file manager implementation
+     * for this tool.  The file manager will use the given diagnostic
+     * listener for producing any non-fatal diagnostics.  Fatal errors
+     * will be signaled with the appropriate exceptions.
+     *
+     * <p>The standard file manager will be automatically reopened if
+     * it is accessed after calls to {@code flush} or {@code close}.
+     * The standard file manager must be usable with other tools.
+     *
+     * @param diagnosticListener a diagnostic listener for non-fatal
+     * diagnostics; if {@code null} use the compiler's default method
+     * for reporting diagnostics
+     *
+     * @param locale the locale to apply when formatting diagnostics;
+     * {@code null} means the {@linkplain Locale#getDefault() default locale}.
+     *
+     * @param charset the character set used for decoding bytes; if
+     * {@code null} use the platform default
+     *
+     * @return the standard file manager
+     */
+    StandardJavaFileManager getStandardFileManager(
+        DiagnosticListener<? super JavaFileObject> diagnosticListener,
+        Locale locale,
+        Charset charset);
+
+    /**
+     * Interface representing a future for a documentation task.  The
+     * task has not yet started.  To start the task, call
+     * the {@linkplain #call call} method.
+     *
+     * <p>Before calling the call method, additional aspects of the
+     * task can be configured, for example, by calling the
+     * {@linkplain #setLocale setLocale} method.
+     */
+    interface DocumentationTask extends Callable<Boolean> {
+        /**
+         * Set the locale to be applied when formatting diagnostics and
+         * other localized data.
+         *
+         * @param locale the locale to apply; {@code null} means apply no
+         * locale
+         * @throws IllegalStateException if the task has started
+         */
+        void setLocale(Locale locale);
+
+        /**
+         * Performs this documentation task.  The task may only
+         * be performed once.  Subsequent calls to this method throw
+         * IllegalStateException.
+         *
+         * @return true if and only all the files were processed without errors;
+         * false otherwise
+         *
+         * @throws RuntimeException if an unrecoverable error occurred
+         * in a user-supplied component.  The
+         * {@linkplain Throwable#getCause() cause} will be the error
+         * in user code.
+         *
+         * @throws IllegalStateException if called more than once
+         */
+        Boolean call();
+    }
+
+    /**
+     * Locations specific to {@link DocumentationTool}.
+     *
+     * @see StandardLocation
+     */
+    enum Location implements JavaFileManager.Location {
+        /**
+         * Location of new documentation files.
+         */
+        DOCUMENTATION_OUTPUT,
+
+        /**
+         * Location to search for doclets.
+         */
+        DOCLET_PATH,
+
+        /**
+         * Location to search for taglets.
+         */
+        TAGLET_PATH;
+
+        public String getName() { return name(); }
+
+        public boolean isOutputLocation() {
+            switch (this) {
+                case DOCUMENTATION_OUTPUT:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+    }
+
+}
--- a/langtools/src/share/classes/javax/tools/JavaCompiler.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/javax/tools/JavaCompiler.java	Thu Nov 15 23:07:24 2012 -0800
@@ -266,7 +266,7 @@
      * Gets a new instance of the standard file manager implementation
      * for this tool.  The file manager will use the given diagnostic
      * listener for producing any non-fatal diagnostics.  Fatal errors
-     * will be signalled with the appropriate exceptions.
+     * will be signaled with the appropriate exceptions.
      *
      * <p>The standard file manager will be automatically reopened if
      * it is accessed after calls to {@code flush} or {@code close}.
--- a/langtools/src/share/classes/javax/tools/ToolProvider.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/src/share/classes/javax/tools/ToolProvider.java	Thu Nov 15 23:07:24 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
@@ -102,6 +102,19 @@
         return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName);
     }
 
+    private static final String defaultDocumentationToolName
+        = "com.sun.tools.javadoc.api.JavadocTool";
+
+    /**
+     * Gets the Java&trade; programming language documentation tool provided
+     * with this platform.
+     * @return the documentation tool provided with this platform or
+     * {@code null} if no documentation tool is provided
+     */
+    public static DocumentationTool getSystemDocumentationTool() {
+        return instance().getSystemTool(DocumentationTool.class, defaultDocumentationToolName);
+    }
+
     /**
      * Returns the class loader for tools provided with this platform.
      * This does not include user-installed tools.  Use the
--- a/langtools/test/tools/javadoc/CheckResourceKeys.java	Thu Nov 15 19:54:20 2012 -0800
+++ b/langtools/test/tools/javadoc/CheckResourceKeys.java	Thu Nov 15 23:07:24 2012 -0800
@@ -167,6 +167,13 @@
                 results.add("doclet." + s.toLowerCase());
         }
 
+        // special handling for code strings synthesized in
+        // com.sun.tools.javadoc.Messager
+        results.add("javadoc.error.msg");
+        results.add("javadoc.note.msg");
+        results.add("javadoc.note.pos.msg");
+        results.add("javadoc.warning.msg");
+
         return results;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/APITest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+
+
+/*
+ * Superclass with utility methods for API tests.
+ */
+class APITest {
+    protected APITest() { }
+
+    /** Marker annotation for test cases. */
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Test { }
+
+    /** Invoke all methods annotated with @Test. */
+    protected void run() throws Exception {
+        for (Method m: getClass().getDeclaredMethods()) {
+            Annotation a = m.getAnnotation(Test.class);
+            if (a != null) {
+                testCount++;
+                testName = m.getName();
+                System.err.println("test: " + testName);
+                try {
+                    m.invoke(this, new Object[] { });
+                } catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
+                    throw (cause instanceof Exception) ? ((Exception) cause) : e;
+                }
+                System.err.println();
+            }
+        }
+
+        if (testCount == 0)
+            error("no tests found");
+
+        StringBuilder summary = new StringBuilder();
+        if (testCount != 1)
+            summary.append(testCount).append(" tests");
+        if (errorCount > 0) {
+            if (summary.length() > 0) summary.append(", ");
+            summary.append(errorCount).append(" errors");
+        }
+        System.err.println(summary);
+        if (errorCount > 0)
+            throw new Exception(errorCount + " errors found");
+    }
+
+    /**
+     * Create a directory in which to store generated doc files.
+     * Avoid using the default (current) directory, so that we can
+     * be sure that javadoc is writing in the intended location,
+     * not a default location.
+     */
+    protected File getOutDir() {
+        File dir = new File(testName);
+        dir.mkdirs();
+        return dir;
+    }
+
+    /**
+     * Create a directory in which to store generated doc files.
+     * Avoid using the default (current) directory, so that we can
+     * be sure that javadoc is writing in the intended location,
+     * not a default location.
+     */
+    protected File getOutDir(String path) {
+        File dir = new File(testName, path);
+        dir.mkdirs();
+        return dir;
+    }
+
+    protected JavaFileObject createSimpleJavaFileObject() {
+        return createSimpleJavaFileObject("pkg/C", "package pkg; public class C { }");
+    }
+
+    protected JavaFileObject createSimpleJavaFileObject(final String binaryName, final String content) {
+        return new SimpleJavaFileObject(
+                URI.create("myfo:///" + binaryName + ".java"), JavaFileObject.Kind.SOURCE) {
+            @Override
+            public CharSequence getCharContent(boolean ignoreEncoding) {
+                return content;
+            }
+        };
+    }
+
+    protected void checkFiles(File dir, Set<String> expectFiles) {
+        Set<File> files = new HashSet<File>();
+        listFiles(dir, files);
+        Set<String> foundFiles = new HashSet<String>();
+        URI dirURI = dir.toURI();
+        for (File f: files)
+            foundFiles.add(dirURI.relativize(f.toURI()).getPath());
+        checkFiles(foundFiles, expectFiles, dir);
+    }
+
+    protected void checkFiles(Path dir, Set<String> expectFiles) throws IOException {
+        Set<Path> files = new HashSet<Path>();
+        listFiles(dir, files);
+        Set<String> foundFiles = new HashSet<String>();
+        for (Path f: files) {
+            foundFiles.add(dir.relativize(f).toString().replace(f.getFileSystem().getSeparator(), "/"));
+        }
+        checkFiles(foundFiles, expectFiles, dir);
+    }
+
+    private void checkFiles(Set<String> foundFiles, Set<String> expectFiles, Object where) {
+        if (!foundFiles.equals(expectFiles)) {
+            Set<String> missing = new TreeSet<String>(expectFiles);
+            missing.removeAll(foundFiles);
+            if (!missing.isEmpty())
+                error("the following files were not found in " + where + ": " + missing);
+            Set<String> unexpected = new TreeSet<String>(foundFiles);
+            unexpected.removeAll(expectFiles);
+            if (!unexpected.isEmpty())
+                error("the following unexpected files were found in " + where + ": " + unexpected);
+        }
+    }
+
+    protected void listFiles(File dir, Set<File> files) {
+        for (File f: dir.listFiles()) {
+            if (f.isDirectory())
+                listFiles(f, files);
+            else if (f.isFile())
+                files.add(f);
+        }
+    }
+
+    private void listFiles(Path dir, Set<Path> files) throws IOException {
+        for (Path f: Files.newDirectoryStream(dir)) {
+            if (Files.isDirectory(f))
+                listFiles(f, files);
+            else if (Files.isRegularFile(f))
+                files.add(f);
+        }
+    }
+
+    protected void error(String msg) {
+        System.err.println("Error: " + msg);
+        errorCount++;
+    }
+
+    protected int testCount;
+    protected int errorCount;
+
+    protected String testName;
+
+    /**
+     * Standard files generated by processing a documented class pkg.C.
+     */
+    protected static Set<String> standardExpectFiles = new HashSet<String>(Arrays.asList(
+        "allclasses-frame.html",
+        "allclasses-noframe.html",
+        "constant-values.html",
+        "deprecated-list.html",
+        "help-doc.html",
+        "index-all.html",
+        "index.html",
+        "overview-tree.html",
+        "package-list",
+        "pkg/C.html",
+        "pkg/package-frame.html",
+        "pkg/package-summary.html",
+        "pkg/package-tree.html",
+        "resources/background.gif",
+        "resources/tab.gif",
+        "resources/titlebar_end.gif",
+        "resources/titlebar.gif",
+        "stylesheet.css"
+    ));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/DocletPathTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main DocletPathTest
+ */
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for locating a doclet via the file manager's DOCLET_PATH.
+ */
+public class DocletPathTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new DocletPathTest().run();
+    }
+
+    /**
+     * Verify that an alternate doclet can be specified, and located via
+     * the file manager's DOCLET_PATH.
+     */
+    @Test
+    public void testDocletPath() throws Exception {
+        JavaFileObject docletSrc =
+                createSimpleJavaFileObject("DocletOnDocletPath", docletSrcText);
+        File docletDir = getOutDir("classes");
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager cfm = compiler.getStandardFileManager(null, null, null);
+        cfm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(docletDir));
+        Iterable<? extends JavaFileObject> cfiles = Arrays.asList(docletSrc);
+        if (!compiler.getTask(null, cfm, null, null, null, cfiles).call())
+            throw new Exception("cannot compile doclet");
+
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir("api");
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        fm.setLocation(DocumentationTool.Location.DOCLET_PATH, Arrays.asList(docletDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        Iterable<String> options = Arrays.asList("-doclet", "DocletOnDocletPath");
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        DocumentationTask t = tool.getTask(pw, fm, null, null, options, files);
+        boolean ok = t.call();
+        String out = sw.toString();
+        System.err.println(">>" + out + "<<");
+        if (ok) {
+            if (out.contains(TEST_STRING)) {
+                System.err.println("doclet executed as expected");
+            } else {
+                error("test string not found in doclet output");
+            }
+        } else {
+            error("task failed");
+        }
+    }
+
+    private static final String TEST_STRING = "DocletOnDocletPath found and running";
+
+    private static final String docletSrcText =
+        "import com.sun.javadoc.*;\n" +
+        "public class DocletOnDocletPath {\n" +
+        "    public static boolean start(RootDoc doc) {\n" +
+        "        doc.printNotice(\"" + TEST_STRING + "\");\n" +
+        "        return true;\n" +
+        "    }\n" +
+        "    public static int optionLength(String option) { return 0; }\n" +
+        "    public static boolean validOptions(String options[][],\n" +
+        "            DocErrorReporter reporter) { return true; }\n" +
+        "    public static LanguageVersion languageVersion() {\n" +
+        "        return LanguageVersion.JAVA_1_1;\n" +
+        "    }\n" +
+        "}\n";
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetSourceVersionsTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetSourceVersionsTest
+ */
+
+import java.util.EnumSet;
+import java.util.Set;
+import javax.lang.model.SourceVersion;
+import javax.tools.DocumentationTool;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getSourceVersions method.
+ */
+public class GetSourceVersionsTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetSourceVersionsTest().run();
+    }
+
+    /**
+     * Verify getSourceVersions.
+     */
+    @Test
+    public void testRun() throws Exception {
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        Set<SourceVersion> found = tool.getSourceVersions();
+        Set<SourceVersion> expect = EnumSet.range(SourceVersion.RELEASE_3, SourceVersion.latest());
+        if (!expect.equals(found)) {
+            System.err.println("expect: " + expect);
+            System.err.println(" found: " + expect);
+            error("unexpected versions");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_DiagListenerTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_DiagListenerTest
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticCollector;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getTask  diagnosticListener  parameter.
+ */
+public class GetTask_DiagListenerTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_DiagListenerTest().run();
+    }
+
+    /**
+     * Verify that a diagnostic listener can be specified.
+     * Note that messages from the tool and doclet are imperfectly modeled
+     * because the DocErrorReporter API works in terms of localized strings
+     * and file:line positions. Therefore, messages reported via DocErrorReporter
+     * and simply wrapped and passed through.
+     */
+    @Test
+    public void testDiagListener() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject("pkg/C", "package pkg; public error { }");
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<JavaFileObject>();
+        DocumentationTask t = tool.getTask(null, fm, dc, null, null, files);
+        if (t.call()) {
+            throw new Exception("task succeeded unexpectedly");
+        } else {
+            List<String> diagCodes = new ArrayList<String>();
+            for (Diagnostic d: dc.getDiagnostics()) {
+                System.err.println(d);
+                diagCodes.add(d.getCode());
+            }
+            List<String> expect = Arrays.asList(
+                    "javadoc.note.msg",         // Loading source file
+                    "compiler.err.expected3",   // class, interface, or enum expected
+                    "javadoc.note.msg");        // 1 error
+            if (!diagCodes.equals(expect))
+                throw new Exception("unexpected diagnostics occurred");
+            System.err.println("diagnostics received as expected");
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_DocletClassTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_DocletClassTest
+ */
+
+import com.sun.javadoc.DocErrorReporter;
+import com.sun.javadoc.LanguageVersion;
+import com.sun.javadoc.RootDoc;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Random;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getTask  docletClass  parameter.
+ */
+public class GetTask_DocletClassTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_DocletClassTest().run();
+    }
+
+    /**
+     * Verify that an alternate doclet can be specified.
+     *
+     * There is no standard interface or superclass for a doclet;
+     * the only requirement is that it provides static methods that
+     * can be invoked via reflection. So, for now, the doclet is
+     * specified as a class.
+     * Because we cannot create and use a unique instance of the class,
+     * we verify that the doclet has been called by having it record
+     * (in a static field!) the comment from the last time it was invoked,
+     * which is randomly generated each time the test is run.
+     */
+    @Test
+    public void testDoclet() throws Exception {
+        Random r = new Random();
+        int key = r.nextInt();
+        JavaFileObject srcFile = createSimpleJavaFileObject(
+                "pkg/C",
+                "package pkg; /** " + key + "*/ public class C { }");
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, TestDoclet.class, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            if (TestDoclet.lastCaller.equals(String.valueOf(key)))
+                System.err.println("found expected key: " + key);
+            else
+                error("Expected key not found");
+            checkFiles(outDir, Collections.<String>emptySet());
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    public static class TestDoclet {
+        static String lastCaller;
+        public static boolean start(RootDoc root) {
+            lastCaller = root.classNamed("pkg.C").commentText().trim();
+            return true;
+        }
+
+        public static int optionLength(String option) {
+            return 0;  // default is option unknown
+        }
+
+        public static boolean validOptions(String options[][],
+                DocErrorReporter reporter) {
+            return true;  // default is options are valid
+        }
+
+        public static LanguageVersion languageVersion() {
+            return LanguageVersion.JAVA_1_1;
+        }
+    }
+
+    /**
+     * Verify that exceptions from a doclet are thrown as expected.
+     */
+    @Test
+    public void testBadDoclet() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, BadDoclet.class, null, files);
+        try {
+            t.call();
+            error("call completed without exception");
+        } catch (RuntimeException e) {
+            Throwable c = e.getCause();
+            if (c.getClass() == UnexpectedError.class)
+                System.err.println("exception caught as expected: " + c);
+            else
+                throw e;
+        }
+    }
+
+    public static class UnexpectedError extends Error { }
+
+    public static class BadDoclet {
+        public static boolean start(RootDoc root) {
+            throw new UnexpectedError();
+        }
+
+        public static int optionLength(String option) {
+            return 0;  // default is option unknown
+        }
+
+        public static boolean validOptions(String options[][],
+                DocErrorReporter reporter) {
+            return true;  // default is options are valid
+        }
+
+        public static LanguageVersion languageVersion() {
+            return LanguageVersion.JAVA_1_1;
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_FileManagerTest
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.nio.JavacPathFileManager;
+import com.sun.tools.javac.nio.PathFileManager;
+import com.sun.tools.javac.util.Context;
+
+/**
+ * Tests for DocumentationTool.getTask  fileManager  parameter.
+ */
+public class GetTask_FileManagerTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_FileManagerTest().run();
+    }
+
+    /**
+     * Verify that an alternate file manager can be specified:
+     * in this case, a PathFileManager.
+     */
+    @Test
+    public void testFileManager() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        PathFileManager fm = new JavacPathFileManager(new Context(), false, null);
+        Path outDir = getOutDir().toPath();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            checkFiles(outDir, standardExpectFiles);
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    /**
+     * Verify that exceptions from a bad file manager are thrown as expected.
+     */
+    @Test
+    public void testBadFileManager() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        PathFileManager fm = new JavacPathFileManager(new Context(), false, null) {
+            @Override
+            public Iterable<JavaFileObject> list(Location location,
+                    String packageName,
+                    Set<Kind> kinds,
+                    boolean recurse)
+                    throws IOException {
+                throw new UnexpectedError();
+            }
+        };
+        Path outDir = getOutDir().toPath();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+        try {
+            t.call();
+            error("call completed without exception");
+        } catch (RuntimeException e) {
+            Throwable c = e.getCause();
+            if (c.getClass() == UnexpectedError.class)
+                System.err.println("exception caught as expected: " + c);
+            else
+                throw e;
+        }
+    }
+
+    public static class UnexpectedError extends Error { }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_FileObjectsTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_FileObjectsTest
+ */
+
+import java.io.File;
+import java.util.Arrays;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getTask  fileObjects  parameter.
+ */
+public class GetTask_FileObjectsTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_FileObjectsTest().run();
+    }
+
+    /**
+     * Verify that expected output files are written via the file manager,
+     * for a source file read from the file system with StandardJavaFileManager.
+     */
+    @Test
+    public void testStandardFileObject() throws Exception {
+        File testSrc = new File(System.getProperty("test.src"));
+        File srcFile = new File(testSrc, "pkg/C.java");
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            checkFiles(outDir, standardExpectFiles);
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    /**
+     * Verify that expected output files are written via the file manager,
+     * for an in-memory file object.
+     */
+    @Test
+    public void testMemoryFileObject() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            checkFiles(outDir, standardExpectFiles);
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    /**
+     * Verify bad file object is handled correctly.
+     */
+    @Test
+    public void testBadFileObject() throws Exception {
+        File testSrc = new File(System.getProperty("test.src"));
+        File srcFile = new File(testSrc, "pkg/C.class");  // unacceptable file kind
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(srcFile);
+        try {
+            DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+            error("getTask succeeded, no exception thrown");
+        } catch (IllegalArgumentException e) {
+            System.err.println("exception caught as expected: " + e);
+        }
+    }
+
+    /**
+     * Verify null is handled correctly.
+     */
+    @Test
+    public void testNull() throws Exception {
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList((JavaFileObject) null);
+        try {
+            DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+            error("getTask succeeded, no exception thrown");
+        } catch (NullPointerException e) {
+            System.err.println("exception caught as expected: " + e);
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_OptionsTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_OptionsTest
+ */
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getTask  options  parameter.
+ */
+public class GetTask_OptionsTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_OptionsTest().run();
+    }
+
+    /**
+     * Verify that expected output files are written for given options.
+     */
+    @Test
+    public void testNoIndex() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        Iterable<String> options = Arrays.asList("-noindex");
+        DocumentationTask t = tool.getTask(null, fm, null, null, options, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            Set<String> expectFiles = new TreeSet<String>(standardExpectFiles);
+            expectFiles.remove("index-all.html");
+            checkFiles(outDir, expectFiles);
+        } else {
+            error("task failed");
+        }
+    }
+
+    /**
+     * Verify null is handled correctly.
+     */
+    @Test
+    public void testNull() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<String> options = Arrays.asList((String) null);
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        try {
+            DocumentationTask t = tool.getTask(null, fm, null, null, options, files);
+            error("getTask succeeded, no exception thrown");
+        } catch (NullPointerException e) {
+            System.err.println("exception caught as expected: " + e);
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/GetTask_WriterTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main GetTask_WriterTest
+ */
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.getTask  writer  parameter.
+ */
+public class GetTask_WriterTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new GetTask_WriterTest().run();
+    }
+
+    /**
+     * Verify that a writer can be provided.
+     */
+    @Test
+    public void testWriter() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        DocumentationTask t = tool.getTask(pw, fm, null, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            checkFiles(outDir, standardExpectFiles);
+            String out = sw.toString();
+            System.err.println(">>" + out + "<<");
+            for (String f: standardExpectFiles) {
+                if (f.endsWith(".html") && !out.contains(f))
+                    throw new Exception("expected string not found: " + f);
+            }
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/IsSupportedOptionTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main IsSupportedOptionTest
+ */
+
+import javax.tools.DocumentationTool;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.usSupportedOption method.
+ */
+public class IsSupportedOptionTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new IsSupportedOptionTest().run();
+    }
+
+    /**
+     * Verify that isSupportedOption method can be invoked.
+     */
+    @Test
+    public void test() throws Exception {
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        check(tool, "-sourcepath", 1);
+        check(tool, "-verbose", 0);
+        check(tool, "-ZZZ", -1);
+
+        try {
+            check(tool, null, -1);
+            error("null was accepted without exception");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    private void check(DocumentationTool tool, String option, int numArgs) {
+        System.err.println("check " + option);
+        int n = tool.isSupportedOption(option);
+        if (n != numArgs)
+            error("unexpected result for option: " + option + ": " + n);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/JavadocTaskImplTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main JavadocTaskImplTest
+ */
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javadoc.Messager;
+import com.sun.tools.javadoc.api.JavadocTaskImpl;
+
+/**
+ *  Misc tests for JavacTaskImpl.
+ */
+public class JavadocTaskImplTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new JavadocTaskImplTest().run();
+    }
+
+    @Test
+    public void testRawCall() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+
+        @SuppressWarnings("rawtypes")
+        Callable t = tool.getTask(null, fm, null, null, null, files);
+
+        if (t.call() == Boolean.TRUE) {
+            System.err.println("task succeeded");
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    @Test
+    public void testDirectAccess1() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        Context c = new Context();
+        Messager.preRegister(c, "javadoc");
+        StandardJavaFileManager fm = new JavacFileManager(c, true, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        DocumentationTask t = new JavadocTaskImpl(c, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+
+    @Test
+    public void testDirectAccess2() throws Exception {
+        JavaFileObject srcFile = null; // error, provokes NPE
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        Context c = new Context();
+        Messager.preRegister(c, "javadoc");
+        StandardJavaFileManager fm = new JavacFileManager(c, true, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        try {
+            DocumentationTask t = new JavadocTaskImpl(c, null, null, files);;
+            error("getTask succeeded, no exception thrown");
+        } catch (NullPointerException e) {
+            System.err.println("exception caught as expected: " + e);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/RunTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main RunTest
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import javax.tools.DocumentationTool;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for DocumentationTool.run method.
+ */
+public class RunTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new RunTest().run();
+    }
+
+    /**
+     * Verify that run method can be invoked.
+     */
+    @Test
+    public void testRun() throws Exception {
+        File testSrc = new File(System.getProperty("test.src"));
+        File srcFile = new File(testSrc, "pkg/C.java");
+        File outDir = getOutDir();
+        String[] args = { "-d", outDir.getPath(), srcFile.getPath() };
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        int rc = tool.run(null, stdout, stderr, args);
+        System.err.println("stdout >>" + stdout.toString() + "<<");
+        System.err.println("stderr >>" + stderr.toString() + "<<");
+
+        if (rc == 0) {
+            System.err.println("call succeeded");
+            checkFiles(outDir, standardExpectFiles);
+            String out = stdout.toString();
+            for (String f: standardExpectFiles) {
+                if (f.endsWith(".html") && !out.contains(f))
+                    error("expected string not found: " + f);
+            }
+        } else {
+            error("call failed");
+        }
+    }
+
+    /**
+     * Verify that run method can be invoked.
+     */
+    @Test
+    public void testRun2() throws Exception {
+        File outDir = getOutDir();
+        String badfile = "badfile.java";
+        String[] args = { "-d", outDir.getPath(), badfile };
+
+        ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+        ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        int rc = tool.run(null, stdout, stderr, args);
+        System.err.println("stdout >>" + stdout.toString() + "<<");
+        System.err.println("stderr >>" + stderr.toString() + "<<");
+
+        if (rc == 0) {
+            error("call succeeded unexpectedly");
+        } else {
+            String err = stderr.toString();
+            if (err.contains(badfile))
+                System.err.println("call failed as expected");
+            else
+                error("expected diagnostic not found");
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/TagletPathTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main TagletPathTest
+ */
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for locating a doclet via the file manager's DOCLET_PATH.
+ */
+public class TagletPathTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new TagletPathTest().run();
+    }
+
+    /**
+     * Verify that a taglet can be specified, and located via
+     * the file manager's TAGLET_PATH.
+     */
+    @Test
+    public void testTagletPath() throws Exception {
+        File testSrc = new File(System.getProperty("test.src"));
+        File tagletSrcFile = new File(testSrc, "taglets/UnderlineTaglet.java");
+        File tagletDir = getOutDir("classes");
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager cfm = compiler.getStandardFileManager(null, null, null);
+        cfm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tagletDir));
+        Iterable<? extends JavaFileObject> cfiles = cfm.getJavaFileObjects(tagletSrcFile);
+        if (!compiler.getTask(null, cfm, null, null, null, cfiles).call())
+            throw new Exception("cannot compile taglet");
+
+        JavaFileObject srcFile = createSimpleJavaFileObject("pkg/C", testSrcText);
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir("api");
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        fm.setLocation(DocumentationTool.Location.TAGLET_PATH, Arrays.asList(tagletDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        Iterable<String> options = Arrays.asList("-taglet", "UnderlineTaglet");
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        DocumentationTask t = tool.getTask(pw, fm, null, null, options, files);
+        boolean ok = t.call();
+        String out = sw.toString();
+        System.err.println(">>" + out + "<<");
+        if (ok) {
+            File f = new File(outDir, "pkg/C.html");
+            List<String> doc = Files.readAllLines(f.toPath(), Charset.defaultCharset());
+            for (String line: doc) {
+                if (line.contains("<u>" + TEST_STRING + "</u>")) {
+                    System.err.println("taglet executed as expected");
+                    return;
+                }
+            }
+            error("expected text not found in output " + f);
+        } else {
+            error("task failed");
+        }
+    }
+
+    static final String TEST_STRING = "xyzzy";
+    static final String testSrcText =
+            "package pkg;\n" +
+            "/** {@underline " + TEST_STRING + "} */\n" +
+            "public class C { }";
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/Task_reuseTest.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 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 6493690
+ * @summary javadoc should have a javax.tools.Tool service provider
+ * @build APITest
+ * @run main Task_reuseTest
+ */
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Locale;
+import javax.tools.DocumentationTool;
+import javax.tools.DocumentationTool.DocumentationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+/**
+ * Tests for reusing a documentation task.
+ */
+public class Task_reuseTest extends APITest {
+    public static void main(String... args) throws Exception {
+        new Task_reuseTest().run();
+    }
+
+    /**
+     * Verify that call can only be called once.
+     */
+    @Test
+    public void testReuse() throws Exception {
+        DocumentationTask t = getAndRunTask();
+        try {
+            t.call();
+            error("task was reused without exception");
+        } catch (IllegalStateException e) {
+            System.err.println("caught exception " + e);
+        }
+    }
+
+    /**
+     * Verify that cannot update task after call
+     */
+    @Test
+    public void testUpdateSetLocale() throws Exception {
+        DocumentationTask t = getAndRunTask();
+        try {
+            t.setLocale(Locale.getDefault());
+            error("task was reused without exception");
+        } catch (IllegalStateException e) {
+            System.err.println("caught exception " + e);
+        }
+    }
+
+    private DocumentationTask getAndRunTask() throws Exception {
+        JavaFileObject srcFile = createSimpleJavaFileObject();
+        DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
+        StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+        File outDir = getOutDir();
+        fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir));
+        Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile);
+        DocumentationTask t = tool.getTask(null, fm, null, null, null, files);
+        if (t.call()) {
+            System.err.println("task succeeded");
+            return t;
+        } else {
+            throw new Exception("task failed");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/pkg/C.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package pkg;
+
+public class C { }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javadoc/api/basic/taglets/UnderlineTaglet.java	Thu Nov 15 23:07:24 2012 -0800
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in
+ *  the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ * Neither the name of Oracle nor the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any
+ * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
+ * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
+ * DAMAGES OR LIABILITIES  SUFFERED BY LICENSEE AS A RESULT OF OR
+ * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
+ * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
+ * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
+ * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
+ * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed, licensed or
+ * intended for use in the design, construction, operation or
+ * maintenance of any nuclear facility.
+ */
+
+import com.sun.tools.doclets.Taglet;
+import com.sun.javadoc.*;
+import java.util.Map;
+
+/**
+ * A sample Inline Taglet representing {@underline ...}. This tag can
+ * be used in any kind of {@link com.sun.javadoc.Doc}.
+ * The text is underlined.  For example,
+ * "@underline UNDERLINE ME" would be shown as: <u>UNDERLINE ME</u>.
+ *
+ * @author Jamie Ho
+ * @since 1.4
+ */
+
+public class UnderlineTaglet implements Taglet {
+
+    private static final String NAME = "underline";
+
+    /**
+     * Return the name of this custom tag.
+     */
+    public String getName() {
+        return NAME;
+    }
+
+    /**
+     * @return true since this tag can be used in a field
+     *         doc comment
+     */
+    public boolean inField() {
+        return true;
+    }
+
+    /**
+     * @return true since this tag can be used in a constructor
+     *         doc comment
+     */
+    public boolean inConstructor() {
+        return true;
+    }
+
+    /**
+     * @return true since this tag can be used in a method
+     *         doc comment
+     */
+    public boolean inMethod() {
+        return true;
+    }
+
+    /**
+     * @return true since this tag can be used in an overview
+     *         doc comment
+     */
+    public boolean inOverview() {
+        return true;
+    }
+
+    /**
+     * @return true since this tag can be used in a package
+     *         doc comment
+     */
+    public boolean inPackage() {
+        return true;
+    }
+
+    /**
+     * @return true since this
+     */
+    public boolean inType() {
+        return true;
+    }
+
+    /**
+     * Will return true since this is an inline tag.
+     * @return true since this is an inline tag.
+     */
+
+    public boolean isInlineTag() {
+        return true;
+    }
+
+    /**
+     * Register this Taglet.
+     * @param tagletMap  the map to register this tag to.
+     */
+    public static void register(Map tagletMap) {
+       UnderlineTaglet tag = new UnderlineTaglet();
+       Taglet t = (Taglet) tagletMap.get(tag.getName());
+       if (t != null) {
+           tagletMap.remove(tag.getName());
+       }
+       tagletMap.put(tag.getName(), tag);
+    }
+
+    /**
+     * Given the <code>Tag</code> representation of this custom
+     * tag, return its string representation.
+     * @param tag he <code>Tag</code> representation of this custom tag.
+     */
+    public String toString(Tag tag) {
+        return "<u>" + tag.text() + "</u>";
+    }
+
+    /**
+     * This method should not be called since arrays of inline tags do not
+     * exist.  Method {@link #tostring(Tag)} should be used to convert this
+     * inline tag to a string.
+     * @param tags the array of <code>Tag</code>s representing of this custom tag.
+     */
+    public String toString(Tag[] tags) {
+        return null;
+    }
+}
+