8219313: Support module specific stylesheets
authorpmuthuswamy
Mon, 20 May 2019 14:42:32 +0530
changeset 54936 8c63164bd540
parent 54935 cb80f2adf35c
child 54937 7e5e0b326ed7
8219313: Support module specific stylesheets Reviewed-by: jjg
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java
test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java
test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Mon May 20 14:42:32 2019 +0530
@@ -43,6 +43,7 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 
 /**
  * Generate the Class Information Page.
@@ -154,9 +155,9 @@
     public void printDocument(Content contentTree) throws DocFileIOException {
         String description = getDescription("declaration", annotationType);
         PackageElement pkg = utils.containingPackage(this.annotationType);
-        Content stylesheetContent = getLocalStylesheetContent(pkg);
+        List<DocPath> localStylesheets = getLocalStylesheets(pkg);
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(annotationType),
-                description, stylesheetContent, contentTree);
+                description, localStylesheets, contentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon May 20 14:42:32 2019 +0530
@@ -55,6 +55,7 @@
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
 
 /**
@@ -185,9 +186,9 @@
     public void printDocument(Content contentTree) throws DocFileIOException {
         String description = getDescription("declaration", typeElement);
         PackageElement pkg = utils.containingPackage(typeElement);
-        Content stylesheetContent = getLocalStylesheetContent(pkg);
+        List<DocPath> localStylesheets = getLocalStylesheets(pkg);
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(typeElement),
-                description, stylesheetContent, contentTree);
+                description, localStylesheets, contentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandlerImpl.java	Mon May 20 14:42:32 2019 +0530
@@ -206,7 +206,7 @@
         footer.add(navBar.getContent(false));
         docletWriter.addBottom(footer);
         htmlContent.add(footer);
-        docletWriter.printHtmlDocument(Collections.emptyList(), null, localTagsContent, htmlContent);
+        docletWriter.printHtmlDocument(Collections.emptyList(), null, localTagsContent, Collections.emptyList(), htmlContent);
     }
 
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java	Mon May 20 14:42:32 2019 +0530
@@ -452,13 +452,17 @@
         return null;
     }
 
-    public DocFile getMainStylesheet() {
-        return stylesheetfile.isEmpty() ? null : DocFile.createFileForInput(this, stylesheetfile);
+    public DocPath getMainStylesheet() {
+        if(!stylesheetfile.isEmpty()){
+            DocFile docFile = DocFile.createFileForInput(this, stylesheetfile);
+            return DocPath.create(docFile.getName());
+        }
+        return  null;
     }
 
-    public List<DocFile> getAdditionalStylesheets() {
+    public List<DocPath> getAdditionalStylesheets() {
         return additionalStylesheets.stream()
-                .map(ssf -> DocFile.createFileForInput(this, ssf))
+                .map(ssf -> DocFile.createFileForInput(this, ssf)).map(file -> DocPath.create(file.getName()))
                 .collect(Collectors.toList());
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Mon May 20 14:42:32 2019 +0530
@@ -26,6 +26,7 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
@@ -399,7 +400,26 @@
                                   String description,
                                   Content body)
             throws DocFileIOException {
-        printHtmlDocument(metakeywords, description, new ContentBuilder(), body);
+        printHtmlDocument(metakeywords, description, new ContentBuilder(), Collections.emptyList(), body);
+    }
+
+    /**
+     * Generates the HTML document tree and prints it out.
+     *
+     * @param metakeywords Array of String keywords for META tag. Each element
+     *                     of the array is assigned to a separate META tag.
+     *                     Pass in null for no array
+     * @param description the content for the description META tag.
+     * @param localStylesheets local stylesheets to be included in the HEAD element
+     * @param body the body htmltree to be included in the document
+     * @throws DocFileIOException if there is a problem writing the file
+     */
+    public void printHtmlDocument(List<String> metakeywords,
+                                  String description,
+                                  List<DocPath> localStylesheets,
+                                  Content body)
+            throws DocFileIOException {
+        printHtmlDocument(metakeywords, description, new ContentBuilder(), localStylesheets, body);
     }
 
     /**
@@ -410,15 +430,19 @@
      *                     Pass in null for no array
      * @param description the content for the description META tag.
      * @param extraHeadContent any additional content to be included in the HEAD element
+     * @param localStylesheets local stylesheets to be included in the HEAD element
      * @param body the body htmltree to be included in the document
      * @throws DocFileIOException if there is a problem writing the file
      */
     public void printHtmlDocument(List<String> metakeywords,
                                   String description,
                                   Content extraHeadContent,
+                                  List<DocPath> localStylesheets,
                                   Content body)
             throws DocFileIOException {
         Content htmlComment = contents.newPage;
+        List<DocPath> additionalStylesheets = configuration.getAdditionalStylesheets();
+        additionalStylesheets.addAll(localStylesheets);
         Head head = new Head(path, configuration.docletVersion)
                 .setTimestamp(!configuration.notimestamp)
                 .setDescription(description)
@@ -426,7 +450,7 @@
                 .setTitle(winTitle)
                 .setCharset(configuration.charset)
                 .addKeywords(metakeywords)
-                .setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets())
+                .setStylesheets(configuration.getMainStylesheet(), additionalStylesheets)
                 .setIndex(configuration.createindex, mainBodyScript)
                 .addContent(extraHeadContent);
 
@@ -2188,8 +2212,42 @@
         return mainBodyScript;
     }
 
-    Content getLocalStylesheetContent(Element element) throws DocFileIOException {
-        Content stylesheetContent = new ContentBuilder();
+    /**
+     * Returns the path of module/package specific stylesheets for the element.
+     * @param element module/Package element
+     * @return list of path of module/package specific stylesheets
+     * @throws DocFileIOException
+     */
+    List<DocPath> getLocalStylesheets(Element element) throws DocFileIOException {
+        List<DocPath> stylesheets = new ArrayList<>();
+        DocPath basePath = null;
+        if (element instanceof PackageElement) {
+            stylesheets.addAll(getModuleStylesheets((PackageElement)element));
+            basePath = docPaths.forPackage((PackageElement)element);
+        } else if (element instanceof ModuleElement) {
+            basePath = DocPaths.forModule((ModuleElement)element);
+        }
+        for (DocPath stylesheet : getStylesheets(element)) {
+            stylesheets.add(basePath.resolve(stylesheet.getPath()));
+        }
+        return stylesheets;
+    }
+
+    private List<DocPath> getModuleStylesheets(PackageElement pkgElement) throws
+            DocFileIOException {
+        List<DocPath> moduleStylesheets = new ArrayList<>();
+        ModuleElement moduleElement = utils.containingModule(pkgElement);
+        if (moduleElement != null && !moduleElement.isUnnamed()) {
+            List<DocPath> localStylesheets = getStylesheets(moduleElement);
+            DocPath basePath = DocPaths.forModule(moduleElement);
+            for (DocPath stylesheet : localStylesheets) {
+                moduleStylesheets.add(basePath.resolve(stylesheet));
+            }
+        }
+        return moduleStylesheets;
+    }
+
+    private List<DocPath> getStylesheets(Element element) throws DocFileIOException {
         List<DocPath> localStylesheets = configuration.localStylesheetMap.get(element);
         if (localStylesheets == null) {
             DocFilesHandlerImpl docFilesHandler = (DocFilesHandlerImpl)configuration
@@ -2197,11 +2255,7 @@
             localStylesheets = docFilesHandler.getStylesheets();
             configuration.localStylesheetMap.put(element, localStylesheets);
         }
-        for (DocPath stylesheet : localStylesheets) {
-            stylesheetContent.add(HtmlTree.LINK("stylesheet",
-                    "text/css", stylesheet.getPath(), "Style"));
-        }
-        return stylesheetContent;
+        return localStylesheets;
     }
 
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Mon May 20 14:42:32 2019 +0530
@@ -902,8 +902,7 @@
     @Override
     public void printDocument(Content contentTree) throws DocFileIOException {
         printHtmlDocument(configuration.metakeywords.getMetaKeywordsForModule(mdle),
-                getDescription("declaration", mdle),
-                contentTree);
+                getDescription("declaration", mdle), getLocalStylesheets(mdle), contentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java	Mon May 20 14:42:32 2019 +0530
@@ -47,6 +47,7 @@
 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 
 /**
@@ -317,9 +318,9 @@
     @Override
     public void printDocument(Content contentTree) throws DocFileIOException {
         String description = getDescription("declaration", packageElement);
-        Content stylesheetContent = getLocalStylesheetContent(packageElement);
+        List<DocPath> localStylesheets = getLocalStylesheets(packageElement);
         printHtmlDocument(configuration.metakeywords.getMetaKeywords(packageElement),
-                description, stylesheetContent, contentTree);
+                description, localStylesheets, contentTree);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java	Mon May 20 14:42:32 2019 +0530
@@ -59,8 +59,8 @@
     private String description;
     private String generator;
     private boolean showTimestamp;
-    private DocFile mainStylesheetFile;
-    private List<DocFile> additionalStylesheetFiles = Collections.emptyList();
+    private DocPath mainStylesheet;
+    private List<DocPath> additionalStylesheets = Collections.emptyList();
     private boolean index;
     private Script mainBodyScript;
     private final List<Script> scripts;
@@ -157,14 +157,16 @@
 
     /**
      * Sets the main and any additional stylesheets to be listed in the HEAD element.
+     * The paths for the stylesheets must be relative to the root of the generated
+     * documentation hierarchy.
      *
      * @param main the main stylesheet, or null to use the default
      * @param additional a list of any additional stylesheets to be included
      * @return  this object
      */
-    public Head setStylesheets(DocFile main, List<DocFile> additional) {
-        this.mainStylesheetFile = main;
-        this.additionalStylesheetFiles = additional;
+    public Head setStylesheets(DocPath main, List<DocPath> additional) {
+        this.mainStylesheet = main;
+        this.additionalStylesheets = additional;
         return this;
     }
 
@@ -286,16 +288,13 @@
     }
 
     private void addStylesheets(HtmlTree tree) {
-        DocPath mainStylesheet;
-        if (mainStylesheetFile == null) {
+        if (mainStylesheet == null) {
             mainStylesheet = DocPaths.STYLESHEET;
-        } else {
-            mainStylesheet = DocPath.create(mainStylesheetFile.getName());
         }
         addStylesheet(tree, mainStylesheet);
 
-        for (DocFile file : additionalStylesheetFiles) {
-            addStylesheet(tree, DocPath.create(file.getName()));
+        for (DocPath path : additionalStylesheets) {
+            addStylesheet(tree, path);
         }
 
         if (index) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Sun May 19 22:14:09 2019 +0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Mon May 20 14:42:32 2019 +0530
@@ -28,6 +28,7 @@
 import javax.lang.model.element.ModuleElement;
 
 import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
 
@@ -116,9 +117,8 @@
 
         moduleWriter.addModuleFooter(contentTree);
         moduleWriter.printDocument(contentTree);
-        // uncomment to support doc-files in modules
-        // DocFilesHandler docFilesHandler = configuration.getWriterFactory().getDocFilesWriter(mdle);
-        // docFilesHandler.copyDocFiles();
+        DocFilesHandler docFilesHandler = configuration.getWriterFactory().getDocFilesHandler(mdle);
+        docFilesHandler.copyDocFiles();
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testModuleSpecificStylesheet/TestModuleSpecificStylesheet.java	Mon May 20 14:42:32 2019 +0530
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019, 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 8219313
+ * @summary Support module specific stylesheets
+ * @library /tools/lib ../../lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.javadoc/jdk.javadoc.internal.tool
+ * @build javadoc.tester.* toolbox.ToolBox
+ * @run main TestModuleSpecificStylesheet
+ */
+
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import toolbox.ModuleBuilder;
+import toolbox.ToolBox;
+
+import javadoc.tester.JavadocTester;
+
+public class TestModuleSpecificStylesheet extends JavadocTester {
+
+    final ToolBox tb;
+
+    public static void main(String... args) throws Exception {
+        TestModuleSpecificStylesheet tester = new TestModuleSpecificStylesheet();
+        tester.runTests(m -> new Object[]{Paths.get(m.getName())});
+    }
+
+    TestModuleSpecificStylesheet() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    public void test(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        Path outDir = base.resolve("out");
+
+        new ModuleBuilder(tb, "ma")
+                .classes("package pa; public class A{}")
+                .classes("package pa.pb; public class B{}")
+                .exports("pa")
+                .exports("pa.pb")
+                .write(srcDir);
+
+        Path docFilesDir = Files.createDirectories(srcDir.resolve("ma").resolve("doc-files"));
+        Path stylesheet = docFilesDir.resolve("spanstyle.css");
+        Files.createFile(stylesheet);
+        Files.write(stylesheet, List.of("span{ color:blue; }"));
+
+        javadoc("-d", outDir.toString(),
+                "--module-source-path", srcDir.toString(),
+                "--module", "ma");
+
+        checkExit(Exit.OK);
+
+        checkOutput("ma/module-summary.html", true,
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../ma/doc-files/spanstyle.css\"" +
+                        " title=\"Style\">");
+
+        checkOutput("ma/pa/package-summary.html", true,
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../ma/doc-files/spanstyle.css\"" +
+                        " title=\"Style\">");
+
+        checkOutput("ma/pa/A.html", true,
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../ma/doc-files/spanstyle.css\"" +
+                        " title=\"Style\">");
+
+        checkOutput("ma/pa/pb/B.html", true,
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../../ma/doc-files/spanstyle.css\"" +
+                        " title=\"Style\">");
+
+        checkOutput("ma/pa/pb/package-summary.html", true,
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../../../ma/doc-files/spanstyle.css\"" +
+                        " title=\"Style\">");
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java	Sun May 19 22:14:09 2019 +0800
+++ b/test/langtools/jdk/javadoc/doclet/testPackageSpecificStylesheet/TestPackageSpecificStylesheet.java	Mon May 20 14:42:32 2019 +0530
@@ -81,15 +81,15 @@
         checkExit(Exit.OK);
 
         checkOutput("pkg/A.html", true,
-                "<link rel=\"stylesheet\" type=\"text/css\" href=\"doc-files/spanstyle.css\"" +
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../pkg/doc-files/spanstyle.css\"" +
                         " title=\"Style\">");
 
         checkOutput("pkg/package-summary.html", true,
-                "<link rel=\"stylesheet\" type=\"text/css\" href=\"doc-files/spanstyle.css\"" +
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../pkg/doc-files/spanstyle.css\"" +
                         " title=\"Style\">");
 
         checkOutput("pkg2/B.html", false,
-                "<link rel=\"stylesheet\" type=\"text/css\" href=\"doc-files/spanstyle.css\"" +
+                "<link rel=\"stylesheet\" type=\"text/css\" href=\"../pkg2/doc-files/spanstyle.css\"" +
                         " title=\"Style\">");
 
     }