package jdk.javadoc.internal.doclets.formats.html;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.EndElementTree;
import com.sun.source.doctree.StartElementTree;
import com.sun.source.util.DocTreeFactory;
import com.sun.tools.doclint.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
import jdk.javadoc.internal.doclets.toolkit.DocFilesHandler;
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
public class DocFilesHandlerImpl implements DocFilesHandler {
public final Element element;
public final Location location;
public final DocPath source;
public final HtmlConfiguration configuration;
private final HtmlOptions options;
private Navigation navBar;
public DocFilesHandlerImpl(HtmlConfiguration configuration, Element element) {
this.configuration = configuration;
this.options = configuration.getOptions();
this.element = element;
switch (element.getKind()) {
case MODULE:
ModuleElement mdle = (ModuleElement)element;
location = configuration.utils.getLocationForModule(mdle);
source = DocPaths.DOC_FILES;
break;
case PACKAGE:
PackageElement pkg = (PackageElement)element;
location = configuration.utils.getLocationForPackage(pkg);
source = DocPath.create(pkg.getQualifiedName().toString().replace('.', '/'))
.resolve(DocPaths.DOC_FILES);
break;
default:
throw new AssertionError("unsupported element " + element);
}
}
@Override
public void copyDocFiles() throws DocFileIOException {
boolean first = true;
for (DocFile srcdir : DocFile.list(configuration, location, source)) {
if (!srcdir.isDirectory()) {
continue;
}
DocPath path = null;
switch (this.element.getKind()) {
case MODULE:
path = DocPaths.forModule((ModuleElement)this.element);
break;
case PACKAGE:
path = configuration.docPaths.forPackage((PackageElement)this.element);
break;
default:
throw new AssertionError("unknown kind:" + this.element.getKind());
}
copyDirectory(srcdir, path.resolve(DocPaths.DOC_FILES), first);
first = false;
}
}
@Override
public List<DocPath> getStylesheets() throws DocFileIOException {
List<DocPath> stylesheets = new ArrayList<DocPath>();
for (DocFile srcdir : DocFile.list(configuration, location, source)) {
for (DocFile srcFile : srcdir.list()) {
if (srcFile.getName().endsWith(".css"))
stylesheets.add(DocPaths.DOC_FILES.resolve(srcFile.getName()));
}
}
return stylesheets;
}
private void copyDirectory(DocFile srcdir, final DocPath dstDocPath,
boolean first) throws DocFileIOException {
DocFile dstdir = DocFile.createFileForOutput(configuration, dstDocPath);
if (srcdir.isSameFile(dstdir)) {
return;
}
for (DocFile srcfile: srcdir.list()) {
if (!isValidFilename(srcfile)) {
configuration.messages.warning("doclet.Copy_Ignored_warning",
srcfile.getPath());
continue;
}
DocFile destfile = dstdir.resolve(srcfile.getName());
if (srcfile.isFile()) {
if (destfile.exists() && !first) {
configuration.messages.warning("doclet.Copy_Overwrite_warning",
srcfile.getPath(), dstdir.getPath());
} else {
if (Utils.toLowerCase(srcfile.getPath()).endsWith(".html")) {
handleHtmlFile(srcfile, dstDocPath);
} else {
configuration.messages.notice("doclet.Copying_File_0_To_Dir_1",
srcfile.getPath(), dstdir.getPath());
destfile.copyFile(srcfile);
}
}
} else if (srcfile.isDirectory()) {
if (options.copyDocfileSubdirs()
&& !configuration.shouldExcludeDocFileDir(srcfile.getName())) {
DocPath dirDocPath = dstDocPath.resolve(srcfile.getName());
copyDirectory(srcfile, dirDocPath, first);
}
}
}
}
private boolean isValidFilename(DocFile f) {
try {
String n = f.getName();
URI u = new URI(n);
return u.getPath().equals(n);
} catch (URISyntaxException e) {
return false;
}
}
private void handleHtmlFile(DocFile srcfile, DocPath dstPath) throws DocFileIOException {
Utils utils = configuration.utils;
FileObject fileObject = srcfile.getFileObject();
DocFileElement dfElement = new DocFileElement(utils, element, fileObject);
DocPath dfilePath = dstPath.resolve(srcfile.getName());
HtmlDocletWriter docletWriter = new DocFileWriter(configuration, dfilePath, element);
configuration.messages.notice("doclet.Generating_0", docletWriter.filename.getPath());
List<? extends DocTree> localTags = getLocalHeaderTags(utils.getPreamble(dfElement));
Content localTagsContent = docletWriter.commentTagsToContent(null, dfElement, localTags, false);
String title = getWindowTitle(docletWriter, dfElement).trim();
HtmlTree htmlContent = docletWriter.getBody(title);
PackageElement pkg = dfElement.getPackageElement();
this.navBar = new Navigation(element, configuration, PageMode.DOC_FILE, docletWriter.path);
Content headerContent = new ContentBuilder();
docletWriter.addTop(headerContent);
Content mdleLinkContent = docletWriter.getModuleLink(utils.elementUtils.getModuleOf(pkg),
docletWriter.contents.moduleLabel);
navBar.setNavLinkModule(mdleLinkContent);
Content pkgLinkContent = docletWriter.getPackageLink(pkg, docletWriter.contents.packageLabel);
navBar.setNavLinkPackage(pkgLinkContent);
navBar.setUserHeader(docletWriter.getUserHeaderFooter(true));
headerContent.add(navBar.getContent(Navigation.Position.TOP));
List<? extends DocTree> fullBody = utils.getFullBody(dfElement);
Content pageContent = docletWriter.commentTagsToContent(null, dfElement, fullBody, false);
docletWriter.addTagsInfo(dfElement, pageContent);
navBar.setUserFooter(docletWriter.getUserHeaderFooter(false));
Content footer = HtmlTree.FOOTER();
footer.add(navBar.getContent(Navigation.Position.BOTTOM));
docletWriter.addBottom(footer);
htmlContent.add(new BodyContents()
.setHeader(headerContent)
.addMainContent(pageContent)
.setFooter(footer));
docletWriter.printHtmlDocument(Collections.emptyList(), null, localTagsContent, Collections.emptyList(), htmlContent);
}
private List<? extends DocTree> getLocalHeaderTags(List<? extends DocTree> dtrees) {
List<DocTree> localTags = new ArrayList<>();
DocTreeFactory docTreeFactory = configuration.docEnv.getDocTrees().getDocTreeFactory();
boolean inHead = false;
boolean inTitle = false;
loop:
for (DocTree dt : dtrees) {
switch (dt.getKind()) {
case START_ELEMENT:
StartElementTree startElem = (StartElementTree)dt;
switch (HtmlTag.get(startElem.getName())) {
case HEAD:
inHead = true;
break;
case META:
break;
case TITLE:
inTitle = true;
break;
default:
if (inHead) {
localTags.add(startElem);
localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
}
}
break;
case END_ELEMENT:
EndElementTree endElem = (EndElementTree)dt;
switch (HtmlTag.get(endElem.getName())) {
case HEAD:
inHead = false;
break loop;
case TITLE:
inTitle = false;
break;
default:
if (inHead) {
localTags.add(endElem);
localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
}
}
break;
case ENTITY:
case TEXT:
if (inHead && !inTitle) {
localTags.add(dt);
}
break;
}
}
return localTags;
}
private String getWindowTitle(HtmlDocletWriter docletWriter, Element element) {
String t = configuration.utils.getHTMLTitle(element);
return docletWriter.getWindowTitle(t);
}
private static class DocFileWriter extends HtmlDocletWriter {
public DocFileWriter(HtmlConfiguration configuration, DocPath path, Element e) {
super(configuration, path);
switch (e.getKind()) {
case PACKAGE:
case MODULE:
break;
default:
throw new AssertionError("unsupported element: " + e.getKind());
}
}
}
}