8164407: Add module support for -link and -linkoffline javadoc option
authorbpatel
Wed, 13 Dec 2017 12:45:06 -0800
changeset 48295 c79d31ba84b9
parent 48294 2608240fc957
child 48320 8e561c68f72a
8164407: Add module support for -link and -linkoffline javadoc option Reviewed-by: jjg, ksrini
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocletConstants.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ElementListWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/PackageListWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java
test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java
test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java
test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java
test/langtools/jdk/javadoc/doclet/testModules/TestModules.java
test/langtools/jdk/javadoc/doclet/testModules/jdk/element-list
test/langtools/jdk/javadoc/doclet/testModules/moduleB/module-info.java
test/langtools/jdk/javadoc/doclet/testModules/moduleB/testpkg3mdlB/TestClassLinkOption.java
test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java
test/langtools/jdk/javadoc/tool/api/basic/APITest.java
test/langtools/tools/javadoc/api/basic/APITest.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Wed Dec 13 12:45:06 2017 -0800
@@ -1119,7 +1119,7 @@
                     (label == null) || label.isEmpty() ? defaultLabel : label,
                     strong,
                     resources.getText("doclet.Href_Class_Or_Interface_Title", packageName),
-                    "");
+                    "", true);
             }
         }
         return null;
@@ -1137,6 +1137,11 @@
             DocPaths.PACKAGE_SUMMARY.getPath());
     }
 
+    public DocLink getCrossModuleLink(String mdleName) {
+        return configuration.extern.getExternalLink(mdleName, pathToRoot,
+            DocPaths.moduleSummary(mdleName).getPath());
+    }
+
     /**
      * Get the class link.
      *
@@ -1411,13 +1416,14 @@
                             new StringContent(refPackage.getQualifiedName()));
                 return getPackageLink(refPackage, label);
             } else {
-                // @see is not referencing an included class or package.  Check for cross links.
+                // @see is not referencing an included class, module or package. Check for cross links.
                 Content classCrossLink;
-                DocLink packageCrossLink = getCrossPackageLink(refClassName);
-                if (packageCrossLink != null) {
-                    // Package cross link found
-                    return Links.createLink(packageCrossLink,
-                        (label.isEmpty() ? text : label));
+                DocLink elementCrossLink = (configuration.extern.isModule(refClassName))
+                        ? getCrossModuleLink(refClassName) : getCrossPackageLink(refClassName);
+                if (elementCrossLink != null) {
+                    // Element cross link found
+                    return Links.createLink(elementCrossLink,
+                            (label.isEmpty() ? text : label), true);
                 } else if ((classCrossLink = getCrossClassLink(refClassName,
                         refMemName, label, false, !isLinkPlain)) != null) {
                     // Class cross link found (possibly to a member in the class)
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Wed Dec 13 12:45:06 2017 -0800
@@ -63,6 +63,7 @@
     details,
     docSummary,
     emphasizedPhrase,
+    externalLink,
     fixedNav,
     header,
     horizontal,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java	Wed Dec 13 12:45:06 2017 -0800
@@ -259,6 +259,24 @@
      */
     public static Content createLink(DocLink link, Content label, boolean strong,
             String title, String target) {
+        return createLink(link, label, strong, title, target, false);
+    }
+
+    /**
+     * Creates a link of the form {@code <a href="link" title="title" target="target">label</a>}.
+     * If {@code strong} is set, the label will be wrapped in
+     *      {@code <span style="typeNameLink">...</span>}.
+     *
+     * @param link       the details for the link
+     * @param label      the content for the link
+     * @param strong     whether to wrap the {@code label} in a SPAN element
+     * @param title      the title for the link
+     * @param target     the target for the link, or null
+     * @param isExternal is the link external to the generated documentation
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocLink link, Content label, boolean strong,
+            String title, String target, boolean isExternal) {
         Content body = label;
         if (strong) {
             body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body);
@@ -270,9 +288,26 @@
         if (target != null && target.length() != 0) {
             l.addAttr(HtmlAttr.TARGET, target);
         }
+        if (isExternal) {
+            l.setStyle(HtmlStyle.externalLink);
+        }
         return l;
     }
 
+    /**
+     * Creates a link.
+     *
+     * @param link       the details for the link
+     * @param label      the content for the link
+     * @param isExternal is the link external to the generated documentation
+     * @return a content tree for the link
+     */
+    public static Content createLink(DocLink link, Content label, boolean isExternal) {
+        HtmlTree anchor = HtmlTree.A(link.toString(), label);
+        anchor.setStyle(HtmlStyle.externalLink);
+        return anchor;
+    }
+
 
     /**
      * Converts a name to a valid HTML name (id).
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Wed Dec 13 12:45:06 2017 -0800
@@ -42,7 +42,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.UncheckedDocletException;
 import jdk.javadoc.internal.doclets.toolkit.util.InternalException;
-import jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter;
+import jdk.javadoc.internal.doclets.toolkit.util.ElementListWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.ResourceIOException;
 import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
@@ -210,7 +210,7 @@
 
         generateClassFiles(docEnv, classtree);
 
-        PackageListWriter.generate(configuration);
+        ElementListWriter.generate(configuration);
         generatePackageFiles(classtree);
         generateModuleFiles();
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java	Wed Dec 13 12:45:06 2017 -0800
@@ -31,6 +31,7 @@
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.TypeMirror;
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java	Wed Dec 13 12:45:06 2017 -0800
@@ -62,6 +62,9 @@
     /** The name of the subdirectory for user-provided additional documentation files. */
     public static final DocPath DOC_FILES = DocPath.create("doc-files");
 
+    /** The name of the file for the element list. */
+    public static final DocPath ELEMENT_LIST = DocPath.create("element-list");
+
     /** The name of the image file showing a magnifying glass on the search box. */
     public static final DocPath GLASS_IMG = DocPath.create("glass.png");
 
@@ -149,7 +152,7 @@
     /** The name of the file for the package frame. */
     public static final DocPath PACKAGE_FRAME = DocPath.create("package-frame.html");
 
-    /** The name of the file for the package list. */
+    /** The name of the file for the package list. This is to support the legacy mode. */
     public static final DocPath PACKAGE_LIST = DocPath.create("package-list");
 
     /** The name of the package search index file. */
@@ -182,7 +185,12 @@
 
     /** The name of the file for the module summary. */
     public static DocPath moduleSummary(ModuleElement mdle) {
-        return DocPath.create(mdle.getQualifiedName() + "-summary.html");
+        return DocPaths.moduleSummary(mdle.getQualifiedName().toString());
+    }
+
+    /** The name of the file for the module summary. */
+    public static DocPath moduleSummary(String mdleName) {
+        return DocPath.create(mdleName + "-summary.html");
     }
 
     /** The name of the file for the module frame. */
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocletConstants.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocletConstants.java	Wed Dec 13 12:45:06 2017 -0800
@@ -54,6 +54,16 @@
     public static final String DEFAULT_PACKAGE_NAME = "<Unnamed>";
 
     /**
+     * The default module or a package name.
+     */
+    public static final String DEFAULT_ELEMENT_NAME = "<Unnamed>";
+
+    /**
+     * The module prefix in the element-list file.
+     */
+    public static final String MODULE_PREFIX = "module:";
+
+    /**
      * The default package file name.
      */
     public static final String DEFAULT_PACKAGE_FILE_NAME = "default";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ElementListWriter.java	Wed Dec 13 12:45:06 2017 -0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1998, 2017, 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 jdk.javadoc.internal.doclets.toolkit.util;
+
+import java.io.*;
+
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.PackageElement;
+
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+
+
+/**
+ * Write out the element index.
+ *
+ *  <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>
+ *
+ * @author Atul M Dambalkar
+ */
+public class ElementListWriter {
+
+    private final BaseConfiguration configuration;
+    private final Utils utils;
+    private final DocFile file;
+
+    /**
+     * Constructor.
+     *
+     * @param configuration the current configuration of the doclet.
+     */
+    public ElementListWriter(BaseConfiguration configuration) {
+        file = DocFile.createFileForOutput(configuration, DocPaths.ELEMENT_LIST);
+        this.configuration = configuration;
+        this.utils = configuration.utils;
+    }
+
+    /**
+     * Generate the element index.
+     *
+     * @param configuration the current configuration of the doclet.
+     * @throws DocFileIOException if there is a problem writing the output
+     */
+    public static void generate(BaseConfiguration configuration) throws DocFileIOException {
+        ElementListWriter elemgen = new ElementListWriter(configuration);
+        elemgen.generateElementListFile(configuration.docEnv);
+    }
+
+    protected void generateElementListFile(DocletEnvironment docEnv) throws DocFileIOException {
+        try (BufferedWriter out = new BufferedWriter(file.openWriter())) {
+            if (configuration.showModules) {
+                for (ModuleElement mdle : configuration.modulePackages.keySet()) {
+                    if (!(configuration.nodeprecated && utils.isDeprecated(mdle))) {
+                        out.write(DocletConstants.MODULE_PREFIX + mdle.toString());
+                        out.newLine();
+                        for (PackageElement pkg : configuration.modulePackages.get(mdle)) {
+                            out.write(pkg.toString());
+                            out.newLine();
+                        }
+                    }
+                }
+            } else {
+                for (PackageElement pkg : configuration.packages) {
+                    // if the -nodeprecated option is set and the package is marked as
+                    // deprecated, do not include it in the packages list.
+                    if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
+                        out.write(pkg.toString());
+                        out.newLine();
+                    }
+                }
+            }
+        } catch (IOException e) {
+            throw new DocFileIOException(file, DocFileIOException.Mode.WRITE, e);
+        }
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java	Wed Dec 13 12:45:06 2017 -0800
@@ -56,10 +56,10 @@
 public class Extern {
 
     /**
-     * Map package names onto Extern Item objects.
+     * Map element names onto Extern Item objects.
      * Lazily initialized.
      */
-    private Map<String, Item> packageToItemMap;
+    private Map<String, Item> elementToItemMap;
 
     /**
      * The global configuration information for this run.
@@ -77,12 +77,12 @@
     private class Item {
 
         /**
-         * Package name, found in the "package-list" file in the {@link path}.
+         * Element name, found in the "element-list" file in the {@link path}.
          */
-        final String packageName;
+        final String elementName;
 
         /**
-         * The URL or the directory path at which the package documentation will be
+         * The URL or the directory path at which the element documentation will be
          * avaliable.
          */
         final String path;
@@ -93,33 +93,40 @@
         final boolean relative;
 
         /**
-         * Constructor to build a Extern Item object and map it with the package name.
-         * If the same package name is found in the map, then the first mapped
+         * If the item is a module then true else if it is a package then false.
+         */
+        boolean isModule = false;
+
+        /**
+         * Constructor to build a Extern Item object and map it with the element name.
+         * If the same element name is found in the map, then the first mapped
          * Item object or offline location will be retained.
          *
-         * @param packageName Package name found in the "package-list" file.
-         * @param path        URL or Directory path from where the "package-list"
+         * @param elementName Element name found in the "element-list" file.
+         * @param path        URL or Directory path from where the "element-list"
          * file is picked.
          * @param relative    True if path is URL, false if directory path.
+         * @param isModule    True if the item is a module. False if it is a package.
          */
-        Item(String packageName, String path, boolean relative) {
-            this.packageName = packageName;
+        Item(String elementName, String path, boolean relative, boolean isModule) {
+            this.elementName = elementName;
             this.path = path;
             this.relative = relative;
-            if (packageToItemMap == null) {
-                packageToItemMap = new HashMap<>();
+            this.isModule = isModule;
+            if (elementToItemMap == null) {
+                elementToItemMap = new HashMap<>();
             }
-            if (!packageToItemMap.containsKey(packageName)) { // save the previous
-                packageToItemMap.put(packageName, this);        // mapped location
+            if (!elementToItemMap.containsKey(elementName)) { // save the previous
+                elementToItemMap.put(elementName, this);        // mapped location
             }
         }
 
         /**
-         * String representation of "this" with packagename and the path.
+         * String representation of "this" with elementname and the path.
          */
         @Override
         public String toString() {
-            return packageName + (relative? " -> " : " => ") + path;
+            return elementName + (relative? " -> " : " => ") + path;
         }
     }
 
@@ -134,31 +141,42 @@
      * @return true if the element is externally documented
      */
     public boolean isExternal(Element element) {
-        if (packageToItemMap == null) {
+        if (elementToItemMap == null) {
             return false;
         }
         PackageElement pe = configuration.utils.containingPackage(element);
         if (pe.isUnnamed()) {
             return false;
         }
-        return packageToItemMap.get(configuration.utils.getPackageName(pe)) != null;
+        return elementToItemMap.get(configuration.utils.getPackageName(pe)) != null;
+    }
+
+    /**
+     * Determine if a element item is a module or not.
+     *
+     * @param elementName name of the element.
+     * @return true if the element is a module
+     */
+    public boolean isModule(String elementName) {
+        Item elem = findElementItem(elementName);
+        return (elem == null) ? false : elem.isModule;
     }
 
     /**
      * Convert a link to be an external link if appropriate.
      *
-     * @param pkgName The package name.
+     * @param elemName The element name.
      * @param relativepath    The relative path.
      * @param filename    The link to convert.
      * @return if external return converted link else return null
      */
-    public DocLink getExternalLink(String pkgName, DocPath relativepath, String filename) {
-        return getExternalLink(pkgName, relativepath, filename, null);
+    public DocLink getExternalLink(String elemName, DocPath relativepath, String filename) {
+        return getExternalLink(elemName, relativepath, filename, null);
     }
 
-    public DocLink getExternalLink(String pkgName, DocPath relativepath, String filename,
+    public DocLink getExternalLink(String elemName, DocPath relativepath, String filename,
             String memberName) {
-        Item fnd = findPackageItem(pkgName);
+        Item fnd = findElementItem(elemName);
         if (fnd == null)
             return null;
 
@@ -170,56 +188,56 @@
     }
 
     /**
-     * Build the extern package list from given URL or the directory path,
+     * Build the extern element list from given URL or the directory path,
      * as specified with the "-link" flag.
      * Flag error if the "-link" or "-linkoffline" option is already used.
      *
      * @param url        URL or Directory path.
      * @param reporter   The <code>DocErrorReporter</code> used to report errors.
      * @return true if successful, false otherwise
-     * @throws DocFileIOException if there is a problem reading a package list file
+     * @throws DocFileIOException if there is a problem reading a element list file
      */
     public boolean link(String url, Reporter reporter) throws DocFileIOException {
         return link(url, url, reporter, false);
     }
 
     /**
-     * Build the extern package list from given URL or the directory path,
+     * Build the extern element list from given URL or the directory path,
      * as specified with the "-linkoffline" flag.
      * Flag error if the "-link" or "-linkoffline" option is already used.
      *
      * @param url        URL or Directory path.
-     * @param pkglisturl This can be another URL for "package-list" or ordinary
+     * @param elemlisturl This can be another URL for "element-list" or ordinary
      *                   file.
      * @param reporter   The <code>DocErrorReporter</code> used to report errors.
      * @return true if successful, false otherwise
-     * @throws DocFileIOException if there is a problem reading a package list file
+     * @throws DocFileIOException if there is a problem reading the element list file
      */
-    public boolean link(String url, String pkglisturl, Reporter reporter) throws DocFileIOException {
-        return link(url, pkglisturl, reporter, true);
+    public boolean link(String url, String elemlisturl, Reporter reporter) throws DocFileIOException {
+        return link(url, elemlisturl, reporter, true);
     }
 
     /*
-     * Build the extern package list from given URL or the directory path.
+     * Build the extern element list from given URL or the directory path.
      * Flag error if the "-link" or "-linkoffline" option is already used.
      *
      * @param url        URL or Directory path.
-     * @param pkglisturl This can be another URL for "package-list" or ordinary
+     * @param elemlisturl This can be another URL for "element-list" or ordinary
      *                   file.
      * @param reporter   The <code>DocErrorReporter</code> used to report errors.
      * @param linkoffline True if -linkoffline is used and false if -link is used.
      * @return true if successful, false otherwise
-     * @throws DocFileIOException if there is a problem reading a package list file
+     * @throws DocFileIOException if there is a problem reading the element list file
      */
-    private boolean link(String url, String pkglisturl, Reporter reporter, boolean linkoffline)
+    private boolean link(String url, String elemlisturl, Reporter reporter, boolean linkoffline)
                 throws DocFileIOException {
         this.linkoffline = linkoffline;
         try {
             url = adjustEndFileSeparator(url);
-            if (isUrl(pkglisturl)) {
-                readPackageListFromURL(url, toURL(adjustEndFileSeparator(pkglisturl)));
+            if (isUrl(elemlisturl)) {
+                readElementListFromURL(url, toURL(adjustEndFileSeparator(elemlisturl)));
             } else {
-                readPackageListFromFile(url, DocFile.createFileForInput(configuration, pkglisturl));
+                readElementListFromFile(url, DocFile.createFileForInput(configuration, elemlisturl));
             }
             return true;
         } catch (Fault f) {
@@ -245,15 +263,15 @@
     }
 
     /**
-     * Get the Extern Item object associated with this package name.
+     * Get the Extern Item object associated with this element name.
      *
-     * @param pkgName Package name.
+     * @param elemName Element name.
      */
-    private Item findPackageItem(String pkgName) {
-        if (packageToItemMap == null) {
+    private Item findElementItem(String elemName) {
+        if (elementToItemMap == null) {
             return null;
         }
-        return packageToItemMap.get(pkgName);
+        return elementToItemMap.get(elemName);
     }
 
     /**
@@ -264,42 +282,75 @@
     }
 
     /**
+     * Fetch the URL and read the "element-list" file.
+     *
+     * @param urlpath        Path to the elements.
+     * @param elemlisturlpath URL or the path to the "element-list" file.
+     */
+    private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws Fault {
+        try {
+            URL link = elemlisturlpath.toURI().resolve(DocPaths.ELEMENT_LIST.getPath()).toURL();
+            readElementList(link.openStream(), urlpath, false);
+        } catch (URISyntaxException | MalformedURLException exc) {
+            throw new Fault(configuration.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
+        } catch (IOException exc) {
+            readAlternateURL(urlpath, elemlisturlpath);
+        }
+    }
+
+    /**
      * Fetch the URL and read the "package-list" file.
      *
      * @param urlpath        Path to the packages.
-     * @param pkglisturlpath URL or the path to the "package-list" file.
+     * @param elemlisturlpath URL or the path to the "package-list" file.
      */
-    private void readPackageListFromURL(String urlpath, URL pkglisturlpath) throws Fault {
+    private void readAlternateURL(String urlpath, URL elemlisturlpath) throws Fault {
         try {
-            URL link = pkglisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL();
-            readPackageList(link.openStream(), urlpath, false);
+            URL link = elemlisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL();
+            readElementList(link.openStream(), urlpath, false);
         } catch (URISyntaxException | MalformedURLException exc) {
-            throw new Fault(configuration.getText("doclet.MalformedURL", pkglisturlpath.toString()), exc);
+            throw new Fault(configuration.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
         } catch (IOException exc) {
-            throw new Fault(configuration.getText("doclet.URL_error", pkglisturlpath.toString()), exc);
+            throw new Fault(configuration.getText("doclet.URL_error", elemlisturlpath.toString()), exc);
         }
     }
 
     /**
-     * Read the "package-list" file which is available locally.
+     * Read the "element-list" file which is available locally.
      *
-     * @param path URL or directory path to the packages.
-     * @param pkgListPath Path to the local "package-list" file.
+     * @param path URL or directory path to the elements.
+     * @param elemListPath Path to the local "element-list" file.
      * @throws Fault if an error occurs that can be treated as a warning
-     * @throws DocFileIOException if there is a problem opening the package list file
+     * @throws DocFileIOException if there is a problem opening the element list file
      */
-    private void readPackageListFromFile(String path, DocFile pkgListPath)
+    private void readElementListFromFile(String path, DocFile elemListPath)
             throws Fault, DocFileIOException {
-        DocFile file = pkgListPath.resolve(DocPaths.PACKAGE_LIST);
+        DocFile file = elemListPath.resolve(DocPaths.ELEMENT_LIST);
         if (! (file.isAbsolute() || linkoffline)){
             file = file.resolveAgainst(DocumentationTool.Location.DOCUMENTATION_OUTPUT);
         }
+        if (file.exists()) {
+            readElementList(file, path);
+        } else {
+            DocFile file1 = elemListPath.resolve(DocPaths.PACKAGE_LIST);
+            if (!(file1.isAbsolute() || linkoffline)) {
+                file1 = file1.resolveAgainst(DocumentationTool.Location.DOCUMENTATION_OUTPUT);
+            }
+            if (file1.exists()) {
+                readElementList(file1, path);
+            } else {
+                throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null);
+            }
+        }
+    }
+
+    private void readElementList(DocFile file, String path) throws Fault, DocFileIOException {
         try {
-            if (file.exists() && file.canRead()) {
-                boolean pathIsRelative =
-                        !isUrl(path)
+            if (file.canRead()) {
+                boolean pathIsRelative
+                        = !isUrl(path)
                         && !DocFile.createFileForInput(configuration, path).isAbsolute();
-                readPackageList(file.openInputStream(), path, pathIsRelative);
+                readElementList(file.openInputStream(), path, pathIsRelative);
             } else {
                 throw new Fault(configuration.getText("doclet.File_error", file.getPath()), null);
             }
@@ -309,33 +360,32 @@
     }
 
     /**
-     * Read the file "package-list" and for each package name found, create
-     * Extern object and associate it with the package name in the map.
+     * Read the file "element-list" and for each element name found, create
+     * Extern object and associate it with the element name in the map.
      *
-     * @param input    InputStream from the "package-list" file.
-     * @param path     URL or the directory path to the packages.
+     * @param input     InputStream from the "element-list" file.
+     * @param path     URL or the directory path to the elements.
      * @param relative Is path relative?
      * @throws IOException if there is a problem reading or closing the stream
      */
-    private void readPackageList(InputStream input, String path, boolean relative)
+    private void readElementList(InputStream input, String path, boolean relative)
                          throws IOException {
         try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) {
-            StringBuilder strbuf = new StringBuilder();
-            int c;
-            while ((c = in.read()) >= 0) {
-                char ch = (char) c;
-                if (ch == '\n' || ch == '\r') {
-                    if (strbuf.length() > 0) {
-                        String packname = strbuf.toString();
-                        String packpath = path
-                                + packname.replace('.', '/') + '/';
-                        Item ignore = new Item(packname, packpath, relative);
-                        strbuf.setLength(0);
+            in.lines().forEach((elemname) -> {
+                if (elemname.length() > 0) {
+                    boolean module;
+                    String elempath;
+                    if (elemname.startsWith(DocletConstants.MODULE_PREFIX)) {
+                        elemname = elemname.replace(DocletConstants.MODULE_PREFIX, "");
+                        elempath = path;
+                        module = true;
+                    } else {
+                        elempath = path + elemname.replace('.', '/') + '/';
+                        module = false;
                     }
-                } else {
-                    strbuf.append(ch);
+                    Item ignore = new Item(elemname, elempath, relative, module);
                 }
-            }
+            });
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/PackageListWriter.java	Wed Dec 13 21:25:49 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 1998, 2017, 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 jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.io.*;
-
-import javax.lang.model.element.PackageElement;
-
-import jdk.javadoc.doclet.DocletEnvironment;
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-
-
-/**
- * Write out the package index.
- *
- *  <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>
- *
- * @author Atul M Dambalkar
- */
-public class PackageListWriter {
-
-    private final BaseConfiguration configuration;
-    private final Utils utils;
-    private final DocFile file;
-
-    /**
-     * Constructor.
-     *
-     * @param configuration the current configuration of the doclet.
-     */
-    public PackageListWriter(BaseConfiguration configuration) {
-        file = DocFile.createFileForOutput(configuration, DocPaths.PACKAGE_LIST);
-        this.configuration = configuration;
-        this.utils = configuration.utils;
-    }
-
-    /**
-     * Generate the package index.
-     *
-     * @param configuration the current configuration of the doclet.
-     * @throws DocFileIOException if there is a problem writing the output
-     */
-    public static void generate(BaseConfiguration configuration) throws DocFileIOException {
-        PackageListWriter packgen = new PackageListWriter(configuration);
-        packgen.generatePackageListFile(configuration.docEnv);
-    }
-
-    protected void generatePackageListFile(DocletEnvironment docEnv) throws DocFileIOException {
-        try (BufferedWriter out = new BufferedWriter(file.openWriter())) {
-            for (PackageElement pkg : configuration.packages) {
-                // if the -nodeprecated option is set and the package is marked as
-                // deprecated, do not include it in the packages list.
-                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                    out.write(pkg.toString());
-                    out.newLine();
-                }
-            }
-        } catch (IOException e) {
-            throw new DocFileIOException(file, DocFileIOException.Mode.WRITE, e);
-        }
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Wed Dec 13 12:45:06 2017 -0800
@@ -2673,7 +2673,8 @@
     }
 
     /**
-     * package name, an unnamed package is returned as &lt;Unnamed&gt;
+     * Get the package name for a given package element. An unnamed package is returned as &lt;Unnamed&gt;
+     *
      * @param pkg
      * @return
      */
@@ -2684,6 +2685,19 @@
         return pkg.getQualifiedName().toString();
     }
 
+    /**
+     * Get the module name for a given module element. An unnamed module is returned as &lt;Unnamed&gt;
+     *
+     * @param mdle a ModuleElement
+     * @return
+     */
+    public String getModuleName(ModuleElement mdle) {
+        if (mdle == null || mdle.isUnnamed()) {
+            return DocletConstants.DEFAULT_ELEMENT_NAME;
+        }
+        return mdle.getQualifiedName().toString();
+    }
+
     public boolean isAttribute(DocTree doctree) {
         return isKind(doctree, ATTRIBUTE);
     }
--- a/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testClassCrossReferences/TestClassCrossReferences.java	Wed Dec 13 12:45:06 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4652655 4857717 8025633 8026567 8071982
+ * @bug 4652655 4857717 8025633 8026567 8071982 8164407
  * @summary This test verifies that class cross references work properly.
  * @author jamieh
  * @library ../lib
@@ -52,16 +52,16 @@
         checkExit(Exit.OK);
 
         checkOutput("C.html", true,
-                "<a href=\"" + uri + "java/math/package-summary.html?is-external=true\">"
+                "<a href=\"" + uri + "java/math/package-summary.html?is-external=true\" class=\"externalLink\">"
                 + "<code>Link to math package</code></a>",
                 "<a href=\"" + uri + "javax/swing/text/AbstractDocument.AttributeContext.html?is-external=true\" "
-                + "title=\"class or interface in javax.swing.text\"><code>Link to AttributeContext innerclass</code></a>",
+                + "title=\"class or interface in javax.swing.text\" class=\"externalLink\"><code>Link to AttributeContext innerclass</code></a>",
                 "<a href=\"" + uri + "java/math/BigDecimal.html?is-external=true\" "
-                + "title=\"class or interface in java.math\"><code>Link to external class BigDecimal</code></a>",
+                + "title=\"class or interface in java.math\" class=\"externalLink\"><code>Link to external class BigDecimal</code></a>",
                 "<a href=\"" + uri + "java/math/BigInteger.html?is-external=true#gcd-java.math.BigInteger-\" "
-                + "title=\"class or interface in java.math\"><code>Link to external member gcd</code></a>",
+                + "title=\"class or interface in java.math\" class=\"externalLink\"><code>Link to external member gcd</code></a>",
                 "<a href=\"" + uri + "javax/tools/SimpleJavaFileObject.html?is-external=true#URI\" "
-                + "title=\"class or interface in javax.tools\"><code>Link to external member URI</code></a>",
+                + "title=\"class or interface in javax.tools\" class=\"externalLink\"><code>Link to external member URI</code></a>",
                 "<dl>\n"
                 + "<dt><span class=\"overrideSpecifyLabel\">Overrides:</span></dt>\n"
                 + "<dd><code>toString</code>&nbsp;in class&nbsp;<code>java.lang.Object</code></dd>\n"
--- a/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testDocRootInlineTag/TestDocRootInlineTag.java	Wed Dec 13 12:45:06 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4369014 4851991
+ * @bug 4369014 4851991 8164407
  * @summary Determine if the docRoot inline tag works properly.
  * If docRoot performs as documented, the test passes.
  * Make sure that the docRoot tag works with the -bottom option.
@@ -54,10 +54,10 @@
 
         checkOutput("TestDocRootTag.html", true,
                 "<a href=\"" + uri + "/java/io/File.html?is-external=true\" "
-                + "title=\"class or interface in java.io\"><code>File</code></a>",
+                + "title=\"class or interface in java.io\" class=\"externalLink\"><code>File</code></a>",
                 "<a href=\"./glossary.html\">glossary</a>",
                 "<a href=\"" + uri + "/java/io/File.html?is-external=true\" "
-                + "title=\"class or interface in java.io\"><code>Second File Link</code></a>",
+                + "title=\"class or interface in java.io\" class=\"externalLink\"><code>Second File Link</code></a>",
                 "The value of @docRoot is \"./\"");
 
         checkOutput("index-all.html", true,
--- a/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testExternalOverridenMethod/TestExternalOverridenMethod.java	Wed Dec 13 12:45:06 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4857717 8025633 8026567
+ * @bug 4857717 8025633 8026567 8164407
  * @summary Test to make sure that externally overriden and implemented methods
  * are documented properly.  The method should still include "implements" or
  * "overrides" documentation even though the method is external.
@@ -53,14 +53,14 @@
         checkOutput("pkg/XReader.html", true,
                 "<dt><span class=\"overrideSpecifyLabel\">Overrides:</span></dt>\n"
                 + "<dd><code><a href=\"" + uri + "/java/io/FilterReader.html?is-external=true#read--\" "
-                + "title=\"class or interface in java.io\">read</a></code>&nbsp;in class&nbsp;<code>"
+                + "title=\"class or interface in java.io\" class=\"externalLink\">read</a></code>&nbsp;in class&nbsp;<code>"
                 + "<a href=\"" + uri + "/java/io/FilterReader.html?is-external=true\" "
-                + "title=\"class or interface in java.io\">FilterReader</a></code></dd>",
+                + "title=\"class or interface in java.io\" class=\"externalLink\">FilterReader</a></code></dd>",
                 "<dt><span class=\"overrideSpecifyLabel\">Specified by:</span></dt>\n"
                 + "<dd><code><a href=\"" + uri + "/java/io/DataInput.html?is-external=true#readInt--\" "
-                + "title=\"class or interface in java.io\">readInt</a></code>&nbsp;in interface&nbsp;<code>"
+                + "title=\"class or interface in java.io\" class=\"externalLink\">readInt</a></code>&nbsp;in interface&nbsp;<code>"
                 + "<a href=\"" + uri + "/java/io/DataInput.html?is-external=true\" "
-                + "title=\"class or interface in java.io\">DataInput</a></code></dd>"
+                + "title=\"class or interface in java.io\" class=\"externalLink\">DataInput</a></code></dd>"
         );
     }
 }
--- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestLinkOption.java	Wed Dec 13 12:45:06 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4720957 5020118 8026567 8038976 8184969
+ * @bug 4720957 5020118 8026567 8038976 8184969 8164407
  * @summary Test to make sure that -link and -linkoffline link to
  * right files, and URLs with and without trailing slash are accepted.
  * @author jamieh
@@ -70,26 +70,26 @@
 
         checkOutput("pkg/C.html", true,
                 "<a href=\"" + url + "java/lang/String.html?is-external=true\" "
-                + "title=\"class or interface in java.lang\"><code>Link to String Class</code></a>",
+                + "title=\"class or interface in java.lang\" class=\"externalLink\"><code>Link to String Class</code></a>",
                 //Make sure the parameters are indented properly when the -link option is used.
                 "(int&nbsp;p1,\n"
                 + "      int&nbsp;p2,\n"
                 + "      int&nbsp;p3)",
                 "(int&nbsp;p1,\n"
                 + "      int&nbsp;p2,\n"
-                + "      <a href=\"" + url + "java/lang/Object.html?is-external=true\" title=\"class or interface in java.lang\">"
+                + "      <a href=\"" + url + "java/lang/Object.html?is-external=true\" title=\"class or interface in java.lang\" class=\"externalLink\">"
                 + "Object</a>&nbsp;p3)");
 
         checkOutput("pkg/B.html", true,
                 "<div class=\"block\">A method with html tag the method "
                 + "<a href=\"" + url + "java/lang/ClassLoader.html?is-external=true#getSystemClassLoader--\""
-                + " title=\"class or interface in java.lang\"><code><tt>getSystemClassLoader()</tt>"
+                + " title=\"class or interface in java.lang\" class=\"externalLink\"><code><tt>getSystemClassLoader()</tt>"
                 + "</code></a> as the parent class loader.</div>",
                 "<div class=\"block\">is equivalent to invoking <code>"
                 + "<a href=\"../pkg/B.html#createTempFile-java.lang.String-java.lang.String-java.io.File-\">"
                 + "<code>createTempFile(prefix,&nbsp;suffix,&nbsp;null)</code></a></code>.</div>",
                 "<a href=\"" + url + "java/lang/String.html?is-external=true\" "
-                + "title=\"class or interface in java.lang\">Link-Plain to String Class</a>",
+                + "title=\"class or interface in java.lang\" class=\"externalLink\">Link-Plain to String Class</a>",
                 "<code><tt>getSystemClassLoader()</tt></code>",
                 "<code>createTempFile(prefix,&nbsp;suffix,&nbsp;null)</code>",
                 "<dd><a href=\"http://www.ietf.org/rfc/rfc2279.txt\"><i>RFC&nbsp;2279: UTF-8, a\n" +
@@ -106,7 +106,7 @@
         checkOutput("mylib/lang/StringBuilderChild.html", true,
                 "<pre>public abstract class <span class=\"typeNameLabel\">StringBuilderChild</span>\n"
                 + "extends <a href=\"" + url + "java/lang/Object.html?is-external=true\" "
-                + "title=\"class or interface in java.lang\">Object</a></pre>"
+                + "title=\"class or interface in java.lang\" class=\"externalLink\">Object</a></pre>"
         );
 
         // Generate the documentation using -linkoffline and a relative path as the first parameter.
@@ -120,7 +120,7 @@
         checkExit(Exit.OK);
         checkOutput("pkg2/C2.html", true,
             "This is a link to <a href=\"../../" + out1 + "/pkg/C.html?is-external=true\" " +
-            "title=\"class or interface in pkg\"><code>Class C</code></a>."
+            "title=\"class or interface in pkg\" class=\"externalLink\"><code>Class C</code></a>."
         );
 
         String out3 = "out3";
@@ -149,10 +149,10 @@
                 + "<div class=\"block\">Test links.\n"
                 + " <br>\n"
                 + " <a href=\"../../out2/pkg2/C2.html?is-external=true\" "
-                + "title=\"class or interface in pkg2\"><code>link to pkg2.C2</code></a>\n"
+                + "title=\"class or interface in pkg2\" class=\"externalLink\"><code>link to pkg2.C2</code></a>\n"
                 + " <br>\n"
                 + " <a href=\"../../out1/mylib/lang/StringBuilderChild.html?is-external=true\" "
-                + "title=\"class or interface in mylib.lang\">"
+                + "title=\"class or interface in mylib.lang\" class=\"externalLink\">"
                 + "<code>link to mylib.lang.StringBuilderChild</code></a>.</div>\n"
         );
 
@@ -169,10 +169,10 @@
                         + "<div class=\"block\">Test links.\n"
                         + " <br>\n"
                         + " <a href=\"../../copy/out2/pkg2/C2.html?is-external=true\" "
-                        + "title=\"class or interface in pkg2\"><code>link to pkg2.C2</code></a>\n"
+                        + "title=\"class or interface in pkg2\" class=\"externalLink\"><code>link to pkg2.C2</code></a>\n"
                         + " <br>\n"
                         + " <a href=\"../../copy/out1/mylib/lang/StringBuilderChild.html?is-external=true\" "
-                        + "title=\"class or interface in mylib.lang\">"
+                        + "title=\"class or interface in mylib.lang\" class=\"externalLink\">"
                         + "<code>link to mylib.lang.StringBuilderChild</code></a>.</div>\n"
         );
     }
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Wed Dec 13 12:45:06 2017 -0800
@@ -26,6 +26,7 @@
  * @bug 8154119 8154262 8156077 8157987 8154261 8154817 8135291 8155995 8162363
  *      8168766 8168688 8162674 8160196 8175799 8174974 8176778 8177562 8175218
  *      8175823 8166306 8178043 8181622 8183511 8169819 8074407 8183037 8191464
+        8164407
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -45,7 +46,7 @@
      */
     @Test
     void testHtml4() {
-        javadoc("-d", "out", "-use",
+        javadoc("-d", "out", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
@@ -67,7 +68,7 @@
      */
     @Test
     void testHtml5() {
-        javadoc("-d", "out-html5", "-html5", "-use",
+        javadoc("-d", "out-html5", "-html5", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
@@ -89,7 +90,7 @@
      */
     @Test
     void testHtml4NoComment() {
-        javadoc("-d", "out-nocomment", "-nocomment", "-use",
+        javadoc("-d", "out-nocomment", "-nocomment", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
@@ -107,7 +108,7 @@
      */
     @Test
     void testHtml5NoComment() {
-        javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5", "-use",
+        javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
@@ -158,7 +159,7 @@
      */
     @Test
     void testJDTagsInModules() {
-        javadoc("-d", "out-mdltags", "-author", "-version",
+        javadoc("-d", "out-mdltags", "-author", "-version", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -173,7 +174,7 @@
      */
     @Test
     void testModuleSummary() {
-        javadoc("-d", "out-moduleSummary", "-use",
+        javadoc("-d", "out-moduleSummary", "-use", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
                 "testpkgmdlA", "testpkgmdlB", "moduleB/testpkg2mdlB");
@@ -200,7 +201,7 @@
      */
     @Test
     void testModuleFilesAndLinks() {
-        javadoc("-d", "out-modulelinks",
+        javadoc("-d", "out-modulelinks", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
                 "testpkgmdlA", "testpkgmdlB");
@@ -214,7 +215,7 @@
      */
     @Test
     void testModuleDeprecation() {
-        javadoc("-d", "out-moduledepr",
+        javadoc("-d", "out-moduledepr", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -229,7 +230,7 @@
      */
     @Test
     void testModuleAnnotation() {
-        javadoc("-d", "out-moduleanno",
+        javadoc("-d", "out-moduleanno", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "--module", "moduleA,moduleB",
                 "testpkgmdlA", "testpkgmdlB");
@@ -242,7 +243,7 @@
      */
     @Test
     void testApiMode() {
-        javadoc("-d", "out-api", "-use", "--show-module-contents=api", "-author", "-version",
+        javadoc("-d", "out-api", "-use", "--show-module-contents=api", "-author", "-version", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -261,7 +262,7 @@
      */
     @Test
     void testAllMode() {
-        javadoc("-d", "out-all", "-use", "--show-module-contents=all", "-author", "-version",
+        javadoc("-d", "out-all", "-use", "--show-module-contents=all", "-author", "-version", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -319,7 +320,7 @@
      */
     @Test
     void testSingleModuleMultiplePkg() {
-        javadoc("-d", "out-singlemodmultiplepkg", "--show-module-contents=all",
+        javadoc("-d", "out-singlemodmultiplepkg", "--show-module-contents=all", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "--module", "moduleB",
                 "testpkg2mdlB", "testpkgmdlB");
@@ -332,7 +333,7 @@
      */
     @Test
     void testGroupOption() {
-        javadoc("-d", "out-group", "--show-module-contents=all",
+        javadoc("-d", "out-group", "--show-module-contents=all", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -353,7 +354,7 @@
      */
     @Test
     void testGroupOptionOrdering() {
-        javadoc("-d", "out-groupOrder", "--show-module-contents=all",
+        javadoc("-d", "out-groupOrder", "--show-module-contents=all", "-Xdoclint:none",
                 "-tag", "regular:a:Regular Tag:",
                 "-tag", "moduletag:s:Module Tag:",
                 "--module-source-path", testSrc,
@@ -373,7 +374,7 @@
      */
     @Test
     void testUnnamedModuleGroupOption() {
-        javadoc("-d", "out-groupnomodule", "-use",
+        javadoc("-d", "out-groupnomodule", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "-sourcepath", testSrc,
                 "-group", "Package Group 0", "testpkgnomodule",
@@ -390,7 +391,7 @@
      */
     @Test
     void testGroupOptionPackageOrdering() {
-        javadoc("-d", "out-groupPkgOrder", "-use",
+        javadoc("-d", "out-groupPkgOrder", "-use", "-Xdoclint:none",
                 "-overview", testSrc("overview.html"),
                 "-sourcepath", testSrc,
                 "-group", "Z Group", "testpkgnomodule",
@@ -405,7 +406,7 @@
      */
     @Test
     void testGroupOptionSingleModule() {
-        javadoc("-d", "out-groupsinglemodule", "-use",
+        javadoc("-d", "out-groupsinglemodule", "-use", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "-group", "Module Group B", "moduleB*",
                 "--module", "moduleB",
@@ -419,7 +420,7 @@
      */
     @Test
     void testModuleName() {
-        javadoc("-d", "out-modulename", "-use",
+        javadoc("-d", "out-modulename", "-use", "-Xdoclint:none",
                 "--module-source-path", testSrc,
                 "--module", "moduleB,test.moduleFullName",
                 "testpkg2mdlB", "testpkgmdlB", "testpkgmdlfullname");
@@ -427,6 +428,21 @@
         checkModuleName(true);
     }
 
+    /**
+     * Test -linkoffline option.
+     */
+    @Test
+    void testLinkOffline() {
+        String url = "https://docs.oracle.com/javase/9/docs/api/";
+        javadoc("-d", "out-linkoffline", "-use", "--show-module-contents=all", "-Xdoclint:none",
+                "--module-source-path", testSrc,
+                "--module", "moduleA,moduleB",
+                "-linkoffline", url, testSrc + "/jdk",
+                "testpkgmdlA", "testpkgmdlB", "testpkg3mdlB");
+        checkExit(Exit.OK);
+        checkLinkOffline();
+    }
+
     void checkDescription(boolean found) {
         checkOutput("moduleA-summary.html", found,
                 "<!-- ============ MODULE DESCRIPTION =========== -->\n"
@@ -1205,4 +1221,16 @@
                 + "</dd>\n"
                 + "</dl>");
     }
+
+    void checkLinkOffline() {
+        checkOutput("testpkg3mdlB/package-summary.html", true,
+                "<a href=\"https://docs.oracle.com/javase/9/docs/api/java/lang/String.html?is-external=true\" "
+                + "title=\"class or interface in java.lang\" class=\"externalLink\"><code>Link to String Class</code></a>");
+        checkOutput("testpkg3mdlB/package-summary.html", true,
+                "<a href=\"https://docs.oracle.com/javase/9/docs/api/java/lang/package-summary.html?is-external=true\" "
+                + "class=\"externalLink\"><code>Link to java.lang package</code></a>");
+        checkOutput("testpkg3mdlB/package-summary.html", true,
+                "<a href=\"https://docs.oracle.com/javase/9/docs/api/java.base-summary.html?is-external=true\" "
+                + "class=\"externalLink\"><code>Link to java.base module</code></a>");
 }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModules/jdk/element-list	Wed Dec 13 12:45:06 2017 -0800
@@ -0,0 +1,343 @@
+module:java.activation
+javax.activation
+module:java.base
+java.io
+java.lang
+java.lang.annotation
+java.lang.invoke
+java.lang.module
+java.lang.ref
+java.lang.reflect
+java.math
+java.net
+java.net.spi
+java.nio
+java.nio.channels
+java.nio.channels.spi
+java.nio.charset
+java.nio.charset.spi
+java.nio.file
+java.nio.file.attribute
+java.nio.file.spi
+java.security
+java.security.acl
+java.security.cert
+java.security.interfaces
+java.security.spec
+java.text
+java.text.spi
+java.time
+java.time.chrono
+java.time.format
+java.time.temporal
+java.time.zone
+java.util
+java.util.concurrent
+java.util.concurrent.atomic
+java.util.concurrent.locks
+java.util.function
+java.util.jar
+java.util.regex
+java.util.spi
+java.util.stream
+java.util.zip
+javax.crypto
+javax.crypto.interfaces
+javax.crypto.spec
+javax.net
+javax.net.ssl
+javax.security.auth
+javax.security.auth.callback
+javax.security.auth.login
+javax.security.auth.spi
+javax.security.auth.x500
+javax.security.cert
+module:java.compiler
+javax.annotation.processing
+javax.lang.model
+javax.lang.model.element
+javax.lang.model.type
+javax.lang.model.util
+javax.tools
+module:java.corba
+javax.activity
+javax.rmi
+javax.rmi.CORBA
+org.omg.CORBA
+org.omg.CORBA_2_3
+org.omg.CORBA_2_3.portable
+org.omg.CORBA.DynAnyPackage
+org.omg.CORBA.ORBPackage
+org.omg.CORBA.portable
+org.omg.CORBA.TypeCodePackage
+org.omg.CosNaming
+org.omg.CosNaming.NamingContextExtPackage
+org.omg.CosNaming.NamingContextPackage
+org.omg.Dynamic
+org.omg.DynamicAny
+org.omg.DynamicAny.DynAnyFactoryPackage
+org.omg.DynamicAny.DynAnyPackage
+org.omg.IOP
+org.omg.IOP.CodecFactoryPackage
+org.omg.IOP.CodecPackage
+org.omg.Messaging
+org.omg.PortableInterceptor
+org.omg.PortableInterceptor.ORBInitInfoPackage
+org.omg.PortableServer
+org.omg.PortableServer.CurrentPackage
+org.omg.PortableServer.POAManagerPackage
+org.omg.PortableServer.POAPackage
+org.omg.PortableServer.portable
+org.omg.PortableServer.ServantLocatorPackage
+org.omg.SendingContext
+org.omg.stub.java.rmi
+module:java.datatransfer
+java.awt.datatransfer
+module:java.desktop
+java.applet
+java.awt
+java.awt.color
+java.awt.desktop
+java.awt.dnd
+java.awt.event
+java.awt.font
+java.awt.geom
+java.awt.im
+java.awt.im.spi
+java.awt.image
+java.awt.image.renderable
+java.awt.print
+java.beans
+java.beans.beancontext
+javax.accessibility
+javax.imageio
+javax.imageio.event
+javax.imageio.metadata
+javax.imageio.plugins.bmp
+javax.imageio.plugins.jpeg
+javax.imageio.plugins.tiff
+javax.imageio.spi
+javax.imageio.stream
+javax.print
+javax.print.attribute
+javax.print.attribute.standard
+javax.print.event
+javax.sound.midi
+javax.sound.midi.spi
+javax.sound.sampled
+javax.sound.sampled.spi
+javax.swing
+javax.swing.border
+javax.swing.colorchooser
+javax.swing.event
+javax.swing.filechooser
+javax.swing.plaf
+javax.swing.plaf.basic
+javax.swing.plaf.metal
+javax.swing.plaf.multi
+javax.swing.plaf.nimbus
+javax.swing.plaf.synth
+javax.swing.table
+javax.swing.text
+javax.swing.text.html
+javax.swing.text.html.parser
+javax.swing.text.rtf
+javax.swing.tree
+javax.swing.undo
+module:java.instrument
+java.lang.instrument
+module:java.logging
+java.util.logging
+module:java.management
+java.lang.management
+javax.management
+javax.management.loading
+javax.management.modelmbean
+javax.management.monitor
+javax.management.openmbean
+javax.management.relation
+javax.management.remote
+javax.management.timer
+module:java.management.rmi
+javax.management.remote.rmi
+module:java.naming
+javax.naming
+javax.naming.directory
+javax.naming.event
+javax.naming.ldap
+javax.naming.spi
+module:java.prefs
+java.util.prefs
+module:java.rmi
+java.rmi
+java.rmi.activation
+java.rmi.dgc
+java.rmi.registry
+java.rmi.server
+javax.rmi.ssl
+module:java.scripting
+javax.script
+module:java.se
+module:java.se.ee
+module:java.security.jgss
+javax.security.auth.kerberos
+org.ietf.jgss
+module:java.security.sasl
+javax.security.sasl
+module:java.smartcardio
+javax.smartcardio
+module:java.sql
+java.sql
+javax.sql
+javax.transaction.xa
+module:java.sql.rowset
+javax.sql.rowset
+javax.sql.rowset.serial
+javax.sql.rowset.spi
+module:java.transaction
+javax.transaction
+module:java.xml
+javax.xml
+javax.xml.catalog
+javax.xml.datatype
+javax.xml.namespace
+javax.xml.parsers
+javax.xml.stream
+javax.xml.stream.events
+javax.xml.stream.util
+javax.xml.transform
+javax.xml.transform.dom
+javax.xml.transform.sax
+javax.xml.transform.stax
+javax.xml.transform.stream
+javax.xml.validation
+javax.xml.xpath
+org.w3c.dom
+org.w3c.dom.bootstrap
+org.w3c.dom.events
+org.w3c.dom.ls
+org.w3c.dom.ranges
+org.w3c.dom.traversal
+org.w3c.dom.views
+org.xml.sax
+org.xml.sax.ext
+org.xml.sax.helpers
+module:java.xml.bind
+javax.xml.bind
+javax.xml.bind.annotation
+javax.xml.bind.annotation.adapters
+javax.xml.bind.attachment
+javax.xml.bind.helpers
+javax.xml.bind.util
+module:java.xml.crypto
+javax.xml.crypto
+javax.xml.crypto.dom
+javax.xml.crypto.dsig
+javax.xml.crypto.dsig.dom
+javax.xml.crypto.dsig.keyinfo
+javax.xml.crypto.dsig.spec
+module:java.xml.ws
+javax.jws
+javax.jws.soap
+javax.xml.soap
+javax.xml.ws
+javax.xml.ws.handler
+javax.xml.ws.handler.soap
+javax.xml.ws.http
+javax.xml.ws.soap
+javax.xml.ws.spi
+javax.xml.ws.spi.http
+javax.xml.ws.wsaddressing
+module:java.xml.ws.annotation
+javax.annotation
+module:jdk.accessibility
+com.sun.java.accessibility.util
+module:jdk.attach
+com.sun.tools.attach
+com.sun.tools.attach.spi
+module:jdk.charsets
+module:jdk.compiler
+com.sun.source.doctree
+com.sun.source.tree
+com.sun.source.util
+com.sun.tools.javac
+module:jdk.crypto.cryptoki
+module:jdk.crypto.ec
+module:jdk.dynalink
+jdk.dynalink
+jdk.dynalink.beans
+jdk.dynalink.linker
+jdk.dynalink.linker.support
+jdk.dynalink.support
+module:jdk.editpad
+module:jdk.hotspot.agent
+module:jdk.httpserver
+com.sun.net.httpserver
+com.sun.net.httpserver.spi
+module:jdk.incubator.httpclient
+jdk.incubator.http
+module:jdk.jartool
+com.sun.jarsigner
+jdk.security.jarsigner
+module:jdk.javadoc
+com.sun.javadoc
+com.sun.tools.javadoc
+jdk.javadoc.doclet
+module:jdk.jcmd
+module:jdk.jconsole
+com.sun.tools.jconsole
+module:jdk.jdeps
+module:jdk.jdi
+com.sun.jdi
+com.sun.jdi.connect
+com.sun.jdi.connect.spi
+com.sun.jdi.event
+com.sun.jdi.request
+module:jdk.jdwp.agent
+module:jdk.jfr
+jdk.jfr
+jdk.jfr.consumer
+module:jdk.jlink
+module:jdk.jshell
+jdk.jshell
+jdk.jshell.execution
+jdk.jshell.spi
+jdk.jshell.tool
+module:jdk.jsobject
+netscape.javascript
+module:jdk.jstatd
+module:jdk.localedata
+module:jdk.management
+com.sun.management
+module:jdk.management.agent
+module:jdk.management.cmm
+jdk.management.cmm
+module:jdk.management.jfr
+jdk.management.jfr
+module:jdk.management.resource
+jdk.management.resource
+module:jdk.naming.dns
+module:jdk.naming.rmi
+module:jdk.net
+jdk.net
+module:jdk.pack
+module:jdk.rmic
+module:jdk.scripting.nashorn
+jdk.nashorn.api.scripting
+jdk.nashorn.api.tree
+module:jdk.sctp
+com.sun.nio.sctp
+module:jdk.security.auth
+com.sun.security.auth
+com.sun.security.auth.callback
+com.sun.security.auth.login
+com.sun.security.auth.module
+module:jdk.security.jgss
+com.sun.security.jgss
+module:jdk.snmp
+module:jdk.xml.dom
+org.w3c.dom.css
+org.w3c.dom.html
+org.w3c.dom.stylesheets
+org.w3c.dom.xpath
+module:jdk.zipfs
--- a/test/langtools/jdk/javadoc/doclet/testModules/moduleB/module-info.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testModules/moduleB/module-info.java	Wed Dec 13 12:45:06 2017 -0800
@@ -36,6 +36,7 @@
     opens testpkgmdlB;
 
     exports testpkg2mdlB to moduleA;
+    exports testpkg3mdlB to moduleA;
 
     uses testpkgmdlB.TestClassInModuleB;
     uses testpkgmdlB.TestClass2InModuleB;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModules/moduleB/testpkg3mdlB/TestClassLinkOption.java	Wed Dec 13 12:45:06 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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 testpkg3mdlB;
+
+/**
+ * {@link java.lang.String Link to String Class}.<br>
+ * {@link java.lang Link to java.lang package}.<br>
+ * {@link java.base Link to java.base module}.
+ *
+ * @author bhavespa
+ */
+public class TestClassLinkOption {
+    public String testMethod() {
+        return "foo";
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/doclet/testTitleInHref/TestTitleInHref.java	Wed Dec 13 12:45:06 2017 -0800
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4714257
+ * @bug 4714257 8164407
  * @summary Test to make sure that the title attribute shows up in links.
  * @author jamieh
  * @library ../lib
@@ -55,7 +55,7 @@
                 "<a href=\"../pkg/Interface.html\" title=\"interface in pkg\">",
                 //Test to make sure that the title shows up in cross link shows up
                 "<a href=\"" + uri + "/java/io/File.html?is-external=true\" "
-                + "title=\"class or interface in java.io\">"
+                + "title=\"class or interface in java.io\" class=\"externalLink\">"
                 + "<code>This is a cross link to class File</code></a>");
     }
 }
--- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java	Wed Dec 13 12:45:06 2017 -0800
@@ -227,7 +227,7 @@
             "member-search-index.js",
             "member-search-index.zip",
             "overview-tree.html",
-            "package-list",
+            "element-list",
             "package-search-index.js",
             "package-search-index.zip",
             "pkg/C.html",
--- a/test/langtools/tools/javadoc/api/basic/APITest.java	Wed Dec 13 21:25:49 2017 +0100
+++ b/test/langtools/tools/javadoc/api/basic/APITest.java	Wed Dec 13 12:45:06 2017 -0800
@@ -227,7 +227,7 @@
             "member-search-index.js",
             "member-search-index.zip",
             "overview-tree.html",
-            "package-list",
+            "element-list",
             "package-search-index.js",
             "package-search-index.zip",
             "pkg/C.html",