Mercurial > hg > icedtea8-forest > langtools
changeset 3393:26a274d91ee6 icedtea-3.3.0pre02
Merge jdk8u121-b13
author | andrew |
---|---|
date | Mon, 23 Jan 2017 16:30:40 +0000 |
parents | fcc9b17c0dc1 (current diff) f634736433d9 (diff) |
children | d10a13bdc98c |
files | .hgtags |
diffstat | 22 files changed, 1616 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Jan 13 17:09:30 2017 +0000 +++ b/.hgtags Mon Jan 23 16:30:40 2017 +0000 @@ -655,6 +655,10 @@ 5665ca5e1896dcf47faa2c5c50d1130b8b783944 icedtea-3.2.0pre03 0549bf2f507dae59bfcd7d11e038cdc62376fee7 jdk8u102-b14 d86027f25a9aa960d69cf3a524588a873ae888f5 jdk8u102-b31 +1b511d4e93e7128ccb7100110ab6604eb2838afa jdk8u102-b32 +3d4b72198b23108f93ccf36b8d9275cc3b40ee1e jdk8u102-b33 +8bde2f8474d372de6a3425affd38de506aa56a51 jdk8u102-b34 +e64f16f8a585332086127b4f24b79e6c83bee530 jdk8u102-b35 90f493bfe1faca0573844fdd2497070c8b224d76 jdk8u111-b00 085fd7e08f4855f134a8048251c4535ddde1feee jdk8u111-b01 f66a535fb6b3b41419c987cc90407507a64712b2 jdk8u111-b02 @@ -686,4 +690,19 @@ 04d857308b8c3db33e8fd4099c3a3dd5d50cdaeb jdk8u112-b13 b353281f73db9617d993353e468342d3420c29f1 jdk8u112-b14 6116c6644be0c85556931aaeb9b4f2dbc9c79157 jdk8u112-b15 +ee37eafc48cb6fb20cb6c1e31cfecfe1ccc800da jdk8u112-b16 3ab9841babb7f624ae830024e42e75344a4fed5a icedtea-3.3.0pre01 +de1c3df992adb0c704005583210d1ed6dac758cd jdk8u112-b31 +5710d574a99aeff3600c49a4aed34fa1b373f7b8 jdk8u121-b00 +ab5d32d8cf5f6d81482692f801385a869b2d83c1 jdk8u121-b01 +e260d46661d2da3ede78aae434d5420acce99950 jdk8u121-b02 +0acfd50d67d98259a25fbd51129b763bab56d068 jdk8u121-b03 +29a08aff06088cad98dafddef7628b51e324fcae jdk8u121-b04 +a933635275c33e37c9403767d600a12b9ee71df7 jdk8u121-b05 +dc1dd2e6cf8e094c4a8437d54ebc7bac1f7ab964 jdk8u121-b06 +6cd0cd4078e9ec8ad9fa167cabf9c671ed21fc66 jdk8u121-b07 +8efc10efbfe137ed5de6bf55875fdafd25bb6a1b jdk8u121-b08 +57a26fe61f2b435332c0697e92965a22246cd143 jdk8u121-b09 +53c94a674d6076ff390c62a7682ea0e87a893cdc jdk8u121-b10 +b634abfcd98fb8b201da9208e398ea17cabd2b32 jdk8u121-b11 +7fc347da372c8c4e5530a7fa32084b5dbc4ee8b6 jdk8u121-b12
--- a/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -38,6 +38,7 @@ import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.StringUtils; +import com.sun.tools.javadoc.JavaScriptScanner; import com.sun.tools.javadoc.RootDocImpl; /** @@ -181,6 +182,11 @@ public Set<String> doclintOpts = new LinkedHashSet<String>(); /** + * Whether or not to check for JavaScript in doc comments. + */ + private boolean allowScriptInComments; + + /** * Unique Resource Handler for this package. */ public final MessageRetriever standardmessage; @@ -283,8 +289,11 @@ doclintOpts.add(null); } else if (opt.startsWith("-xdoclint:")) { doclintOpts.add(opt.substring(opt.indexOf(":") + 1)); + } else if (opt.equals("--allow-script-in-comments")) { + allowScriptInComments = true; } } + if (root.specifiedClasses().length > 0) { Map<String,PackageDoc> map = new HashMap<String,PackageDoc>(); PackageDoc pd; @@ -301,9 +310,30 @@ if (root instanceof RootDocImpl) { ((RootDocImpl) root).initDocLint(doclintOpts, tagletManager.getCustomTagNames()); + JavaScriptScanner jss = ((RootDocImpl) root).initJavaScriptScanner(isAllowScriptInComments()); + if (jss != null) { + // In a more object-oriented world, this would be done by methods on the Option objects. + // Note that -windowtitle silently removes any and all HTML elements, and so does not need + // to be handled here. + checkJavaScript(jss, "-header", header); + checkJavaScript(jss, "-footer", footer); + checkJavaScript(jss, "-top", top); + checkJavaScript(jss, "-bottom", bottom); + checkJavaScript(jss, "-doctitle", doctitle); + checkJavaScript(jss, "-packagesheader", packagesheader); + } } } + private void checkJavaScript(JavaScriptScanner jss, final String opt, String value) { + jss.parse(value, new JavaScriptScanner.Reporter() { + public void report() { + root.printError(getText("doclet.JavaScript_in_option", opt)); + throw new FatalError(); + } + }); + } + /** * Returns the "length" of a given option. If an option takes no * arguments, its length is one. If it takes one argument, it's @@ -337,7 +367,8 @@ option.equals("-nonavbar") || option.equals("-nooverview") || option.equals("-xdoclint") || - option.startsWith("-xdoclint:")) { + option.startsWith("-xdoclint:") || + option.equals("--allow-script-in-comments")) { return 1; } else if (option.equals("-help")) { // Uugh: first, this should not be hidden inside optionLength, @@ -595,4 +626,13 @@ public Content newContent() { return new ContentBuilder(); } + + /** + * Returns whether or not to allow JavaScript in comments. + * Default is off; can be set true from a command line option. + * @return the allowScriptInComments + */ + public boolean isAllowScriptInComments() { + return allowScriptInComments; + } }
--- a/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -190,6 +190,8 @@ } } catch (IOException e) { throw new DocletAbortException(e); + } catch (FatalError fe) { + throw fe; } catch (DocletAbortException de) { throw de; } catch (Exception e) {
--- a/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -164,7 +164,9 @@ public final Content descfrmInterfaceLabel; - private final Writer writer; + private final DocFile file; + + private Writer writer; private Content script; @@ -180,7 +182,7 @@ */ public HtmlWriter(Configuration configuration, DocPath path) throws IOException, UnsupportedEncodingException { - writer = DocFile.createFileForOutput(configuration, path).openWriter(); + file = DocFile.createFileForOutput(configuration, path); this.configuration = configuration; this.memberDetailsListPrinted = false; profileTableHeader = new String[] { @@ -239,6 +241,7 @@ } public void write(Content c) throws IOException { + writer = file.openWriter(); c.write(writer, true); }
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -83,6 +83,8 @@ } catch (Configuration.Fault f) { root.printError(f.getMessage()); return false; + } catch (FatalError fe) { + return false; } catch (DocletAbortException e) { Throwable cause = e.getCause(); if (cause != null) {
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, 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 @@ -140,7 +140,14 @@ configuration.root.printError("Unknown element: " + component); throw new DocletAbortException(e); } catch (InvocationTargetException e) { - throw new DocletAbortException(e.getCause()); + Throwable cause = e.getCause(); + if (cause instanceof FatalError) { + throw (FatalError) cause; + } else if (cause instanceof DocletAbortException) { + throw (DocletAbortException) cause; + } else { + throw new DocletAbortException(cause); + } } catch (Exception e) { e.printStackTrace(); configuration.root.printError("Exception " +
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Mon Jan 23 16:30:40 2017 +0000 @@ -29,6 +29,8 @@ doclet.Building_Tree=Building tree for all the packages and classes... doclet.Building_Index=Building index for all the packages and classes... doclet.Building_Index_For_All_Classes=Building index for all classes... +doclet.JavaScript_in_option=Argument for {0} contains JavaScript.\n\ +Use --allow-script-in-comments to allow use of JavaScript. doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0. doclet.Packages=Packages doclet.Profiles=Profiles
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties Mon Jan 23 16:30:40 2017 +0000 @@ -27,6 +27,7 @@ doclet.Building_Tree=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u968E\u5C64\u30C4\u30EA\u30FC\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059... doclet.Building_Index=\u5168\u30D1\u30C3\u30B1\u30FC\u30B8\u3068\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059... doclet.Building_Index_For_All_Classes=\u5168\u30AF\u30E9\u30B9\u306E\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059... +doclet.JavaScript_in_option={0}\u306E\u5F15\u6570\u306BJavaScript\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002 doclet.sourcetab_warning=-sourcetab\u306E\u5F15\u6570\u306F0\u3088\u308A\u5927\u304D\u3044\u6574\u6570\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 doclet.Packages=\u30D1\u30C3\u30B1\u30FC\u30B8 doclet.Profiles=\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB
--- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties Mon Jan 23 16:30:40 2017 +0000 @@ -27,6 +27,7 @@ doclet.Building_Tree=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u6811... doclet.Building_Index=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u7D22\u5F15... doclet.Building_Index_For_All_Classes=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7C7B\u7684\u7D22\u5F15... +doclet.JavaScript_in_option={0} \u7684\u53C2\u6570\u5305\u542B JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002 doclet.sourcetab_warning=-sourcetab \u7684\u53C2\u6570\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002 doclet.Packages=\u7A0B\u5E8F\u5305 doclet.Profiles=\u914D\u7F6E\u6587\u4EF6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java Mon Jan 23 16:30:40 2017 +0000 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.doclets.internal.toolkit.util; + +/** + * <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> + */ +@Deprecated +public class FatalError extends Error { + private static final long serialVersionUID = -9131058909576418984L; + + public FatalError() { } +}
--- a/src/share/classes/com/sun/tools/doclint/Checker.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclint/Checker.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, 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 @@ -126,7 +126,7 @@ } } - private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well + private final Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well private HtmlTag currHeaderTag; private final int implicitHeaderLevel; @@ -401,7 +401,16 @@ break; case OTHER: - env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName); + switch (t) { + case SCRIPT: + // <script> may or may not be allowed, depending on --allow-script-in-comments + // but we allow it here, and rely on a separate scanner to detect all uses + // of JavaScript, including <script> tags, and use in attributes, etc. + break; + + default: + env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName); + } return; } @@ -519,22 +528,27 @@ if (!first) env.messages.error(HTML, tree, "dc.attr.repeated", name); } - AttrKind k = currTag.getAttrKind(name); - switch (k) { - case OK: - break; + + // for now, doclint allows all attribute names beginning with "on" as event handler names, + // without checking the validity or applicability of the name + if (!name.toString().startsWith("on")) { + AttrKind k = currTag.getAttrKind(name); + switch (k) { + case OK: + break; - case INVALID: - env.messages.error(HTML, tree, "dc.attr.unknown", name); - break; + case INVALID: + env.messages.error(HTML, tree, "dc.attr.unknown", name); + break; - case OBSOLETE: - env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name); - break; + case OBSOLETE: + env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name); + break; - case USE_CSS: - env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name); - break; + case USE_CSS: + env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name); + break; + } } if (attr != null) { @@ -643,6 +657,9 @@ } private void checkURI(AttributeTree tree, String uri) { + // allow URIs beginning with javascript:, which would otherwise be rejected by the URI API. + if (uri.startsWith("javascript:")) + return; try { URI u = new URI(uri); } catch (URISyntaxException e) {
--- a/src/share/classes/com/sun/tools/doclint/HtmlTag.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/doclint/HtmlTag.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, 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 @@ -183,7 +183,8 @@ } }, - SCRIPT(BlockType.OTHER, EndKind.REQUIRED), + SCRIPT(BlockType.OTHER, EndKind.REQUIRED, + attrs(AttrKind.OK, SRC)), SMALL(BlockType.INLINE, EndKind.REQUIRED, EnumSet.of(Flag.EXPECT_CONTENT)),
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, 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 @@ -585,7 +585,7 @@ /** * Ident = IDENTIFIER */ - Name ident() { + public Name ident() { if (token.kind == IDENTIFIER) { Name name = token.name(); nextToken();
--- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, 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 @@ -86,7 +86,7 @@ JavadocEnter enter; /** The name table. */ - Names names; + private final Names names; /** The encoding name. */ private String encoding; @@ -109,6 +109,7 @@ JavaFileManager fileManager; Context context; DocLint doclint; + JavaScriptScanner javaScriptScanner; WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>(); @@ -834,6 +835,15 @@ doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); } + JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) { + if (allowScriptInComments) { + javaScriptScanner = null; + } else { + javaScriptScanner = new JavaScriptScanner(); + } + return javaScriptScanner; + } + boolean showTagMessages() { return (doclint == null); }
--- a/src/share/classes/com/sun/tools/javadoc/DocImpl.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/DocImpl.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -36,6 +36,7 @@ import com.sun.javadoc.*; import com.sun.source.util.TreePath; +import com.sun.tools.doclets.internal.toolkit.util.FatalError; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Position; @@ -127,6 +128,15 @@ Comment comment() { if (comment == null) { String d = documentation(); + if (env.javaScriptScanner != null) { + env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() { + @Override + public void report() { + env.error(DocImpl.this, "javadoc.JavaScript_in_comment"); + throw new FatalError(); + } + }); + } if (env.doclint != null && treePath != null && d.equals(getCommentText(treePath))) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java Mon Jan 23 16:30:40 2017 +0000 @@ -0,0 +1,1103 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javadoc; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import com.sun.tools.javadoc.JavaScriptScanner.TagParser.Kind; + +import static com.sun.tools.javac.util.LayoutCharacters.EOI; + +/** + * Parser to detect use of JavaScript in documentation comments. + */ +@Deprecated +public class JavaScriptScanner { + public static interface Reporter { + void report(); + } + + static class ParseException extends Exception { + private static final long serialVersionUID = 0; + ParseException(String key) { + super(key); + } + } + + private Reporter reporter; + + /** The input buffer, index of most recent character read, + * index of one past last character in buffer. + */ + protected char[] buf; + protected int bp; + protected int buflen; + + /** The current character. + */ + protected char ch; + + private boolean newline = true; + + Map<String, TagParser> tagParsers; + Set<String> eventAttrs; + Set<String> uriAttrs; + + public JavaScriptScanner() { + initTagParsers(); + initEventAttrs(); + initURIAttrs(); + } + + public void parse(String comment, Reporter r) { + reporter = r; + String c = comment; + buf = new char[c.length() + 1]; + c.getChars(0, c.length(), buf, 0); + buf[buf.length - 1] = EOI; + buflen = buf.length - 1; + bp = -1; + newline = true; + nextChar(); + + blockContent(); + blockTags(); + } + + private void checkHtmlTag(String tag) { + if (tag.equalsIgnoreCase("script")) { + reporter.report(); + } + } + + private void checkHtmlAttr(String name, String value) { + String n = name.toLowerCase(Locale.ENGLISH); + if (eventAttrs.contains(n) + || uriAttrs.contains(n) + && value != null && value.toLowerCase(Locale.ENGLISH).trim().startsWith("javascript:")) { + reporter.report(); + } + } + + void nextChar() { + ch = buf[bp < buflen ? ++bp : buflen]; + switch (ch) { + case '\f': case '\n': case '\r': + newline = true; + } + } + + /** + * Read block content, consisting of text, html and inline tags. + * Terminated by the end of input, or the beginning of the next block tag: + * i.e. @ as the first non-whitespace character on a line. + */ + @SuppressWarnings("fallthrough") + protected void blockContent() { + + loop: + while (bp < buflen) { + switch (ch) { + case '\n': case '\r': case '\f': + newline = true; + // fallthrough + + case ' ': case '\t': + nextChar(); + break; + + case '&': + entity(null); + break; + + case '<': + html(); + break; + + case '>': + newline = false; + nextChar(); + break; + + case '{': + inlineTag(null); + break; + + case '@': + if (newline) { + break loop; + } + // fallthrough + + default: + newline = false; + nextChar(); + } + } + } + + /** + * Read a series of block tags, including their content. + * Standard tags parse their content appropriately. + * Non-standard tags are represented by {@link UnknownBlockTag}. + */ + protected void blockTags() { + while (ch == '@') + blockTag(); + } + + /** + * Read a single block tag, including its content. + * Standard tags parse their content appropriately. + * Non-standard tags are represented by {@link UnknownBlockTag}. + */ + protected void blockTag() { + int p = bp; + try { + nextChar(); + if (isIdentifierStart(ch)) { + String name = readTagName(); + TagParser tp = tagParsers.get(name); + if (tp == null) { + blockContent(); + } else { + switch (tp.getKind()) { + case BLOCK: + tp.parse(p); + return; + case INLINE: + return; + } + } + } + blockContent(); + } catch (ParseException e) { + blockContent(); + } + } + + protected void inlineTag(Void list) { + newline = false; + nextChar(); + if (ch == '@') { + inlineTag(); + } + } + + /** + * Read a single inline tag, including its content. + * Standard tags parse their content appropriately. + * Non-standard tags are represented by {@link UnknownBlockTag}. + * Malformed tags may be returned as {@link Erroneous}. + */ + protected void inlineTag() { + int p = bp - 1; + try { + nextChar(); + if (isIdentifierStart(ch)) { + String name = readTagName(); + TagParser tp = tagParsers.get(name); + + if (tp == null) { + skipWhitespace(); + inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); + nextChar(); + } else { + skipWhitespace(); + if (tp.getKind() == TagParser.Kind.INLINE) { + tp.parse(p); + } else { // handle block tags (ex: @see) in inline content + inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip content + nextChar(); + } + } + } + } catch (ParseException e) { + } + } + + private static enum WhitespaceRetentionPolicy { + RETAIN_ALL, + REMOVE_FIRST_SPACE, + REMOVE_ALL + } + + /** + * Read plain text content of an inline tag. + * Matching pairs of { } are skipped; the text is terminated by the first + * unmatched }. It is an error if the beginning of the next tag is detected. + */ + private void inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException { + switch (whitespacePolicy) { + case REMOVE_ALL: + skipWhitespace(); + break; + case REMOVE_FIRST_SPACE: + if (ch == ' ') + nextChar(); + break; + case RETAIN_ALL: + default: + // do nothing + break; + + } + int pos = bp; + int depth = 1; + + loop: + while (bp < buflen) { + switch (ch) { + case '\n': case '\r': case '\f': + newline = true; + break; + + case ' ': case '\t': + break; + + case '{': + newline = false; + depth++; + break; + + case '}': + if (--depth == 0) { + return; + } + newline = false; + break; + + case '@': + if (newline) + break loop; + newline = false; + break; + + default: + newline = false; + break; + } + nextChar(); + } + throw new ParseException("dc.unterminated.inline.tag"); + } + + /** + * Read Java class name, possibly followed by member + * Matching pairs of {@literal < >} are skipped. The text is terminated by the first + * unmatched }. It is an error if the beginning of the next tag is detected. + */ + // TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE + // TODO: improve quality of parse to forbid bad constructions. + // TODO: update to use ReferenceParser + @SuppressWarnings("fallthrough") + protected void reference(boolean allowMember) throws ParseException { + int pos = bp; + int depth = 0; + + // scan to find the end of the signature, by looking for the first + // whitespace not enclosed in () or <>, or the end of the tag + loop: + while (bp < buflen) { + switch (ch) { + case '\n': case '\r': case '\f': + newline = true; + // fallthrough + + case ' ': case '\t': + if (depth == 0) + break loop; + break; + + case '(': + case '<': + newline = false; + depth++; + break; + + case ')': + case '>': + newline = false; + --depth; + break; + + case '}': + if (bp == pos) + return; + newline = false; + break loop; + + case '@': + if (newline) + break loop; + // fallthrough + + default: + newline = false; + + } + nextChar(); + } + + if (depth != 0) + throw new ParseException("dc.unterminated.signature"); + } + + /** + * Read Java identifier + * Matching pairs of { } are skipped; the text is terminated by the first + * unmatched }. It is an error if the beginning of the next tag is detected. + */ + @SuppressWarnings("fallthrough") + protected void identifier() throws ParseException { + skipWhitespace(); + int pos = bp; + + if (isJavaIdentifierStart(ch)) { + readJavaIdentifier(); + return; + } + + throw new ParseException("dc.identifier.expected"); + } + + /** + * Read a quoted string. + * It is an error if the beginning of the next tag is detected. + */ + @SuppressWarnings("fallthrough") + protected void quotedString() { + int pos = bp; + nextChar(); + + loop: + while (bp < buflen) { + switch (ch) { + case '\n': case '\r': case '\f': + newline = true; + break; + + case ' ': case '\t': + break; + + case '"': + nextChar(); + // trim trailing white-space? + return; + + case '@': + if (newline) + break loop; + + } + nextChar(); + } + } + + /** + * Read a term ie. one word. + * It is an error if the beginning of the next tag is detected. + */ + @SuppressWarnings("fallthrough") + protected void inlineWord() { + int pos = bp; + int depth = 0; + loop: + while (bp < buflen) { + switch (ch) { + case '\n': + newline = true; + // fallthrough + + case '\r': case '\f': case ' ': case '\t': + return; + + case '@': + if (newline) + break loop; + + case '{': + depth++; + break; + + case '}': + if (depth == 0 || --depth == 0) + return; + break; + } + newline = false; + nextChar(); + } + } + + /** + * Read general text content of an inline tag, including HTML entities and elements. + * Matching pairs of { } are skipped; the text is terminated by the first + * unmatched }. It is an error if the beginning of the next tag is detected. + */ + @SuppressWarnings("fallthrough") + private void inlineContent() { + + skipWhitespace(); + int pos = bp; + int depth = 1; + + loop: + while (bp < buflen) { + + switch (ch) { + case '\n': case '\r': case '\f': + newline = true; + // fall through + + case ' ': case '\t': + nextChar(); + break; + + case '&': + entity(null); + break; + + case '<': + newline = false; + html(); + break; + + case '{': + newline = false; + depth++; + nextChar(); + break; + + case '}': + newline = false; + if (--depth == 0) { + nextChar(); + return; + } + nextChar(); + break; + + case '@': + if (newline) + break loop; + // fallthrough + + default: + nextChar(); + break; + } + } + + } + + protected void entity(Void list) { + newline = false; + entity(); + } + + /** + * Read an HTML entity. + * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; } + */ + protected void entity() { + nextChar(); + String name = null; + if (ch == '#') { + int namep = bp; + nextChar(); + if (isDecimalDigit(ch)) { + nextChar(); + while (isDecimalDigit(ch)) + nextChar(); + name = new String(buf, namep, bp - namep); + } else if (ch == 'x' || ch == 'X') { + nextChar(); + if (isHexDigit(ch)) { + nextChar(); + while (isHexDigit(ch)) + nextChar(); + name = new String(buf, namep, bp - namep); + } + } + } else if (isIdentifierStart(ch)) { + name = readIdentifier(); + } + + if (name != null) { + if (ch != ';') + return; + nextChar(); + } + } + + /** + * Read the start or end of an HTML tag, or an HTML comment + * {@literal <identifier attrs> } or {@literal </identifier> } + */ + protected void html() { + int p = bp; + nextChar(); + if (isIdentifierStart(ch)) { + String name = readIdentifier(); + checkHtmlTag(name); + htmlAttrs(); + if (ch == '/') { + nextChar(); + } + if (ch == '>') { + nextChar(); + return; + } + } else if (ch == '/') { + nextChar(); + if (isIdentifierStart(ch)) { + readIdentifier(); + skipWhitespace(); + if (ch == '>') { + nextChar(); + return; + } + } + } else if (ch == '!') { + nextChar(); + if (ch == '-') { + nextChar(); + if (ch == '-') { + nextChar(); + while (bp < buflen) { + int dash = 0; + while (ch == '-') { + dash++; + nextChar(); + } + // Strictly speaking, a comment should not contain "--" + // so dash > 2 is an error, dash == 2 implies ch == '>' + // See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments + // for more details. + if (dash >= 2 && ch == '>') { + nextChar(); + return; + } + + nextChar(); + } + } + } + } + + bp = p + 1; + ch = buf[bp]; + } + + /** + * Read a series of HTML attributes, terminated by {@literal > }. + * Each attribute is of the form {@literal identifier[=value] }. + * "value" may be unquoted, single-quoted, or double-quoted. + */ + protected void htmlAttrs() { + skipWhitespace(); + + loop: + while (isIdentifierStart(ch)) { + int namePos = bp; + String name = readAttributeName(); + skipWhitespace(); + StringBuilder value = new StringBuilder(); + if (ch == '=') { + nextChar(); + skipWhitespace(); + if (ch == '\'' || ch == '"') { + char quote = ch; + nextChar(); + while (bp < buflen && ch != quote) { + if (newline && ch == '@') { + // No point trying to read more. + // In fact, all attrs get discarded by the caller + // and superseded by a malformed.html node because + // the html tag itself is not terminated correctly. + break loop; + } + value.append(ch); + nextChar(); + } + nextChar(); + } else { + while (bp < buflen && !isUnquotedAttrValueTerminator(ch)) { + value.append(ch); + nextChar(); + } + } + skipWhitespace(); + } + checkHtmlAttr(name, value.toString()); + } + } + + protected void attrValueChar(Void list) { + switch (ch) { + case '&': + entity(list); + break; + + case '{': + inlineTag(list); + break; + + default: + nextChar(); + } + } + + protected boolean isIdentifierStart(char ch) { + return Character.isUnicodeIdentifierStart(ch); + } + + protected String readIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isUnicodeIdentifierPart(ch)) + nextChar(); + return new String(buf, start, bp - start); + } + + protected String readAttributeName() { + int start = bp; + nextChar(); + while (bp < buflen && (Character.isUnicodeIdentifierPart(ch) || ch == '-')) + nextChar(); + return new String(buf, start, bp - start); + } + + protected String readTagName() { + int start = bp; + nextChar(); + while (bp < buflen + && (Character.isUnicodeIdentifierPart(ch) || ch == '.' + || ch == '-' || ch == ':')) { + nextChar(); + } + return new String(buf, start, bp - start); + } + + protected boolean isJavaIdentifierStart(char ch) { + return Character.isJavaIdentifierStart(ch); + } + + protected String readJavaIdentifier() { + int start = bp; + nextChar(); + while (bp < buflen && Character.isJavaIdentifierPart(ch)) + nextChar(); + return new String(buf, start, bp - start); + } + + protected boolean isDecimalDigit(char ch) { + return ('0' <= ch && ch <= '9'); + } + + protected boolean isHexDigit(char ch) { + return ('0' <= ch && ch <= '9') + || ('a' <= ch && ch <= 'f') + || ('A' <= ch && ch <= 'F'); + } + + protected boolean isUnquotedAttrValueTerminator(char ch) { + switch (ch) { + case '\f': case '\n': case '\r': case '\t': + case ' ': + case '"': case '\'': case '`': + case '=': case '<': case '>': + return true; + default: + return false; + } + } + + protected boolean isWhitespace(char ch) { + return Character.isWhitespace(ch); + } + + protected void skipWhitespace() { + while (isWhitespace(ch)) { + nextChar(); + } + } + + /** + * @param start position of first character of string + * @param end position of character beyond last character to be included + */ + String newString(int start, int end) { + return new String(buf, start, end - start); + } + + static abstract class TagParser { + enum Kind { INLINE, BLOCK } + + final Kind kind; + final String name; + + + TagParser(Kind k, String tk) { + kind = k; + name = tk; + } + + TagParser(Kind k, String tk, boolean retainWhiteSpace) { + this(k, tk); + } + + Kind getKind() { + return kind; + } + + String getName() { + return name; + } + + abstract void parse(int pos) throws ParseException; + } + + /** + * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a> + */ + @SuppressWarnings("deprecation") + private void initTagParsers() { + TagParser[] parsers = { + // @author name-text + new TagParser(Kind.BLOCK, "author") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // {@code text} + new TagParser(Kind.INLINE, "code", true) { + @Override + public void parse(int pos) throws ParseException { + inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); + nextChar(); + } + }, + + // @deprecated deprecated-text + new TagParser(Kind.BLOCK, "deprecated") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // {@docRoot} + new TagParser(Kind.INLINE, "docRoot") { + @Override + public void parse(int pos) throws ParseException { + if (ch == '}') { + nextChar(); + return; + } + inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content + nextChar(); + throw new ParseException("dc.unexpected.content"); + } + }, + + // @exception class-name description + new TagParser(Kind.BLOCK, "exception") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + reference(false); + blockContent(); + } + }, + + // @hidden hidden-text + new TagParser(Kind.BLOCK, "hidden") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // @index search-term options-description + new TagParser(Kind.INLINE, "index") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + if (ch == '}') { + throw new ParseException("dc.no.content"); + } + if (ch == '"') quotedString(); else inlineWord(); + skipWhitespace(); + if (ch != '}') { + inlineContent(); + } else { + nextChar(); + } + } + }, + + // {@inheritDoc} + new TagParser(Kind.INLINE, "inheritDoc") { + @Override + public void parse(int pos) throws ParseException { + if (ch == '}') { + nextChar(); + return; + } + inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content + nextChar(); + throw new ParseException("dc.unexpected.content"); + } + }, + + // {@link package.class#member label} + new TagParser(Kind.INLINE, "link") { + @Override + public void parse(int pos) throws ParseException { + reference(true); + inlineContent(); + } + }, + + // {@linkplain package.class#member label} + new TagParser(Kind.INLINE, "linkplain") { + @Override + public void parse(int pos) throws ParseException { + reference(true); + inlineContent(); + } + }, + + // {@literal text} + new TagParser(Kind.INLINE, "literal", true) { + @Override + public void parse(int pos) throws ParseException { + inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE); + nextChar(); + } + }, + + // @param parameter-name description + new TagParser(Kind.BLOCK, "param") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + + boolean typaram = false; + if (ch == '<') { + typaram = true; + nextChar(); + } + + identifier(); + + if (typaram) { + if (ch != '>') + throw new ParseException("dc.gt.expected"); + nextChar(); + } + + skipWhitespace(); + blockContent(); + } + }, + + // @return description + new TagParser(Kind.BLOCK, "return") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // @see reference | quoted-string | HTML + new TagParser(Kind.BLOCK, "see") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + switch (ch) { + case '"': + quotedString(); + skipWhitespace(); + if (ch == '@' + || ch == EOI && bp == buf.length - 1) { + return; + } + break; + + case '<': + blockContent(); + return; + + case '@': + if (newline) + throw new ParseException("dc.no.content"); + break; + + case EOI: + if (bp == buf.length - 1) + throw new ParseException("dc.no.content"); + break; + + default: + if (isJavaIdentifierStart(ch) || ch == '#') { + reference(true); + blockContent(); + } + } + throw new ParseException("dc.unexpected.content"); + } + }, + + // @serialData data-description + new TagParser(Kind.BLOCK, "@serialData") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // @serialField field-name field-type description + new TagParser(Kind.BLOCK, "serialField") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + identifier(); + skipWhitespace(); + reference(false); + if (isWhitespace(ch)) { + skipWhitespace(); + blockContent(); + } + } + }, + + // @serial field-description | include | exclude + new TagParser(Kind.BLOCK, "serial") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // @since since-text + new TagParser(Kind.BLOCK, "since") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + + // @throws class-name description + new TagParser(Kind.BLOCK, "throws") { + @Override + public void parse(int pos) throws ParseException { + skipWhitespace(); + reference(false); + blockContent(); + } + }, + + // {@value package.class#field} + new TagParser(Kind.INLINE, "value") { + @Override + public void parse(int pos) throws ParseException { + reference(true); + skipWhitespace(); + if (ch == '}') { + nextChar(); + return; + } + nextChar(); + throw new ParseException("dc.unexpected.content"); + } + }, + + // @version version-text + new TagParser(Kind.BLOCK, "version") { + @Override + public void parse(int pos) { + blockContent(); + } + }, + }; + + tagParsers = new HashMap<>(); + for (TagParser p: parsers) + tagParsers.put(p.getName(), p); + + } + + private void initEventAttrs() { + eventAttrs = new HashSet<>(Arrays.asList( + // See https://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.event-handler + "onabort", "onblur", "oncanplay", "oncanplaythrough", + "onchange", "onclick", "oncontextmenu", "ondblclick", + "ondrag", "ondragend", "ondragenter", "ondragleave", + "ondragover", "ondragstart", "ondrop", "ondurationchange", + "onemptied", "onended", "onerror", "onfocus", "oninput", + "oninvalid", "onkeydown", "onkeypress", "onkeyup", + "onload", "onloadeddata", "onloadedmetadata", "onloadstart", + "onmousedown", "onmousemove", "onmouseout", "onmouseover", + "onmouseup", "onmousewheel", "onpause", "onplay", + "onplaying", "onprogress", "onratechange", "onreadystatechange", + "onreset", "onscroll", "onseeked", "onseeking", + "onselect", "onshow", "onstalled", "onsubmit", "onsuspend", + "ontimeupdate", "onvolumechange", "onwaiting", + + // See https://www.w3.org/TR/html4/sgml/dtd.html + // Most of the attributes that take a %Script are also defined as event handlers + // in HTML 5. The one exception is onunload. + // "onchange", "onclick", "ondblclick", "onfocus", + // "onkeydown", "onkeypress", "onkeyup", "onload", + // "onmousedown", "onmousemove", "onmouseout", "onmouseover", + // "onmouseup", "onreset", "onselect", "onsubmit", + "onunload" + )); + } + + private void initURIAttrs() { + uriAttrs = new HashSet<>(Arrays.asList( + // See https://www.w3.org/TR/html4/sgml/dtd.html + // https://www.w3.org/TR/html5/ + // These are all the attributes that take a %URI or a valid URL potentially surrounded + // by spaces + "action", "cite", "classid", "codebase", "data", + "datasrc", "for", "href", "longdesc", "profile", + "src", "usemap" + )); + } + +}
--- a/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -381,6 +381,10 @@ env.initDoclint(opts, customTagNames); } + public JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) { + return env.initJavaScriptScanner(allowScriptInComments); + } + public boolean isFunctionalInterface(AnnotationDesc annotationDesc) { return annotationDesc.annotationType().qualifiedName().equals( env.syms.functionalInterfaceType.toString()) && env.source.allowLambda();
--- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, 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 @@ -110,6 +110,8 @@ javadoc.Body_missing_from_html_file=Body tag missing from HTML file javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file javadoc.Multiple_package_comments=Multiple sources of package comments found for package "{0}" +javadoc.JavaScript_in_comment=JavaScript found in documentation comment.\n\ + Use --allow-script-in-comments to allow use of JavaScript. javadoc.class_not_found=Class {0} not found. javadoc.error=error javadoc.warning=warning
--- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, 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 @@ -81,6 +81,7 @@ javadoc.Body_missing_from_html_file=HTML\u306Bbody\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093 javadoc.End_body_missing_from_html_file=HTML\u30D5\u30A1\u30A4\u30EB\u306Bbody\u306E\u9589\u3058\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093 javadoc.Multiple_package_comments=\u30D1\u30C3\u30B1\u30FC\u30B8"{0}"\u306B\u8907\u6570\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B3\u30E1\u30F3\u30C8\u306E\u30BD\u30FC\u30B9\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F +javadoc.JavaScript_in_comment=\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u306BJavaScript\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\n--allow-script-in-comments\u3092\u4F7F\u7528\u3057\u3066\u3001JavaScript\u306E\u4F7F\u7528\u3092\u8A31\u53EF\u3057\u3066\u304F\u3060\u3055\u3044\u3002 javadoc.class_not_found=\u30AF\u30E9\u30B9{0}\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 javadoc.error=\u30A8\u30E9\u30FC javadoc.warning=\u8B66\u544A
--- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties Fri Jan 13 17:09:30 2017 +0000 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties Mon Jan 23 16:30:40 2017 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, 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 @@ -81,6 +81,7 @@ javadoc.Body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u6807\u8BB0 javadoc.End_body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u7ED3\u675F\u6807\u8BB0 javadoc.Multiple_package_comments=\u627E\u5230\u7A0B\u5E8F\u5305 "{0}" \u7684\u591A\u4E2A\u7A0B\u5E8F\u5305\u6CE8\u91CA\u6E90 +javadoc.JavaScript_in_comment=\u6587\u6863\u6CE8\u91CA\u4E2D\u53D1\u73B0 JavaScript\u3002\n\u4F7F\u7528 --allow-script-in-comments \u53EF\u5141\u8BB8\u4F7F\u7528 JavaScript\u3002 javadoc.class_not_found=\u627E\u4E0D\u5230\u7C7B{0}\u3002 javadoc.error=\u9519\u8BEF javadoc.warning=\u8B66\u544A
--- a/test/tools/doclint/html/OtherTagsTest.out Fri Jan 13 17:09:30 2017 +0000 +++ b/test/tools/doclint/html/OtherTagsTest.out Mon Jan 23 16:30:40 2017 +0000 @@ -19,10 +19,7 @@ OtherTagsTest.java:20: error: element not allowed in documentation comments: <noframes> * <noframes> </noframes> ^ -OtherTagsTest.java:21: error: element not allowed in documentation comments: <script> - * <script> </script> - ^ OtherTagsTest.java:22: error: element not allowed in documentation comments: <title> * <title> </title> ^ -9 errors +8 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javadoc/TestScriptInComment.java Mon Jan 23 16:30:40 2017 +0000 @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016, 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. + */ + +/** + * @test + * @bug 8138725 + * @summary test --allow-script-in-comments + * @run main TestScriptInComment + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Combo-style test, exercising combinations of different HTML fragments that may contain + * JavaScript, different places to place those fragments, and whether or not to allow the use + * of JavaScript. + */ +public class TestScriptInComment { + public static void main(String... args) throws Exception { + new TestScriptInComment().run(); + } + + /** + * Representative samples of different fragments of HTML that may contain JavaScript. + * To facilitate checking the output manually in a browser, the text "#ALERT" will be + * replaced by a JavaScript call of "alert(msg)", using a message string that is specific + * to the test case. + */ + enum Comment { + LC("<script>#ALERT</script>", true), // script tag in Lower Case + UC("<SCRIPT>#ALERT</script>", true), // script tag in Upper Case + WS("< script >#ALERT</script>", false, "-Xdoclint:none"), // script tag with invalid white space + SA("<script src=\"file\"> #ALERT </script>", true), // script tag with an attribute + ON("<a onclick='#ALERT'>x</a>", true), // event handler attribute + URI("<a href='javascript:#ALERT'>x</a>", true); // javadcript URI + + /** + * Creates an HTML fragment to be injected into a template. + * @param text the HTML fragment to put into a doc comment or option. + * @param hasScript whether or not this fragment does contain legal JavaScript + * @param opts any additional options to be specified when javadoc is run + */ + Comment(String text, boolean hasScript, String... opts) { + this.text = text; + this.hasScript = hasScript; + this.opts = Arrays.asList(opts); + } + + final String text; + final boolean hasScript; + final List<String> opts; + }; + + /** + * Representative samples of positions in which javadoc may find JavaScript. + * Each template contains a series of strings, which are written to files or inferred as options. + * The first source file implies a corresponding output file which should not be written + * if the comment contains JavaScript and JavaScript is not allowed. + */ + enum Template { + OVR("<html><body> overview #COMMENT </body></html>", "package p; public class C { }"), + PKGINFO("#COMMENT package p;", "package p; public class C { }"), + PKGHTML("<html><body>#COMMENT package p;</body></html>", "package p; public class C { }"), + CLS("package p; #COMMENT public class C { }"), + CON("package p; public class C { #COMMENT public C() { } }"), + FLD("package p; public class C { #COMMENT public int f; }"), + MTH("package p; public class C { #COMMENT public void m() { } }"), + TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"), + HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"), + FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"), + BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"), + DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"), + PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }"); + + Template(String... args) { + opts = new ArrayList<String>(); + sources = new ArrayList<String>(); + int i = 0; + while (args[i].startsWith("-")) { + // all options being tested have a single argument that follow the option + opts.add(args[i++]); + opts.add(args[i++]); + } + while(i < args.length) { + sources.add(args[i++]); + } + } + + // groups: 1 <html> or not; 2: package name; 3: class name + private final Pattern pat = + Pattern.compile("(?i)(<html>)?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?"); + + /** + * Infer the file in which to write the given source. + * @param dir the base source directory + * @param src the source text + * @return the file in which the source should be written + */ + File getSrcFile(File srcDir, String src) { + String f; + Matcher m = pat.matcher(src); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".java"; + } else if (m.group(2) != null) { + f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html"); + } else { + f = "overview.html"; + } + return new File(srcDir, f); + } + + /** + * Get the options to give to javadoc. + * @param srcDir the srcDir to use -overview is needed + * @return + */ + List<String> getOpts(File srcDir) { + if (!opts.isEmpty()) { + return opts; + } else if (sources.get(0).contains("overview")) { + return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath()); + } else { + return Collections.emptyList(); + } + } + + /** + * Gets the output file corresponding to the first source file. + * This file should not be written if the comment contains JavaScript and JavaScripot is + * not allowed. + * @param dir the base output directory + * @return the output file + */ + File getOutFile(File outDir) { + String f; + Matcher m = pat.matcher(sources.get(0)); + if (!m.matches()) + throw new Error("match failed"); + if (m.group(3) != null) { + f = m.group(2) + "/" + m.group(3) + ".html"; + } else if (m.group(2) != null) { + f = m.group(2) + "/package-summary.html"; + } else { + f = "overview-summary.html"; + } + return new File(outDir, f); + } + + final List<String> opts; + final List<String> sources; + }; + + enum Option { + OFF(null), + ON("--allow-script-in-comments"); + + Option(String text) { + this.text = text; + } + + final String text; + }; + + private PrintStream out = System.err; + + public void run() throws Exception { + int count = 0; + for (Template template: Template.values()) { + for (Comment comment: Comment.values()) { + for (Option option: Option.values()) { + if (test(template, comment, option)) { + count++; + } + } + } + } + + out.println(count + " test cases run"); + if (errors > 0) { + throw new Exception(errors + " errors occurred"); + } + } + + boolean test(Template template, Comment comment, Option option) throws IOException { + if (option == Option.ON && !comment.hasScript) { + // skip --allowScriptInComments if comment does not contain JavaScript + return false; + } + + String test = template + "-" + comment + "-" + option; + out.println("Test: " + test); + + File dir = new File(test); + dir.mkdirs(); + File srcDir = new File(dir, "src"); + File outDir = new File(dir, "out"); + + String alert = "alert(\"" + test + "\");"; + for (String src: template.sources) { + writeFile(template.getSrcFile(srcDir, src), + src.replace("#COMMENT", + "/** " + comment.text.replace("#ALERT", alert) + " **/")); + } + + List<String> opts = new ArrayList<String>(); + opts.add("-sourcepath"); + opts.add(srcDir.getPath()); + opts.add("-d"); + opts.add(outDir.getPath()); + if (option.text != null) + opts.add(option.text); + for (String opt: template.getOpts(srcDir)) { + opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert))); + } + opts.addAll(comment.opts); + opts.add("-noindex"); // index not required; save time/space writing files + opts.add("p"); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = javadoc(opts, pw); + pw.close(); + String log = sw.toString(); + writeFile(new File(dir, "log.txt"), log); + + out.println("opts: " + opts); + out.println(" rc: " + rc); + out.println(" log:"); + out.println(log); + + String ERROR = "Use --allow-script-in-comment"; + File outFile = template.getOutFile(outDir); + + boolean expectErrors = comment.hasScript && (option == Option.OFF); + + if (expectErrors) { + check(rc != 0, "unexpected exit code: " + rc); + check(log.contains(ERROR), "expected error message not found"); + check(!outFile.exists(), "output file found unexpectedly"); + } else { + check(rc == 0, "unexpected exit code: " + rc); + check(!log.contains(ERROR), "error message found"); + check(outFile.exists(), "output file not found"); + } + + out.println(); + return true; + } + + int javadoc(List<String> opts, PrintWriter pw) { + return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw, + "com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()])); + } + + File writeFile(File f, String text) throws IOException { + f.getParentFile().mkdirs(); + FileWriter fw = new FileWriter(f); + try { + fw.write(text); + } finally { + fw.close(); + } + return f; + } + + void check(boolean cond, String errMessage) { + if (!cond) { + error(errMessage); + } + } + + void error(String message) { + out.println("Error: " + message); + errors++; + } + + int errors = 0; +} +