Merge

Thu, 22 Dec 2016 16:21:25 -0800

author
asaha
date
Thu, 22 Dec 2016 16:21:25 -0800
changeset 3347
46a7edb68d0a
parent 3313
041fd0291a68
parent 3346
8dc65c3ac595
child 3349
f47b61665c6f

Merge

.hgtags file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Tue Dec 20 15:24:55 2016 -0800
     1.2 +++ b/.hgtags	Thu Dec 22 16:21:25 2016 -0800
     1.3 @@ -632,6 +632,10 @@
     1.4  56b0df415b570e31dc0b97d4a1c8f28b85240089 jdk8u102-b13
     1.5  0549bf2f507dae59bfcd7d11e038cdc62376fee7 jdk8u102-b14
     1.6  d86027f25a9aa960d69cf3a524588a873ae888f5 jdk8u102-b31
     1.7 +1b511d4e93e7128ccb7100110ab6604eb2838afa jdk8u102-b32
     1.8 +3d4b72198b23108f93ccf36b8d9275cc3b40ee1e jdk8u102-b33
     1.9 +8bde2f8474d372de6a3425affd38de506aa56a51 jdk8u102-b34
    1.10 +e64f16f8a585332086127b4f24b79e6c83bee530 jdk8u102-b35
    1.11  90f493bfe1faca0573844fdd2497070c8b224d76 jdk8u111-b00
    1.12  085fd7e08f4855f134a8048251c4535ddde1feee jdk8u111-b01
    1.13  f66a535fb6b3b41419c987cc90407507a64712b2 jdk8u111-b02
    1.14 @@ -663,6 +667,21 @@
    1.15  b353281f73db9617d993353e468342d3420c29f1 jdk8u112-b14
    1.16  6116c6644be0c85556931aaeb9b4f2dbc9c79157 jdk8u112-b15
    1.17  ee37eafc48cb6fb20cb6c1e31cfecfe1ccc800da jdk8u112-b16
    1.18 +de1c3df992adb0c704005583210d1ed6dac758cd jdk8u112-b31
    1.19 +5710d574a99aeff3600c49a4aed34fa1b373f7b8 jdk8u121-b00
    1.20 +ab5d32d8cf5f6d81482692f801385a869b2d83c1 jdk8u121-b01
    1.21 +e260d46661d2da3ede78aae434d5420acce99950 jdk8u121-b02
    1.22 +0acfd50d67d98259a25fbd51129b763bab56d068 jdk8u121-b03
    1.23 +29a08aff06088cad98dafddef7628b51e324fcae jdk8u121-b04
    1.24 +a933635275c33e37c9403767d600a12b9ee71df7 jdk8u121-b05
    1.25 +dc1dd2e6cf8e094c4a8437d54ebc7bac1f7ab964 jdk8u121-b06
    1.26 +6cd0cd4078e9ec8ad9fa167cabf9c671ed21fc66 jdk8u121-b07
    1.27 +8efc10efbfe137ed5de6bf55875fdafd25bb6a1b jdk8u121-b08
    1.28 +57a26fe61f2b435332c0697e92965a22246cd143 jdk8u121-b09
    1.29 +53c94a674d6076ff390c62a7682ea0e87a893cdc jdk8u121-b10
    1.30 +b634abfcd98fb8b201da9208e398ea17cabd2b32 jdk8u121-b11
    1.31 +7fc347da372c8c4e5530a7fa32084b5dbc4ee8b6 jdk8u121-b12
    1.32 +f634736433d9fc1cffbdc55611f97ecb2cd44059 jdk8u121-b13
    1.33  9a9ce479b92f1b4d9d436fb857d70c3d2b59a20c jdk8u122-b00
    1.34  85d9e434701cc7112aaf965b0f5ee4b31ab2a445 jdk8u122-b01
    1.35  2baeb96fa198f75e9bd50a5f5ef4a19be6cfbc4e jdk8u122-b02
     2.1 --- a/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Tue Dec 20 15:24:55 2016 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java	Thu Dec 22 16:21:25 2016 -0800
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -38,6 +38,7 @@
    2.11  import com.sun.tools.javac.file.JavacFileManager;
    2.12  import com.sun.tools.javac.util.Context;
    2.13  import com.sun.tools.javac.util.StringUtils;
    2.14 +import com.sun.tools.javadoc.JavaScriptScanner;
    2.15  import com.sun.tools.javadoc.RootDocImpl;
    2.16  
    2.17  /**
    2.18 @@ -181,6 +182,11 @@
    2.19      public Set<String> doclintOpts = new LinkedHashSet<String>();
    2.20  
    2.21      /**
    2.22 +     * Whether or not to check for JavaScript in doc comments.
    2.23 +     */
    2.24 +    private boolean allowScriptInComments;
    2.25 +
    2.26 +    /**
    2.27       * Unique Resource Handler for this package.
    2.28       */
    2.29      public final MessageRetriever standardmessage;
    2.30 @@ -283,8 +289,11 @@
    2.31                  doclintOpts.add(null);
    2.32              } else if (opt.startsWith("-xdoclint:")) {
    2.33                  doclintOpts.add(opt.substring(opt.indexOf(":") + 1));
    2.34 +            } else if (opt.equals("--allow-script-in-comments")) {
    2.35 +                allowScriptInComments = true;
    2.36              }
    2.37          }
    2.38 +
    2.39          if (root.specifiedClasses().length > 0) {
    2.40              Map<String,PackageDoc> map = new HashMap<String,PackageDoc>();
    2.41              PackageDoc pd;
    2.42 @@ -301,9 +310,30 @@
    2.43  
    2.44          if (root instanceof RootDocImpl) {
    2.45              ((RootDocImpl) root).initDocLint(doclintOpts, tagletManager.getCustomTagNames());
    2.46 +            JavaScriptScanner jss = ((RootDocImpl) root).initJavaScriptScanner(isAllowScriptInComments());
    2.47 +            if (jss != null) {
    2.48 +                // In a more object-oriented world, this would be done by methods on the Option objects.
    2.49 +                // Note that -windowtitle silently removes any and all HTML elements, and so does not need
    2.50 +                // to be handled here.
    2.51 +                checkJavaScript(jss, "-header", header);
    2.52 +                checkJavaScript(jss, "-footer", footer);
    2.53 +                checkJavaScript(jss, "-top", top);
    2.54 +                checkJavaScript(jss, "-bottom", bottom);
    2.55 +                checkJavaScript(jss, "-doctitle", doctitle);
    2.56 +                checkJavaScript(jss, "-packagesheader", packagesheader);
    2.57 +            }
    2.58          }
    2.59      }
    2.60  
    2.61 +    private void checkJavaScript(JavaScriptScanner jss, final String opt, String value) {
    2.62 +        jss.parse(value, new JavaScriptScanner.Reporter() {
    2.63 +            public void report() {
    2.64 +                root.printError(getText("doclet.JavaScript_in_option", opt));
    2.65 +                throw new FatalError();
    2.66 +            }
    2.67 +        });
    2.68 +    }
    2.69 +
    2.70      /**
    2.71       * Returns the "length" of a given option. If an option takes no
    2.72       * arguments, its length is one. If it takes one argument, it's
    2.73 @@ -337,7 +367,8 @@
    2.74              option.equals("-nonavbar") ||
    2.75              option.equals("-nooverview") ||
    2.76              option.equals("-xdoclint") ||
    2.77 -            option.startsWith("-xdoclint:")) {
    2.78 +            option.startsWith("-xdoclint:") ||
    2.79 +            option.equals("--allow-script-in-comments")) {
    2.80              return 1;
    2.81          } else if (option.equals("-help")) {
    2.82              // Uugh: first, this should not be hidden inside optionLength,
    2.83 @@ -595,4 +626,13 @@
    2.84      public Content newContent() {
    2.85          return new ContentBuilder();
    2.86      }
    2.87 +
    2.88 +    /**
    2.89 +     * Returns whether or not to allow JavaScript in comments.
    2.90 +     * Default is off; can be set true from a command line option.
    2.91 +     * @return the allowScriptInComments
    2.92 +     */
    2.93 +    public boolean isAllowScriptInComments() {
    2.94 +        return allowScriptInComments;
    2.95 +    }
    2.96  }
     3.1 --- a/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java	Tue Dec 20 15:24:55 2016 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java	Thu Dec 22 16:21:25 2016 -0800
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -190,6 +190,8 @@
    3.11                  }
    3.12              } catch (IOException e) {
    3.13                  throw new DocletAbortException(e);
    3.14 +            } catch (FatalError fe) {
    3.15 +                throw fe;
    3.16              } catch (DocletAbortException de) {
    3.17                  throw de;
    3.18              } catch (Exception e) {
     4.1 --- a/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java	Tue Dec 20 15:24:55 2016 -0800
     4.2 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java	Thu Dec 22 16:21:25 2016 -0800
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -164,7 +164,9 @@
    4.11  
    4.12      public final Content descfrmInterfaceLabel;
    4.13  
    4.14 -    private final Writer writer;
    4.15 +    private final DocFile file;
    4.16 +
    4.17 +    private Writer writer;
    4.18  
    4.19      private Content script;
    4.20  
    4.21 @@ -180,7 +182,7 @@
    4.22       */
    4.23      public HtmlWriter(Configuration configuration, DocPath path)
    4.24              throws IOException, UnsupportedEncodingException {
    4.25 -        writer = DocFile.createFileForOutput(configuration, path).openWriter();
    4.26 +        file = DocFile.createFileForOutput(configuration, path);
    4.27          this.configuration = configuration;
    4.28          this.memberDetailsListPrinted = false;
    4.29          profileTableHeader = new String[] {
    4.30 @@ -239,6 +241,7 @@
    4.31      }
    4.32  
    4.33      public void write(Content c) throws IOException {
    4.34 +        writer = file.openWriter();
    4.35          c.write(writer, true);
    4.36      }
    4.37  
     5.1 --- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java	Tue Dec 20 15:24:55 2016 -0800
     5.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/AbstractDoclet.java	Thu Dec 22 16:21:25 2016 -0800
     5.3 @@ -1,5 +1,5 @@
     5.4  /*
     5.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
     5.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.8   *
     5.9   * This code is free software; you can redistribute it and/or modify it
    5.10 @@ -83,6 +83,8 @@
    5.11          } catch (Configuration.Fault f) {
    5.12              root.printError(f.getMessage());
    5.13              return false;
    5.14 +        } catch (FatalError fe) {
    5.15 +            return false;
    5.16          } catch (DocletAbortException e) {
    5.17              Throwable cause = e.getCause();
    5.18              if (cause != null) {
     6.1 --- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java	Tue Dec 20 15:24:55 2016 -0800
     6.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AbstractBuilder.java	Thu Dec 22 16:21:25 2016 -0800
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -140,7 +140,14 @@
    6.11              configuration.root.printError("Unknown element: " + component);
    6.12              throw new DocletAbortException(e);
    6.13          } catch (InvocationTargetException e) {
    6.14 -            throw new DocletAbortException(e.getCause());
    6.15 +            Throwable cause = e.getCause();
    6.16 +            if (cause instanceof FatalError) {
    6.17 +                throw (FatalError) cause;
    6.18 +            } else if (cause instanceof DocletAbortException) {
    6.19 +                throw (DocletAbortException) cause;
    6.20 +            } else {
    6.21 +                throw new DocletAbortException(cause);
    6.22 +            }
    6.23          } catch (Exception e) {
    6.24              e.printStackTrace();
    6.25              configuration.root.printError("Exception " +
     7.1 --- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties	Tue Dec 20 15:24:55 2016 -0800
     7.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties	Thu Dec 22 16:21:25 2016 -0800
     7.3 @@ -29,6 +29,8 @@
     7.4  doclet.Building_Tree=Building tree for all the packages and classes...
     7.5  doclet.Building_Index=Building index for all the packages and classes...
     7.6  doclet.Building_Index_For_All_Classes=Building index for all classes...
     7.7 +doclet.JavaScript_in_option=Argument for {0} contains JavaScript.\n\
     7.8 +Use --allow-script-in-comments to allow use of JavaScript.
     7.9  doclet.sourcetab_warning=The argument for -sourcetab must be an integer greater than 0.
    7.10  doclet.Packages=Packages
    7.11  doclet.Profiles=Profiles
     8.1 --- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties	Tue Dec 20 15:24:55 2016 -0800
     8.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties	Thu Dec 22 16:21:25 2016 -0800
     8.3 @@ -27,6 +27,7 @@
     8.4  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...
     8.5  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...
     8.6  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...
     8.7 +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
     8.8  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
     8.9  doclet.Packages=\u30D1\u30C3\u30B1\u30FC\u30B8
    8.10  doclet.Profiles=\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB
     9.1 --- a/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties	Tue Dec 20 15:24:55 2016 -0800
     9.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties	Thu Dec 22 16:21:25 2016 -0800
     9.3 @@ -27,6 +27,7 @@
     9.4  doclet.Building_Tree=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u6811...
     9.5  doclet.Building_Index=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7A0B\u5E8F\u5305\u548C\u7C7B\u7684\u7D22\u5F15...
     9.6  doclet.Building_Index_For_All_Classes=\u6B63\u5728\u6784\u5EFA\u6240\u6709\u7C7B\u7684\u7D22\u5F15...
     9.7 +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
     9.8  doclet.sourcetab_warning=-sourcetab \u7684\u53C2\u6570\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570\u3002
     9.9  doclet.Packages=\u7A0B\u5E8F\u5305
    9.10  doclet.Profiles=\u914D\u7F6E\u6587\u4EF6
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/FatalError.java	Thu Dec 22 16:21:25 2016 -0800
    10.3 @@ -0,0 +1,39 @@
    10.4 +/*
    10.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Oracle designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Oracle in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.25 + * or visit www.oracle.com if you need additional information or have any
   10.26 + * questions.
   10.27 + */
   10.28 +
   10.29 +package com.sun.tools.doclets.internal.toolkit.util;
   10.30 +
   10.31 +/**
   10.32 + *  <p><b>This is NOT part of any supported API.
   10.33 + *  If you write code that depends on this, you do so at your own risk.
   10.34 + *  This code and its internal interfaces are subject to change or
   10.35 + *  deletion without notice.</b>
   10.36 + */
   10.37 +@Deprecated
   10.38 +public class FatalError extends Error {
   10.39 +    private static final long serialVersionUID = -9131058909576418984L;
   10.40 +
   10.41 +    public FatalError() { }
   10.42 +}
    11.1 --- a/src/share/classes/com/sun/tools/doclint/Checker.java	Tue Dec 20 15:24:55 2016 -0800
    11.2 +++ b/src/share/classes/com/sun/tools/doclint/Checker.java	Thu Dec 22 16:21:25 2016 -0800
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -126,7 +126,7 @@
   11.11          }
   11.12      }
   11.13  
   11.14 -    private Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
   11.15 +    private final Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
   11.16      private HtmlTag currHeaderTag;
   11.17  
   11.18      private final int implicitHeaderLevel;
   11.19 @@ -401,7 +401,16 @@
   11.20                  break;
   11.21  
   11.22              case OTHER:
   11.23 -                env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
   11.24 +                switch (t) {
   11.25 +                    case SCRIPT:
   11.26 +                        // <script> may or may not be allowed, depending on --allow-script-in-comments
   11.27 +                        // but we allow it here, and rely on a separate scanner to detect all uses
   11.28 +                        // of JavaScript, including <script> tags, and use in attributes, etc.
   11.29 +                        break;
   11.30 +
   11.31 +                    default:
   11.32 +                        env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
   11.33 +                }
   11.34                  return;
   11.35          }
   11.36  
   11.37 @@ -519,22 +528,27 @@
   11.38                  if (!first)
   11.39                      env.messages.error(HTML, tree, "dc.attr.repeated", name);
   11.40              }
   11.41 -            AttrKind k = currTag.getAttrKind(name);
   11.42 -            switch (k) {
   11.43 -                case OK:
   11.44 -                    break;
   11.45  
   11.46 -                case INVALID:
   11.47 -                    env.messages.error(HTML, tree, "dc.attr.unknown", name);
   11.48 -                    break;
   11.49 +            // for now, doclint allows all attribute names beginning with "on" as event handler names,
   11.50 +            // without checking the validity or applicability of the name
   11.51 +            if (!name.toString().startsWith("on")) {
   11.52 +                AttrKind k = currTag.getAttrKind(name);
   11.53 +                switch (k) {
   11.54 +                    case OK:
   11.55 +                        break;
   11.56  
   11.57 -                case OBSOLETE:
   11.58 -                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
   11.59 -                    break;
   11.60 +                    case INVALID:
   11.61 +                        env.messages.error(HTML, tree, "dc.attr.unknown", name);
   11.62 +                        break;
   11.63  
   11.64 -                case USE_CSS:
   11.65 -                    env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
   11.66 -                    break;
   11.67 +                    case OBSOLETE:
   11.68 +                        env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
   11.69 +                        break;
   11.70 +
   11.71 +                    case USE_CSS:
   11.72 +                        env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
   11.73 +                        break;
   11.74 +                }
   11.75              }
   11.76  
   11.77              if (attr != null) {
   11.78 @@ -643,6 +657,9 @@
   11.79      }
   11.80  
   11.81      private void checkURI(AttributeTree tree, String uri) {
   11.82 +        // allow URIs beginning with javascript:, which would otherwise be rejected by the URI API.
   11.83 +        if (uri.startsWith("javascript:"))
   11.84 +            return;
   11.85          try {
   11.86              URI u = new URI(uri);
   11.87          } catch (URISyntaxException e) {
    12.1 --- a/src/share/classes/com/sun/tools/doclint/HtmlTag.java	Tue Dec 20 15:24:55 2016 -0800
    12.2 +++ b/src/share/classes/com/sun/tools/doclint/HtmlTag.java	Thu Dec 22 16:21:25 2016 -0800
    12.3 @@ -1,5 +1,5 @@
    12.4  /*
    12.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    12.6 + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
    12.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.8   *
    12.9   * This code is free software; you can redistribute it and/or modify it
   12.10 @@ -183,7 +183,8 @@
   12.11          }
   12.12      },
   12.13  
   12.14 -    SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
   12.15 +    SCRIPT(BlockType.OTHER, EndKind.REQUIRED,
   12.16 +            attrs(AttrKind.OK, SRC)),
   12.17  
   12.18      SMALL(BlockType.INLINE, EndKind.REQUIRED,
   12.19              EnumSet.of(Flag.EXPECT_CONTENT)),
    13.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Dec 20 15:24:55 2016 -0800
    13.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Dec 22 16:21:25 2016 -0800
    13.3 @@ -1,5 +1,5 @@
    13.4  /*
    13.5 - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
    13.6 + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
    13.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.8   *
    13.9   * This code is free software; you can redistribute it and/or modify it
   13.10 @@ -585,7 +585,7 @@
   13.11      /**
   13.12       * Ident = IDENTIFIER
   13.13       */
   13.14 -    Name ident() {
   13.15 +    public Name ident() {
   13.16          if (token.kind == IDENTIFIER) {
   13.17              Name name = token.name();
   13.18              nextToken();
    14.1 --- a/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Tue Dec 20 15:24:55 2016 -0800
    14.2 +++ b/src/share/classes/com/sun/tools/javadoc/DocEnv.java	Thu Dec 22 16:21:25 2016 -0800
    14.3 @@ -1,5 +1,5 @@
    14.4  /*
    14.5 - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    14.6 + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
    14.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.8   *
    14.9   * This code is free software; you can redistribute it and/or modify it
   14.10 @@ -86,7 +86,7 @@
   14.11      JavadocEnter enter;
   14.12  
   14.13      /** The name table. */
   14.14 -    Names names;
   14.15 +    private final Names names;
   14.16  
   14.17      /** The encoding name. */
   14.18      private String encoding;
   14.19 @@ -109,6 +109,7 @@
   14.20      JavaFileManager fileManager;
   14.21      Context context;
   14.22      DocLint doclint;
   14.23 +    JavaScriptScanner javaScriptScanner;
   14.24  
   14.25      WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>();
   14.26  
   14.27 @@ -834,6 +835,15 @@
   14.28          doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
   14.29      }
   14.30  
   14.31 +    JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
   14.32 +        if (allowScriptInComments) {
   14.33 +            javaScriptScanner = null;
   14.34 +        } else {
   14.35 +            javaScriptScanner = new JavaScriptScanner();
   14.36 +        }
   14.37 +        return javaScriptScanner;
   14.38 +    }
   14.39 +
   14.40      boolean showTagMessages() {
   14.41          return (doclint == null);
   14.42      }
    15.1 --- a/src/share/classes/com/sun/tools/javadoc/DocImpl.java	Tue Dec 20 15:24:55 2016 -0800
    15.2 +++ b/src/share/classes/com/sun/tools/javadoc/DocImpl.java	Thu Dec 22 16:21:25 2016 -0800
    15.3 @@ -1,5 +1,5 @@
    15.4  /*
    15.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    15.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
    15.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.8   *
    15.9   * This code is free software; you can redistribute it and/or modify it
   15.10 @@ -36,6 +36,7 @@
   15.11  
   15.12  import com.sun.javadoc.*;
   15.13  import com.sun.source.util.TreePath;
   15.14 +import com.sun.tools.doclets.internal.toolkit.util.FatalError;
   15.15  import com.sun.tools.javac.tree.JCTree;
   15.16  import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
   15.17  import com.sun.tools.javac.util.Position;
   15.18 @@ -127,6 +128,15 @@
   15.19      Comment comment() {
   15.20          if (comment == null) {
   15.21              String d = documentation();
   15.22 +            if (env.javaScriptScanner != null) {
   15.23 +                env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() {
   15.24 +                    @Override
   15.25 +                    public void report() {
   15.26 +                        env.error(DocImpl.this, "javadoc.JavaScript_in_comment");
   15.27 +                        throw new FatalError();
   15.28 +                    }
   15.29 +                });
   15.30 +            }
   15.31              if (env.doclint != null
   15.32                      && treePath != null
   15.33                      && d.equals(getCommentText(treePath))) {
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/share/classes/com/sun/tools/javadoc/JavaScriptScanner.java	Thu Dec 22 16:21:25 2016 -0800
    16.3 @@ -0,0 +1,1103 @@
    16.4 +/*
    16.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.  Oracle designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Oracle in the LICENSE file that accompanied this code.
   16.13 + *
   16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 + * version 2 for more details (a copy is included in the LICENSE file that
   16.18 + * accompanied this code).
   16.19 + *
   16.20 + * You should have received a copy of the GNU General Public License version
   16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 + *
   16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.25 + * or visit www.oracle.com if you need additional information or have any
   16.26 + * questions.
   16.27 + */
   16.28 +
   16.29 +package com.sun.tools.javadoc;
   16.30 +
   16.31 +import java.util.Arrays;
   16.32 +import java.util.HashMap;
   16.33 +import java.util.HashSet;
   16.34 +import java.util.Locale;
   16.35 +import java.util.Map;
   16.36 +import java.util.Set;
   16.37 +
   16.38 +import com.sun.tools.javadoc.JavaScriptScanner.TagParser.Kind;
   16.39 +
   16.40 +import static com.sun.tools.javac.util.LayoutCharacters.EOI;
   16.41 +
   16.42 +/**
   16.43 + * Parser to detect use of JavaScript in documentation comments.
   16.44 + */
   16.45 +@Deprecated
   16.46 +public class JavaScriptScanner {
   16.47 +    public static interface Reporter {
   16.48 +        void report();
   16.49 +    }
   16.50 +
   16.51 +    static class ParseException extends Exception {
   16.52 +        private static final long serialVersionUID = 0;
   16.53 +        ParseException(String key) {
   16.54 +            super(key);
   16.55 +        }
   16.56 +    }
   16.57 +
   16.58 +    private Reporter reporter;
   16.59 +
   16.60 +    /** The input buffer, index of most recent character read,
   16.61 +     *  index of one past last character in buffer.
   16.62 +     */
   16.63 +    protected char[] buf;
   16.64 +    protected int bp;
   16.65 +    protected int buflen;
   16.66 +
   16.67 +    /** The current character.
   16.68 +     */
   16.69 +    protected char ch;
   16.70 +
   16.71 +    private boolean newline = true;
   16.72 +
   16.73 +    Map<String, TagParser> tagParsers;
   16.74 +    Set<String> eventAttrs;
   16.75 +    Set<String> uriAttrs;
   16.76 +
   16.77 +    public JavaScriptScanner() {
   16.78 +        initTagParsers();
   16.79 +        initEventAttrs();
   16.80 +        initURIAttrs();
   16.81 +    }
   16.82 +
   16.83 +    public void parse(String comment, Reporter r) {
   16.84 +        reporter = r;
   16.85 +        String c = comment;
   16.86 +        buf = new char[c.length() + 1];
   16.87 +        c.getChars(0, c.length(), buf, 0);
   16.88 +        buf[buf.length - 1] = EOI;
   16.89 +        buflen = buf.length - 1;
   16.90 +        bp = -1;
   16.91 +        newline = true;
   16.92 +        nextChar();
   16.93 +
   16.94 +        blockContent();
   16.95 +        blockTags();
   16.96 +    }
   16.97 +
   16.98 +    private void checkHtmlTag(String tag) {
   16.99 +        if (tag.equalsIgnoreCase("script")) {
  16.100 +            reporter.report();
  16.101 +        }
  16.102 +    }
  16.103 +
  16.104 +    private void checkHtmlAttr(String name, String value) {
  16.105 +        String n = name.toLowerCase(Locale.ENGLISH);
  16.106 +        if (eventAttrs.contains(n)
  16.107 +                || uriAttrs.contains(n)
  16.108 +                    && value != null && value.toLowerCase(Locale.ENGLISH).trim().startsWith("javascript:")) {
  16.109 +            reporter.report();
  16.110 +        }
  16.111 +    }
  16.112 +
  16.113 +    void nextChar() {
  16.114 +        ch = buf[bp < buflen ? ++bp : buflen];
  16.115 +        switch (ch) {
  16.116 +            case '\f': case '\n': case '\r':
  16.117 +                newline = true;
  16.118 +        }
  16.119 +    }
  16.120 +
  16.121 +    /**
  16.122 +     * Read block content, consisting of text, html and inline tags.
  16.123 +     * Terminated by the end of input, or the beginning of the next block tag:
  16.124 +     * i.e. @ as the first non-whitespace character on a line.
  16.125 +     */
  16.126 +    @SuppressWarnings("fallthrough")
  16.127 +    protected void blockContent() {
  16.128 +
  16.129 +        loop:
  16.130 +        while (bp < buflen) {
  16.131 +            switch (ch) {
  16.132 +                case '\n': case '\r': case '\f':
  16.133 +                    newline = true;
  16.134 +                    // fallthrough
  16.135 +
  16.136 +                case ' ': case '\t':
  16.137 +                    nextChar();
  16.138 +                    break;
  16.139 +
  16.140 +                case '&':
  16.141 +                    entity(null);
  16.142 +                    break;
  16.143 +
  16.144 +                case '<':
  16.145 +                    html();
  16.146 +                    break;
  16.147 +
  16.148 +                case '>':
  16.149 +                    newline = false;
  16.150 +                    nextChar();
  16.151 +                    break;
  16.152 +
  16.153 +                case '{':
  16.154 +                    inlineTag(null);
  16.155 +                    break;
  16.156 +
  16.157 +                case '@':
  16.158 +                    if (newline) {
  16.159 +                        break loop;
  16.160 +                    }
  16.161 +                    // fallthrough
  16.162 +
  16.163 +                default:
  16.164 +                    newline = false;
  16.165 +                    nextChar();
  16.166 +            }
  16.167 +        }
  16.168 +    }
  16.169 +
  16.170 +    /**
  16.171 +     * Read a series of block tags, including their content.
  16.172 +     * Standard tags parse their content appropriately.
  16.173 +     * Non-standard tags are represented by {@link UnknownBlockTag}.
  16.174 +     */
  16.175 +    protected void blockTags() {
  16.176 +        while (ch == '@')
  16.177 +            blockTag();
  16.178 +    }
  16.179 +
  16.180 +    /**
  16.181 +     * Read a single block tag, including its content.
  16.182 +     * Standard tags parse their content appropriately.
  16.183 +     * Non-standard tags are represented by {@link UnknownBlockTag}.
  16.184 +     */
  16.185 +    protected void blockTag() {
  16.186 +        int p = bp;
  16.187 +        try {
  16.188 +            nextChar();
  16.189 +            if (isIdentifierStart(ch)) {
  16.190 +                String name = readTagName();
  16.191 +                TagParser tp = tagParsers.get(name);
  16.192 +                if (tp == null) {
  16.193 +                    blockContent();
  16.194 +                } else {
  16.195 +                    switch (tp.getKind()) {
  16.196 +                        case BLOCK:
  16.197 +                            tp.parse(p);
  16.198 +                            return;
  16.199 +                        case INLINE:
  16.200 +                            return;
  16.201 +                    }
  16.202 +                }
  16.203 +            }
  16.204 +            blockContent();
  16.205 +        } catch (ParseException e) {
  16.206 +            blockContent();
  16.207 +        }
  16.208 +    }
  16.209 +
  16.210 +    protected void inlineTag(Void list) {
  16.211 +        newline = false;
  16.212 +        nextChar();
  16.213 +        if (ch == '@') {
  16.214 +            inlineTag();
  16.215 +        }
  16.216 +    }
  16.217 +
  16.218 +    /**
  16.219 +     * Read a single inline tag, including its content.
  16.220 +     * Standard tags parse their content appropriately.
  16.221 +     * Non-standard tags are represented by {@link UnknownBlockTag}.
  16.222 +     * Malformed tags may be returned as {@link Erroneous}.
  16.223 +     */
  16.224 +    protected void inlineTag() {
  16.225 +        int p = bp - 1;
  16.226 +        try {
  16.227 +            nextChar();
  16.228 +            if (isIdentifierStart(ch)) {
  16.229 +                String name = readTagName();
  16.230 +                TagParser tp = tagParsers.get(name);
  16.231 +
  16.232 +                if (tp == null) {
  16.233 +                    skipWhitespace();
  16.234 +                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL);
  16.235 +                    nextChar();
  16.236 +                } else {
  16.237 +                    skipWhitespace();
  16.238 +                    if (tp.getKind() == TagParser.Kind.INLINE) {
  16.239 +                        tp.parse(p);
  16.240 +                    } else { // handle block tags (ex: @see) in inline content
  16.241 +                        inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip content
  16.242 +                        nextChar();
  16.243 +                    }
  16.244 +                }
  16.245 +            }
  16.246 +        } catch (ParseException e) {
  16.247 +        }
  16.248 +    }
  16.249 +
  16.250 +    private static enum WhitespaceRetentionPolicy {
  16.251 +        RETAIN_ALL,
  16.252 +        REMOVE_FIRST_SPACE,
  16.253 +        REMOVE_ALL
  16.254 +    }
  16.255 +
  16.256 +    /**
  16.257 +     * Read plain text content of an inline tag.
  16.258 +     * Matching pairs of { } are skipped; the text is terminated by the first
  16.259 +     * unmatched }. It is an error if the beginning of the next tag is detected.
  16.260 +     */
  16.261 +    private void inlineText(WhitespaceRetentionPolicy whitespacePolicy) throws ParseException {
  16.262 +        switch (whitespacePolicy) {
  16.263 +            case REMOVE_ALL:
  16.264 +                skipWhitespace();
  16.265 +                break;
  16.266 +            case REMOVE_FIRST_SPACE:
  16.267 +                if (ch == ' ')
  16.268 +                    nextChar();
  16.269 +                break;
  16.270 +            case RETAIN_ALL:
  16.271 +            default:
  16.272 +                // do nothing
  16.273 +                break;
  16.274 +
  16.275 +        }
  16.276 +        int pos = bp;
  16.277 +        int depth = 1;
  16.278 +
  16.279 +        loop:
  16.280 +        while (bp < buflen) {
  16.281 +            switch (ch) {
  16.282 +                case '\n': case '\r': case '\f':
  16.283 +                    newline = true;
  16.284 +                    break;
  16.285 +
  16.286 +                case ' ': case '\t':
  16.287 +                    break;
  16.288 +
  16.289 +                case '{':
  16.290 +                    newline = false;
  16.291 +                    depth++;
  16.292 +                    break;
  16.293 +
  16.294 +                case '}':
  16.295 +                    if (--depth == 0) {
  16.296 +                        return;
  16.297 +                    }
  16.298 +                    newline = false;
  16.299 +                    break;
  16.300 +
  16.301 +                case '@':
  16.302 +                    if (newline)
  16.303 +                        break loop;
  16.304 +                    newline = false;
  16.305 +                    break;
  16.306 +
  16.307 +                default:
  16.308 +                    newline = false;
  16.309 +                    break;
  16.310 +            }
  16.311 +            nextChar();
  16.312 +        }
  16.313 +        throw new ParseException("dc.unterminated.inline.tag");
  16.314 +    }
  16.315 +
  16.316 +    /**
  16.317 +     * Read Java class name, possibly followed by member
  16.318 +     * Matching pairs of {@literal < >} are skipped. The text is terminated by the first
  16.319 +     * unmatched }. It is an error if the beginning of the next tag is detected.
  16.320 +     */
  16.321 +    // TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
  16.322 +    // TODO: improve quality of parse to forbid bad constructions.
  16.323 +    // TODO: update to use ReferenceParser
  16.324 +    @SuppressWarnings("fallthrough")
  16.325 +    protected void reference(boolean allowMember) throws ParseException {
  16.326 +        int pos = bp;
  16.327 +        int depth = 0;
  16.328 +
  16.329 +        // scan to find the end of the signature, by looking for the first
  16.330 +        // whitespace not enclosed in () or <>, or the end of the tag
  16.331 +        loop:
  16.332 +        while (bp < buflen) {
  16.333 +            switch (ch) {
  16.334 +                case '\n': case '\r': case '\f':
  16.335 +                    newline = true;
  16.336 +                    // fallthrough
  16.337 +
  16.338 +                case ' ': case '\t':
  16.339 +                    if (depth == 0)
  16.340 +                        break loop;
  16.341 +                    break;
  16.342 +
  16.343 +                case '(':
  16.344 +                case '<':
  16.345 +                    newline = false;
  16.346 +                    depth++;
  16.347 +                    break;
  16.348 +
  16.349 +                case ')':
  16.350 +                case '>':
  16.351 +                    newline = false;
  16.352 +                    --depth;
  16.353 +                    break;
  16.354 +
  16.355 +                case '}':
  16.356 +                    if (bp == pos)
  16.357 +                        return;
  16.358 +                    newline = false;
  16.359 +                    break loop;
  16.360 +
  16.361 +                case '@':
  16.362 +                    if (newline)
  16.363 +                        break loop;
  16.364 +                    // fallthrough
  16.365 +
  16.366 +                default:
  16.367 +                    newline = false;
  16.368 +
  16.369 +            }
  16.370 +            nextChar();
  16.371 +        }
  16.372 +
  16.373 +        if (depth != 0)
  16.374 +            throw new ParseException("dc.unterminated.signature");
  16.375 +    }
  16.376 +
  16.377 +    /**
  16.378 +     * Read Java identifier
  16.379 +     * Matching pairs of { } are skipped; the text is terminated by the first
  16.380 +     * unmatched }. It is an error if the beginning of the next tag is detected.
  16.381 +     */
  16.382 +    @SuppressWarnings("fallthrough")
  16.383 +    protected void identifier() throws ParseException {
  16.384 +        skipWhitespace();
  16.385 +        int pos = bp;
  16.386 +
  16.387 +        if (isJavaIdentifierStart(ch)) {
  16.388 +            readJavaIdentifier();
  16.389 +            return;
  16.390 +        }
  16.391 +
  16.392 +        throw new ParseException("dc.identifier.expected");
  16.393 +    }
  16.394 +
  16.395 +    /**
  16.396 +     * Read a quoted string.
  16.397 +     * It is an error if the beginning of the next tag is detected.
  16.398 +     */
  16.399 +    @SuppressWarnings("fallthrough")
  16.400 +    protected void quotedString() {
  16.401 +        int pos = bp;
  16.402 +        nextChar();
  16.403 +
  16.404 +        loop:
  16.405 +        while (bp < buflen) {
  16.406 +            switch (ch) {
  16.407 +                case '\n': case '\r': case '\f':
  16.408 +                    newline = true;
  16.409 +                    break;
  16.410 +
  16.411 +                case ' ': case '\t':
  16.412 +                    break;
  16.413 +
  16.414 +                case '"':
  16.415 +                    nextChar();
  16.416 +                    // trim trailing white-space?
  16.417 +                    return;
  16.418 +
  16.419 +                case '@':
  16.420 +                    if (newline)
  16.421 +                        break loop;
  16.422 +
  16.423 +            }
  16.424 +            nextChar();
  16.425 +        }
  16.426 +    }
  16.427 +
  16.428 +    /**
  16.429 +     * Read a term ie. one word.
  16.430 +     * It is an error if the beginning of the next tag is detected.
  16.431 +     */
  16.432 +    @SuppressWarnings("fallthrough")
  16.433 +    protected void inlineWord() {
  16.434 +        int pos = bp;
  16.435 +        int depth = 0;
  16.436 +        loop:
  16.437 +        while (bp < buflen) {
  16.438 +            switch (ch) {
  16.439 +                case '\n':
  16.440 +                    newline = true;
  16.441 +                    // fallthrough
  16.442 +
  16.443 +                case '\r': case '\f': case ' ': case '\t':
  16.444 +                    return;
  16.445 +
  16.446 +                case '@':
  16.447 +                    if (newline)
  16.448 +                        break loop;
  16.449 +
  16.450 +                case '{':
  16.451 +                    depth++;
  16.452 +                    break;
  16.453 +
  16.454 +                case '}':
  16.455 +                    if (depth == 0 || --depth == 0)
  16.456 +                        return;
  16.457 +                    break;
  16.458 +            }
  16.459 +            newline = false;
  16.460 +            nextChar();
  16.461 +        }
  16.462 +    }
  16.463 +
  16.464 +    /**
  16.465 +     * Read general text content of an inline tag, including HTML entities and elements.
  16.466 +     * Matching pairs of { } are skipped; the text is terminated by the first
  16.467 +     * unmatched }. It is an error if the beginning of the next tag is detected.
  16.468 +     */
  16.469 +    @SuppressWarnings("fallthrough")
  16.470 +    private void inlineContent() {
  16.471 +
  16.472 +        skipWhitespace();
  16.473 +        int pos = bp;
  16.474 +        int depth = 1;
  16.475 +
  16.476 +        loop:
  16.477 +        while (bp < buflen) {
  16.478 +
  16.479 +            switch (ch) {
  16.480 +                case '\n': case '\r': case '\f':
  16.481 +                    newline = true;
  16.482 +                    // fall through
  16.483 +
  16.484 +                case ' ': case '\t':
  16.485 +                    nextChar();
  16.486 +                    break;
  16.487 +
  16.488 +                case '&':
  16.489 +                    entity(null);
  16.490 +                    break;
  16.491 +
  16.492 +                case '<':
  16.493 +                    newline = false;
  16.494 +                    html();
  16.495 +                    break;
  16.496 +
  16.497 +                case '{':
  16.498 +                    newline = false;
  16.499 +                    depth++;
  16.500 +                    nextChar();
  16.501 +                    break;
  16.502 +
  16.503 +                case '}':
  16.504 +                    newline = false;
  16.505 +                    if (--depth == 0) {
  16.506 +                        nextChar();
  16.507 +                        return;
  16.508 +                    }
  16.509 +                    nextChar();
  16.510 +                    break;
  16.511 +
  16.512 +                case '@':
  16.513 +                    if (newline)
  16.514 +                        break loop;
  16.515 +                    // fallthrough
  16.516 +
  16.517 +                default:
  16.518 +                    nextChar();
  16.519 +                    break;
  16.520 +            }
  16.521 +        }
  16.522 +
  16.523 +    }
  16.524 +
  16.525 +    protected void entity(Void list) {
  16.526 +        newline = false;
  16.527 +        entity();
  16.528 +    }
  16.529 +
  16.530 +    /**
  16.531 +     * Read an HTML entity.
  16.532 +     * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; }
  16.533 +     */
  16.534 +    protected void entity() {
  16.535 +        nextChar();
  16.536 +        String name = null;
  16.537 +        if (ch == '#') {
  16.538 +            int namep = bp;
  16.539 +            nextChar();
  16.540 +            if (isDecimalDigit(ch)) {
  16.541 +                nextChar();
  16.542 +                while (isDecimalDigit(ch))
  16.543 +                    nextChar();
  16.544 +                name = new String(buf, namep, bp - namep);
  16.545 +            } else if (ch == 'x' || ch == 'X') {
  16.546 +                nextChar();
  16.547 +                if (isHexDigit(ch)) {
  16.548 +                    nextChar();
  16.549 +                    while (isHexDigit(ch))
  16.550 +                        nextChar();
  16.551 +                    name = new String(buf, namep, bp - namep);
  16.552 +                }
  16.553 +            }
  16.554 +        } else if (isIdentifierStart(ch)) {
  16.555 +            name = readIdentifier();
  16.556 +        }
  16.557 +
  16.558 +        if (name != null) {
  16.559 +            if (ch != ';')
  16.560 +                return;
  16.561 +            nextChar();
  16.562 +        }
  16.563 +    }
  16.564 +
  16.565 +    /**
  16.566 +     * Read the start or end of an HTML tag, or an HTML comment
  16.567 +     * {@literal <identifier attrs> } or {@literal </identifier> }
  16.568 +     */
  16.569 +    protected void html() {
  16.570 +        int p = bp;
  16.571 +        nextChar();
  16.572 +        if (isIdentifierStart(ch)) {
  16.573 +            String name = readIdentifier();
  16.574 +            checkHtmlTag(name);
  16.575 +            htmlAttrs();
  16.576 +            if (ch == '/') {
  16.577 +                nextChar();
  16.578 +            }
  16.579 +            if (ch == '>') {
  16.580 +                nextChar();
  16.581 +                return;
  16.582 +            }
  16.583 +        } else if (ch == '/') {
  16.584 +            nextChar();
  16.585 +            if (isIdentifierStart(ch)) {
  16.586 +                readIdentifier();
  16.587 +                skipWhitespace();
  16.588 +                if (ch == '>') {
  16.589 +                    nextChar();
  16.590 +                    return;
  16.591 +                }
  16.592 +            }
  16.593 +        } else if (ch == '!') {
  16.594 +            nextChar();
  16.595 +            if (ch == '-') {
  16.596 +                nextChar();
  16.597 +                if (ch == '-') {
  16.598 +                    nextChar();
  16.599 +                    while (bp < buflen) {
  16.600 +                        int dash = 0;
  16.601 +                        while (ch == '-') {
  16.602 +                            dash++;
  16.603 +                            nextChar();
  16.604 +                        }
  16.605 +                        // Strictly speaking, a comment should not contain "--"
  16.606 +                        // so dash > 2 is an error, dash == 2 implies ch == '>'
  16.607 +                        // See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments
  16.608 +                        // for more details.
  16.609 +                        if (dash >= 2 && ch == '>') {
  16.610 +                            nextChar();
  16.611 +                            return;
  16.612 +                        }
  16.613 +
  16.614 +                        nextChar();
  16.615 +                    }
  16.616 +                }
  16.617 +            }
  16.618 +        }
  16.619 +
  16.620 +        bp = p + 1;
  16.621 +        ch = buf[bp];
  16.622 +    }
  16.623 +
  16.624 +    /**
  16.625 +     * Read a series of HTML attributes, terminated by {@literal > }.
  16.626 +     * Each attribute is of the form {@literal identifier[=value] }.
  16.627 +     * "value" may be unquoted, single-quoted, or double-quoted.
  16.628 +     */
  16.629 +    protected void htmlAttrs() {
  16.630 +        skipWhitespace();
  16.631 +
  16.632 +        loop:
  16.633 +        while (isIdentifierStart(ch)) {
  16.634 +            int namePos = bp;
  16.635 +            String name = readAttributeName();
  16.636 +            skipWhitespace();
  16.637 +            StringBuilder value = new StringBuilder();
  16.638 +            if (ch == '=') {
  16.639 +                nextChar();
  16.640 +                skipWhitespace();
  16.641 +                if (ch == '\'' || ch == '"') {
  16.642 +                    char quote = ch;
  16.643 +                    nextChar();
  16.644 +                    while (bp < buflen && ch != quote) {
  16.645 +                        if (newline && ch == '@') {
  16.646 +                            // No point trying to read more.
  16.647 +                            // In fact, all attrs get discarded by the caller
  16.648 +                            // and superseded by a malformed.html node because
  16.649 +                            // the html tag itself is not terminated correctly.
  16.650 +                            break loop;
  16.651 +                        }
  16.652 +                        value.append(ch);
  16.653 +                        nextChar();
  16.654 +                    }
  16.655 +                    nextChar();
  16.656 +                } else {
  16.657 +                    while (bp < buflen && !isUnquotedAttrValueTerminator(ch)) {
  16.658 +                        value.append(ch);
  16.659 +                        nextChar();
  16.660 +                    }
  16.661 +                }
  16.662 +                skipWhitespace();
  16.663 +            }
  16.664 +            checkHtmlAttr(name, value.toString());
  16.665 +        }
  16.666 +    }
  16.667 +
  16.668 +    protected void attrValueChar(Void list) {
  16.669 +        switch (ch) {
  16.670 +            case '&':
  16.671 +                entity(list);
  16.672 +                break;
  16.673 +
  16.674 +            case '{':
  16.675 +                inlineTag(list);
  16.676 +                break;
  16.677 +
  16.678 +            default:
  16.679 +                nextChar();
  16.680 +        }
  16.681 +    }
  16.682 +
  16.683 +    protected boolean isIdentifierStart(char ch) {
  16.684 +        return Character.isUnicodeIdentifierStart(ch);
  16.685 +    }
  16.686 +
  16.687 +    protected String readIdentifier() {
  16.688 +        int start = bp;
  16.689 +        nextChar();
  16.690 +        while (bp < buflen && Character.isUnicodeIdentifierPart(ch))
  16.691 +            nextChar();
  16.692 +        return new String(buf, start, bp - start);
  16.693 +    }
  16.694 +
  16.695 +    protected String readAttributeName() {
  16.696 +        int start = bp;
  16.697 +        nextChar();
  16.698 +        while (bp < buflen && (Character.isUnicodeIdentifierPart(ch) || ch == '-'))
  16.699 +            nextChar();
  16.700 +        return new String(buf, start, bp - start);
  16.701 +    }
  16.702 +
  16.703 +    protected String readTagName() {
  16.704 +        int start = bp;
  16.705 +        nextChar();
  16.706 +        while (bp < buflen
  16.707 +                && (Character.isUnicodeIdentifierPart(ch) || ch == '.'
  16.708 +                || ch == '-' || ch == ':')) {
  16.709 +            nextChar();
  16.710 +        }
  16.711 +        return new String(buf, start, bp - start);
  16.712 +    }
  16.713 +
  16.714 +    protected boolean isJavaIdentifierStart(char ch) {
  16.715 +        return Character.isJavaIdentifierStart(ch);
  16.716 +    }
  16.717 +
  16.718 +    protected String readJavaIdentifier() {
  16.719 +        int start = bp;
  16.720 +        nextChar();
  16.721 +        while (bp < buflen && Character.isJavaIdentifierPart(ch))
  16.722 +            nextChar();
  16.723 +        return new String(buf, start, bp - start);
  16.724 +    }
  16.725 +
  16.726 +    protected boolean isDecimalDigit(char ch) {
  16.727 +        return ('0' <= ch && ch <= '9');
  16.728 +    }
  16.729 +
  16.730 +    protected boolean isHexDigit(char ch) {
  16.731 +        return ('0' <= ch && ch <= '9')
  16.732 +                || ('a' <= ch && ch <= 'f')
  16.733 +                || ('A' <= ch && ch <= 'F');
  16.734 +    }
  16.735 +
  16.736 +    protected boolean isUnquotedAttrValueTerminator(char ch) {
  16.737 +        switch (ch) {
  16.738 +            case '\f': case '\n': case '\r': case '\t':
  16.739 +            case ' ':
  16.740 +            case '"': case '\'': case '`':
  16.741 +            case '=': case '<': case '>':
  16.742 +                return true;
  16.743 +            default:
  16.744 +                return false;
  16.745 +        }
  16.746 +    }
  16.747 +
  16.748 +    protected boolean isWhitespace(char ch) {
  16.749 +        return Character.isWhitespace(ch);
  16.750 +    }
  16.751 +
  16.752 +    protected void skipWhitespace() {
  16.753 +        while (isWhitespace(ch)) {
  16.754 +            nextChar();
  16.755 +        }
  16.756 +    }
  16.757 +
  16.758 +    /**
  16.759 +     * @param start position of first character of string
  16.760 +     * @param end position of character beyond last character to be included
  16.761 +     */
  16.762 +    String newString(int start, int end) {
  16.763 +        return new String(buf, start, end - start);
  16.764 +    }
  16.765 +
  16.766 +    static abstract class TagParser {
  16.767 +        enum Kind { INLINE, BLOCK }
  16.768 +
  16.769 +        final Kind kind;
  16.770 +        final String name;
  16.771 +
  16.772 +
  16.773 +        TagParser(Kind k, String tk) {
  16.774 +            kind = k;
  16.775 +            name = tk;
  16.776 +        }
  16.777 +
  16.778 +        TagParser(Kind k, String tk, boolean retainWhiteSpace) {
  16.779 +            this(k, tk);
  16.780 +        }
  16.781 +
  16.782 +        Kind getKind() {
  16.783 +            return kind;
  16.784 +        }
  16.785 +
  16.786 +        String getName() {
  16.787 +            return name;
  16.788 +        }
  16.789 +
  16.790 +        abstract void parse(int pos) throws ParseException;
  16.791 +    }
  16.792 +
  16.793 +    /**
  16.794 +     * @see <a href="http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javadoc.html#javadoctags">Javadoc Tags</a>
  16.795 +     */
  16.796 +    @SuppressWarnings("deprecation")
  16.797 +    private void initTagParsers() {
  16.798 +        TagParser[] parsers = {
  16.799 +            // @author name-text
  16.800 +            new TagParser(Kind.BLOCK, "author") {
  16.801 +                @Override
  16.802 +                public void parse(int pos) {
  16.803 +                    blockContent();
  16.804 +                }
  16.805 +            },
  16.806 +
  16.807 +            // {@code text}
  16.808 +            new TagParser(Kind.INLINE, "code", true) {
  16.809 +                @Override
  16.810 +                public void parse(int pos) throws ParseException {
  16.811 +                    inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
  16.812 +                    nextChar();
  16.813 +                }
  16.814 +            },
  16.815 +
  16.816 +            // @deprecated deprecated-text
  16.817 +            new TagParser(Kind.BLOCK, "deprecated") {
  16.818 +                @Override
  16.819 +                public void parse(int pos) {
  16.820 +                    blockContent();
  16.821 +                }
  16.822 +            },
  16.823 +
  16.824 +            // {@docRoot}
  16.825 +            new TagParser(Kind.INLINE, "docRoot") {
  16.826 +                @Override
  16.827 +                public void parse(int pos) throws ParseException {
  16.828 +                    if (ch == '}') {
  16.829 +                        nextChar();
  16.830 +                        return;
  16.831 +                    }
  16.832 +                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
  16.833 +                    nextChar();
  16.834 +                    throw new ParseException("dc.unexpected.content");
  16.835 +                }
  16.836 +            },
  16.837 +
  16.838 +            // @exception class-name description
  16.839 +            new TagParser(Kind.BLOCK, "exception") {
  16.840 +                @Override
  16.841 +                public void parse(int pos) throws ParseException {
  16.842 +                    skipWhitespace();
  16.843 +                    reference(false);
  16.844 +                    blockContent();
  16.845 +                }
  16.846 +            },
  16.847 +
  16.848 +            // @hidden hidden-text
  16.849 +            new TagParser(Kind.BLOCK, "hidden") {
  16.850 +                @Override
  16.851 +                public void parse(int pos) {
  16.852 +                    blockContent();
  16.853 +                }
  16.854 +            },
  16.855 +
  16.856 +            // @index search-term options-description
  16.857 +            new TagParser(Kind.INLINE, "index") {
  16.858 +                @Override
  16.859 +                public void parse(int pos) throws ParseException {
  16.860 +                    skipWhitespace();
  16.861 +                    if (ch == '}') {
  16.862 +                        throw new ParseException("dc.no.content");
  16.863 +                    }
  16.864 +                    if (ch == '"') quotedString(); else inlineWord();
  16.865 +                    skipWhitespace();
  16.866 +                    if (ch != '}') {
  16.867 +                        inlineContent();
  16.868 +                    } else {
  16.869 +                        nextChar();
  16.870 +                    }
  16.871 +                }
  16.872 +            },
  16.873 +
  16.874 +            // {@inheritDoc}
  16.875 +            new TagParser(Kind.INLINE, "inheritDoc") {
  16.876 +                @Override
  16.877 +                public void parse(int pos) throws ParseException {
  16.878 +                    if (ch == '}') {
  16.879 +                        nextChar();
  16.880 +                        return;
  16.881 +                    }
  16.882 +                    inlineText(WhitespaceRetentionPolicy.REMOVE_ALL); // skip unexpected content
  16.883 +                    nextChar();
  16.884 +                    throw new ParseException("dc.unexpected.content");
  16.885 +                }
  16.886 +            },
  16.887 +
  16.888 +            // {@link package.class#member label}
  16.889 +            new TagParser(Kind.INLINE, "link") {
  16.890 +                @Override
  16.891 +                public void parse(int pos) throws ParseException {
  16.892 +                    reference(true);
  16.893 +                    inlineContent();
  16.894 +                }
  16.895 +            },
  16.896 +
  16.897 +            // {@linkplain package.class#member label}
  16.898 +            new TagParser(Kind.INLINE, "linkplain") {
  16.899 +                @Override
  16.900 +                public void parse(int pos) throws ParseException {
  16.901 +                    reference(true);
  16.902 +                    inlineContent();
  16.903 +                }
  16.904 +            },
  16.905 +
  16.906 +            // {@literal text}
  16.907 +            new TagParser(Kind.INLINE, "literal", true) {
  16.908 +                @Override
  16.909 +                public void parse(int pos) throws ParseException {
  16.910 +                    inlineText(WhitespaceRetentionPolicy.REMOVE_FIRST_SPACE);
  16.911 +                    nextChar();
  16.912 +                }
  16.913 +            },
  16.914 +
  16.915 +            // @param parameter-name description
  16.916 +            new TagParser(Kind.BLOCK, "param") {
  16.917 +                @Override
  16.918 +                public void parse(int pos) throws ParseException {
  16.919 +                    skipWhitespace();
  16.920 +
  16.921 +                    boolean typaram = false;
  16.922 +                    if (ch == '<') {
  16.923 +                        typaram = true;
  16.924 +                        nextChar();
  16.925 +                    }
  16.926 +
  16.927 +                    identifier();
  16.928 +
  16.929 +                    if (typaram) {
  16.930 +                        if (ch != '>')
  16.931 +                            throw new ParseException("dc.gt.expected");
  16.932 +                        nextChar();
  16.933 +                    }
  16.934 +
  16.935 +                    skipWhitespace();
  16.936 +                    blockContent();
  16.937 +                }
  16.938 +            },
  16.939 +
  16.940 +            // @return description
  16.941 +            new TagParser(Kind.BLOCK, "return") {
  16.942 +                @Override
  16.943 +                public void parse(int pos) {
  16.944 +                    blockContent();
  16.945 +                }
  16.946 +            },
  16.947 +
  16.948 +            // @see reference | quoted-string | HTML
  16.949 +            new TagParser(Kind.BLOCK, "see") {
  16.950 +                @Override
  16.951 +                public void parse(int pos) throws ParseException {
  16.952 +                    skipWhitespace();
  16.953 +                    switch (ch) {
  16.954 +                        case '"':
  16.955 +                            quotedString();
  16.956 +                            skipWhitespace();
  16.957 +                            if (ch == '@'
  16.958 +                                    || ch == EOI && bp == buf.length - 1) {
  16.959 +                                return;
  16.960 +                            }
  16.961 +                            break;
  16.962 +
  16.963 +                        case '<':
  16.964 +                            blockContent();
  16.965 +                            return;
  16.966 +
  16.967 +                        case '@':
  16.968 +                            if (newline)
  16.969 +                                throw new ParseException("dc.no.content");
  16.970 +                            break;
  16.971 +
  16.972 +                        case EOI:
  16.973 +                            if (bp == buf.length - 1)
  16.974 +                                throw new ParseException("dc.no.content");
  16.975 +                            break;
  16.976 +
  16.977 +                        default:
  16.978 +                            if (isJavaIdentifierStart(ch) || ch == '#') {
  16.979 +                                reference(true);
  16.980 +                                blockContent();
  16.981 +                            }
  16.982 +                    }
  16.983 +                    throw new ParseException("dc.unexpected.content");
  16.984 +                }
  16.985 +            },
  16.986 +
  16.987 +            // @serialData data-description
  16.988 +            new TagParser(Kind.BLOCK, "@serialData") {
  16.989 +                @Override
  16.990 +                public void parse(int pos) {
  16.991 +                    blockContent();
  16.992 +                }
  16.993 +            },
  16.994 +
  16.995 +            // @serialField field-name field-type description
  16.996 +            new TagParser(Kind.BLOCK, "serialField") {
  16.997 +                @Override
  16.998 +                public void parse(int pos) throws ParseException {
  16.999 +                    skipWhitespace();
 16.1000 +                    identifier();
 16.1001 +                    skipWhitespace();
 16.1002 +                    reference(false);
 16.1003 +                    if (isWhitespace(ch)) {
 16.1004 +                        skipWhitespace();
 16.1005 +                        blockContent();
 16.1006 +                    }
 16.1007 +                }
 16.1008 +            },
 16.1009 +
 16.1010 +            // @serial field-description | include | exclude
 16.1011 +            new TagParser(Kind.BLOCK, "serial") {
 16.1012 +                @Override
 16.1013 +                public void parse(int pos) {
 16.1014 +                    blockContent();
 16.1015 +                }
 16.1016 +            },
 16.1017 +
 16.1018 +            // @since since-text
 16.1019 +            new TagParser(Kind.BLOCK, "since") {
 16.1020 +                @Override
 16.1021 +                public void parse(int pos) {
 16.1022 +                    blockContent();
 16.1023 +                }
 16.1024 +            },
 16.1025 +
 16.1026 +            // @throws class-name description
 16.1027 +            new TagParser(Kind.BLOCK, "throws") {
 16.1028 +                @Override
 16.1029 +                public void parse(int pos) throws ParseException {
 16.1030 +                    skipWhitespace();
 16.1031 +                    reference(false);
 16.1032 +                    blockContent();
 16.1033 +                }
 16.1034 +            },
 16.1035 +
 16.1036 +            // {@value package.class#field}
 16.1037 +            new TagParser(Kind.INLINE, "value") {
 16.1038 +                @Override
 16.1039 +                public void parse(int pos) throws ParseException {
 16.1040 +                    reference(true);
 16.1041 +                    skipWhitespace();
 16.1042 +                    if (ch == '}') {
 16.1043 +                        nextChar();
 16.1044 +                        return;
 16.1045 +                    }
 16.1046 +                    nextChar();
 16.1047 +                    throw new ParseException("dc.unexpected.content");
 16.1048 +                }
 16.1049 +            },
 16.1050 +
 16.1051 +            // @version version-text
 16.1052 +            new TagParser(Kind.BLOCK, "version") {
 16.1053 +                @Override
 16.1054 +                public void parse(int pos) {
 16.1055 +                    blockContent();
 16.1056 +                }
 16.1057 +            },
 16.1058 +        };
 16.1059 +
 16.1060 +        tagParsers = new HashMap<>();
 16.1061 +        for (TagParser p: parsers)
 16.1062 +            tagParsers.put(p.getName(), p);
 16.1063 +
 16.1064 +    }
 16.1065 +
 16.1066 +    private void initEventAttrs() {
 16.1067 +        eventAttrs = new HashSet<>(Arrays.asList(
 16.1068 +            // See https://www.w3.org/TR/html-markup/global-attributes.html#common.attrs.event-handler
 16.1069 +            "onabort",  "onblur",  "oncanplay",  "oncanplaythrough",
 16.1070 +            "onchange",  "onclick",  "oncontextmenu",  "ondblclick",
 16.1071 +            "ondrag",  "ondragend",  "ondragenter",  "ondragleave",
 16.1072 +            "ondragover",  "ondragstart",  "ondrop",  "ondurationchange",
 16.1073 +            "onemptied",  "onended",  "onerror",  "onfocus",  "oninput",
 16.1074 +            "oninvalid",  "onkeydown",  "onkeypress",  "onkeyup",
 16.1075 +            "onload",  "onloadeddata",  "onloadedmetadata",  "onloadstart",
 16.1076 +            "onmousedown",  "onmousemove",  "onmouseout",  "onmouseover",
 16.1077 +            "onmouseup",  "onmousewheel",  "onpause",  "onplay",
 16.1078 +            "onplaying",  "onprogress",  "onratechange",  "onreadystatechange",
 16.1079 +            "onreset",  "onscroll",  "onseeked",  "onseeking",
 16.1080 +            "onselect",  "onshow",  "onstalled",  "onsubmit",  "onsuspend",
 16.1081 +            "ontimeupdate",  "onvolumechange",  "onwaiting",
 16.1082 +
 16.1083 +            // See https://www.w3.org/TR/html4/sgml/dtd.html
 16.1084 +            // Most of the attributes that take a %Script are also defined as event handlers
 16.1085 +            // in HTML 5. The one exception is onunload.
 16.1086 +            // "onchange",  "onclick",   "ondblclick",  "onfocus",
 16.1087 +            // "onkeydown",  "onkeypress",  "onkeyup",  "onload",
 16.1088 +            // "onmousedown",  "onmousemove",  "onmouseout",  "onmouseover",
 16.1089 +            // "onmouseup",  "onreset",  "onselect",  "onsubmit",
 16.1090 +            "onunload"
 16.1091 +        ));
 16.1092 +    }
 16.1093 +
 16.1094 +    private void initURIAttrs() {
 16.1095 +        uriAttrs = new HashSet<>(Arrays.asList(
 16.1096 +            // See https://www.w3.org/TR/html4/sgml/dtd.html
 16.1097 +            //     https://www.w3.org/TR/html5/
 16.1098 +            // These are all the attributes that take a %URI or a valid URL potentially surrounded
 16.1099 +            // by spaces
 16.1100 +            "action",  "cite",  "classid",  "codebase",  "data",
 16.1101 +            "datasrc",  "for",  "href",  "longdesc",  "profile",
 16.1102 +            "src",  "usemap"
 16.1103 +        ));
 16.1104 +    }
 16.1105 +
 16.1106 +}
    17.1 --- a/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java	Tue Dec 20 15:24:55 2016 -0800
    17.2 +++ b/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java	Thu Dec 22 16:21:25 2016 -0800
    17.3 @@ -1,5 +1,5 @@
    17.4  /*
    17.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    17.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
    17.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.8   *
    17.9   * This code is free software; you can redistribute it and/or modify it
   17.10 @@ -381,6 +381,10 @@
   17.11          env.initDoclint(opts, customTagNames);
   17.12      }
   17.13  
   17.14 +    public JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) {
   17.15 +        return env.initJavaScriptScanner(allowScriptInComments);
   17.16 +    }
   17.17 +
   17.18      public boolean isFunctionalInterface(AnnotationDesc annotationDesc) {
   17.19          return annotationDesc.annotationType().qualifiedName().equals(
   17.20                  env.syms.functionalInterfaceType.toString()) && env.source.allowLambda();
    18.1 --- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties	Tue Dec 20 15:24:55 2016 -0800
    18.2 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties	Thu Dec 22 16:21:25 2016 -0800
    18.3 @@ -1,5 +1,5 @@
    18.4  #
    18.5 -# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    18.6 +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
    18.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.8  #
    18.9  # This code is free software; you can redistribute it and/or modify it
   18.10 @@ -110,6 +110,8 @@
   18.11  javadoc.Body_missing_from_html_file=Body tag missing from HTML file
   18.12  javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file
   18.13  javadoc.Multiple_package_comments=Multiple sources of package comments found for package "{0}"
   18.14 +javadoc.JavaScript_in_comment=JavaScript found in documentation comment.\n\
   18.15 +    Use --allow-script-in-comments to allow use of JavaScript.
   18.16  javadoc.class_not_found=Class {0} not found.
   18.17  javadoc.error=error
   18.18  javadoc.warning=warning
    19.1 --- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties	Tue Dec 20 15:24:55 2016 -0800
    19.2 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties	Thu Dec 22 16:21:25 2016 -0800
    19.3 @@ -1,5 +1,5 @@
    19.4  #
    19.5 -# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
    19.6 +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
    19.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.8  #
    19.9  # This code is free software; you can redistribute it and/or modify it
   19.10 @@ -81,6 +81,7 @@
   19.11  javadoc.Body_missing_from_html_file=HTML\u306Bbody\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
   19.12  javadoc.End_body_missing_from_html_file=HTML\u30D5\u30A1\u30A4\u30EB\u306Bbody\u306E\u9589\u3058\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093
   19.13  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
   19.14 +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
   19.15  javadoc.class_not_found=\u30AF\u30E9\u30B9{0}\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
   19.16  javadoc.error=\u30A8\u30E9\u30FC
   19.17  javadoc.warning=\u8B66\u544A
    20.1 --- a/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties	Tue Dec 20 15:24:55 2016 -0800
    20.2 +++ b/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties	Thu Dec 22 16:21:25 2016 -0800
    20.3 @@ -1,5 +1,5 @@
    20.4  #
    20.5 -# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    20.6 +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
    20.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.8  #
    20.9  # This code is free software; you can redistribute it and/or modify it
   20.10 @@ -81,6 +81,7 @@
   20.11  javadoc.Body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u6807\u8BB0
   20.12  javadoc.End_body_missing_from_html_file=HTML \u6587\u4EF6\u4E2D\u7F3A\u5C11\u4E3B\u4F53\u7ED3\u675F\u6807\u8BB0
   20.13  javadoc.Multiple_package_comments=\u627E\u5230\u7A0B\u5E8F\u5305 "{0}" \u7684\u591A\u4E2A\u7A0B\u5E8F\u5305\u6CE8\u91CA\u6E90
   20.14 +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
   20.15  javadoc.class_not_found=\u627E\u4E0D\u5230\u7C7B{0}\u3002
   20.16  javadoc.error=\u9519\u8BEF
   20.17  javadoc.warning=\u8B66\u544A
    21.1 --- a/test/tools/doclint/html/OtherTagsTest.out	Tue Dec 20 15:24:55 2016 -0800
    21.2 +++ b/test/tools/doclint/html/OtherTagsTest.out	Thu Dec 22 16:21:25 2016 -0800
    21.3 @@ -19,10 +19,7 @@
    21.4  OtherTagsTest.java:20: error: element not allowed in documentation comments: <noframes>
    21.5       *  <noframes> </noframes>
    21.6          ^
    21.7 -OtherTagsTest.java:21: error: element not allowed in documentation comments: <script>
    21.8 -     *  <script> </script>
    21.9 -        ^
   21.10  OtherTagsTest.java:22: error: element not allowed in documentation comments: <title>
   21.11       *  <title> </title>
   21.12          ^
   21.13 -9 errors
   21.14 +8 errors
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/tools/javadoc/TestScriptInComment.java	Thu Dec 22 16:21:25 2016 -0800
    22.3 @@ -0,0 +1,314 @@
    22.4 +/*
    22.5 + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.  Oracle designates this
   22.11 + * particular file as subject to the "Classpath" exception as provided
   22.12 + * by Oracle in the LICENSE file that accompanied this code.
   22.13 + *
   22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 + * version 2 for more details (a copy is included in the LICENSE file that
   22.18 + * accompanied this code).
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License version
   22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 + *
   22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22.25 + * or visit www.oracle.com if you need additional information or have any
   22.26 + * questions.
   22.27 + */
   22.28 +
   22.29 +/**
   22.30 + * @test
   22.31 + * @bug 8138725
   22.32 + * @summary test --allow-script-in-comments
   22.33 + * @run main TestScriptInComment
   22.34 + */
   22.35 +
   22.36 +import java.io.File;
   22.37 +import java.io.FileWriter;
   22.38 +import java.io.IOException;
   22.39 +import java.io.PrintStream;
   22.40 +import java.io.PrintWriter;
   22.41 +import java.io.StringWriter;
   22.42 +import java.util.ArrayList;
   22.43 +import java.util.Arrays;
   22.44 +import java.util.Collections;
   22.45 +import java.util.List;
   22.46 +import java.util.regex.Matcher;
   22.47 +import java.util.regex.Pattern;
   22.48 +
   22.49 +/**
   22.50 + * Combo-style test, exercising combinations of different HTML fragments that may contain
   22.51 + * JavaScript, different places to place those fragments, and whether or not to allow the use
   22.52 + * of JavaScript.
   22.53 + */
   22.54 +public class TestScriptInComment {
   22.55 +    public static void main(String... args) throws Exception {
   22.56 +        new TestScriptInComment().run();
   22.57 +    }
   22.58 +
   22.59 +    /**
   22.60 +     * Representative samples of different fragments of HTML that may contain JavaScript.
   22.61 +     * To facilitate checking the output manually in a browser, the text "#ALERT" will be
   22.62 +     * replaced by a JavaScript call of "alert(msg)", using a message string that is specific
   22.63 +     * to the test case.
   22.64 +     */
   22.65 +    enum Comment {
   22.66 +        LC("<script>#ALERT</script>", true), // script tag in Lower Case
   22.67 +        UC("<SCRIPT>#ALERT</script>", true), // script tag in Upper Case
   22.68 +        WS("< script >#ALERT</script>", false, "-Xdoclint:none"), // script tag with invalid white space
   22.69 +        SA("<script src=\"file\"> #ALERT </script>", true), // script tag with an attribute
   22.70 +        ON("<a onclick='#ALERT'>x</a>", true), // event handler attribute
   22.71 +        URI("<a href='javascript:#ALERT'>x</a>", true); // javadcript URI
   22.72 +
   22.73 +        /**
   22.74 +         * Creates an HTML fragment to be injected into a template.
   22.75 +         * @param text the HTML fragment to put into a doc comment or option.
   22.76 +         * @param hasScript whether or not this fragment does contain legal JavaScript
   22.77 +         * @param opts any additional options to be specified when javadoc is run
   22.78 +         */
   22.79 +        Comment(String text, boolean hasScript, String... opts) {
   22.80 +            this.text = text;
   22.81 +            this.hasScript = hasScript;
   22.82 +            this.opts = Arrays.asList(opts);
   22.83 +        }
   22.84 +
   22.85 +        final String text;
   22.86 +        final boolean hasScript;
   22.87 +        final List<String> opts;
   22.88 +    };
   22.89 +
   22.90 +    /**
   22.91 +     * Representative samples of positions in which javadoc may find JavaScript.
   22.92 +     * Each template contains a series of strings, which are written to files or inferred as options.
   22.93 +     * The first source file implies a corresponding output file which should not be written
   22.94 +     * if the comment contains JavaScript and JavaScript is not allowed.
   22.95 +     */
   22.96 +    enum Template {
   22.97 +        OVR("<html><body> overview #COMMENT </body></html>", "package p; public class C { }"),
   22.98 +        PKGINFO("#COMMENT package p;", "package p; public class C { }"),
   22.99 +        PKGHTML("<html><body>#COMMENT package p;</body></html>", "package p; public class C { }"),
  22.100 +        CLS("package p; #COMMENT public class C { }"),
  22.101 +        CON("package p; public class C { #COMMENT public C() { } }"),
  22.102 +        FLD("package p; public class C { #COMMENT public int f; }"),
  22.103 +        MTH("package p; public class C { #COMMENT public void m() { } }"),
  22.104 +        TOP("-top", "lorem #COMMENT ipsum", "package p; public class C { }"),
  22.105 +        HDR("-header", "lorem #COMMENT ipsum", "package p; public class C { }"),
  22.106 +        FTR("-footer", "lorem #COMMENT ipsum", "package p; public class C { }"),
  22.107 +        BTM("-bottom", "lorem #COMMENT ipsum", "package p; public class C { }"),
  22.108 +        DTTL("-doctitle", "lorem #COMMENT ipsum", "package p; public class C { }"),
  22.109 +        PHDR("-packagesheader", "lorem #COMMENT ipsum", "package p; public class C { }");
  22.110 +
  22.111 +        Template(String... args) {
  22.112 +            opts = new ArrayList<String>();
  22.113 +            sources = new ArrayList<String>();
  22.114 +            int i = 0;
  22.115 +            while (args[i].startsWith("-")) {
  22.116 +                // all options being tested have a single argument that follow the option
  22.117 +                opts.add(args[i++]);
  22.118 +                opts.add(args[i++]);
  22.119 +            }
  22.120 +            while(i < args.length) {
  22.121 +                sources.add(args[i++]);
  22.122 +            }
  22.123 +        }
  22.124 +
  22.125 +        // groups: 1 <html> or not;  2: package name;  3: class name
  22.126 +        private final Pattern pat =
  22.127 +                Pattern.compile("(?i)(<html>)?.*?(?:package ([a-z]+);.*?(?:class ([a-z]+).*)?)?");
  22.128 +
  22.129 +        /**
  22.130 +         * Infer the file in which to write the given source.
  22.131 +         * @param dir the base source directory
  22.132 +         * @param src the source text
  22.133 +         * @return the file in which the source should be written
  22.134 +         */
  22.135 +        File getSrcFile(File srcDir, String src) {
  22.136 +            String f;
  22.137 +            Matcher m = pat.matcher(src);
  22.138 +            if (!m.matches())
  22.139 +                throw new Error("match failed");
  22.140 +            if (m.group(3) != null) {
  22.141 +                f = m.group(2) + "/" + m.group(3) + ".java";
  22.142 +            } else if (m.group(2) != null) {
  22.143 +                f = m.group(2) + "/" + (m.group(1) == null ? "package-info.java" : "package.html");
  22.144 +            } else {
  22.145 +                f = "overview.html";
  22.146 +            }
  22.147 +            return new File(srcDir, f);
  22.148 +        }
  22.149 +
  22.150 +        /**
  22.151 +         * Get the options to give to javadoc.
  22.152 +         * @param srcDir the srcDir to use -overview is needed
  22.153 +         * @return
  22.154 +         */
  22.155 +        List<String> getOpts(File srcDir) {
  22.156 +            if (!opts.isEmpty()) {
  22.157 +                return opts;
  22.158 +            } else if (sources.get(0).contains("overview")) {
  22.159 +                return Arrays.asList("-overview", getSrcFile(srcDir, sources.get(0)).getPath());
  22.160 +            } else {
  22.161 +                return Collections.emptyList();
  22.162 +            }
  22.163 +        }
  22.164 +
  22.165 +        /**
  22.166 +         * Gets the output file corresponding to the first source file.
  22.167 +         * This file should not be written if the comment contains JavaScript and JavaScripot is
  22.168 +         * not allowed.
  22.169 +         * @param dir the base output directory
  22.170 +         * @return the output file
  22.171 +         */
  22.172 +        File getOutFile(File outDir) {
  22.173 +            String f;
  22.174 +            Matcher m = pat.matcher(sources.get(0));
  22.175 +            if (!m.matches())
  22.176 +                throw new Error("match failed");
  22.177 +            if (m.group(3) != null) {
  22.178 +                f = m.group(2) + "/" + m.group(3) + ".html";
  22.179 +            } else if (m.group(2) != null) {
  22.180 +                f = m.group(2) + "/package-summary.html";
  22.181 +            } else {
  22.182 +                f = "overview-summary.html";
  22.183 +            }
  22.184 +            return new File(outDir, f);
  22.185 +        }
  22.186 +
  22.187 +        final List<String> opts;
  22.188 +        final List<String> sources;
  22.189 +    };
  22.190 +
  22.191 +    enum Option {
  22.192 +        OFF(null),
  22.193 +        ON("--allow-script-in-comments");
  22.194 +
  22.195 +        Option(String text) {
  22.196 +            this.text = text;
  22.197 +        }
  22.198 +
  22.199 +        final String text;
  22.200 +    };
  22.201 +
  22.202 +    private PrintStream out = System.err;
  22.203 +
  22.204 +    public void run() throws Exception {
  22.205 +        int count = 0;
  22.206 +        for (Template template: Template.values()) {
  22.207 +            for (Comment comment: Comment.values()) {
  22.208 +                for (Option option: Option.values()) {
  22.209 +                    if (test(template, comment, option)) {
  22.210 +                        count++;
  22.211 +                    }
  22.212 +                }
  22.213 +            }
  22.214 +        }
  22.215 +
  22.216 +        out.println(count + " test cases run");
  22.217 +        if (errors > 0) {
  22.218 +            throw new Exception(errors + " errors occurred");
  22.219 +        }
  22.220 +    }
  22.221 +
  22.222 +    boolean test(Template template, Comment comment, Option option) throws IOException {
  22.223 +        if (option == Option.ON && !comment.hasScript) {
  22.224 +            // skip --allowScriptInComments if comment does not contain JavaScript
  22.225 +            return false;
  22.226 +        }
  22.227 +
  22.228 +        String test = template + "-" + comment + "-" + option;
  22.229 +        out.println("Test: " + test);
  22.230 +
  22.231 +        File dir = new File(test);
  22.232 +        dir.mkdirs();
  22.233 +        File srcDir = new File(dir, "src");
  22.234 +        File outDir = new File(dir, "out");
  22.235 +
  22.236 +        String alert = "alert(\"" + test + "\");";
  22.237 +        for (String src: template.sources) {
  22.238 +            writeFile(template.getSrcFile(srcDir, src),
  22.239 +                src.replace("#COMMENT",
  22.240 +                        "/** " + comment.text.replace("#ALERT", alert) + " **/"));
  22.241 +        }
  22.242 +
  22.243 +        List<String> opts = new ArrayList<String>();
  22.244 +        opts.add("-sourcepath");
  22.245 +        opts.add(srcDir.getPath());
  22.246 +        opts.add("-d");
  22.247 +        opts.add(outDir.getPath());
  22.248 +        if (option.text != null)
  22.249 +            opts.add(option.text);
  22.250 +        for (String opt: template.getOpts(srcDir)) {
  22.251 +            opts.add(opt.replace("#COMMENT", comment.text.replace("#ALERT", alert)));
  22.252 +        }
  22.253 +        opts.addAll(comment.opts);
  22.254 +        opts.add("-noindex");   // index not required; save time/space writing files
  22.255 +        opts.add("p");
  22.256 +
  22.257 +        StringWriter sw = new StringWriter();
  22.258 +        PrintWriter pw = new PrintWriter(sw);
  22.259 +        int rc = javadoc(opts, pw);
  22.260 +        pw.close();
  22.261 +        String log = sw.toString();
  22.262 +        writeFile(new File(dir, "log.txt"), log);
  22.263 +
  22.264 +        out.println("opts: " + opts);
  22.265 +        out.println("  rc: " + rc);
  22.266 +        out.println(" log:");
  22.267 +        out.println(log);
  22.268 +
  22.269 +        String ERROR = "Use --allow-script-in-comment";
  22.270 +        File outFile = template.getOutFile(outDir);
  22.271 +
  22.272 +        boolean expectErrors = comment.hasScript && (option == Option.OFF);
  22.273 +
  22.274 +        if (expectErrors) {
  22.275 +            check(rc != 0, "unexpected exit code: " + rc);
  22.276 +            check(log.contains(ERROR), "expected error message not found");
  22.277 +            check(!outFile.exists(), "output file found unexpectedly");
  22.278 +        } else {
  22.279 +            check(rc == 0, "unexpected exit code: " + rc);
  22.280 +            check(!log.contains(ERROR), "error message found");
  22.281 +            check(outFile.exists(), "output file not found");
  22.282 +        }
  22.283 +
  22.284 +        out.println();
  22.285 +        return true;
  22.286 +    }
  22.287 +
  22.288 +    int javadoc(List<String> opts, PrintWriter pw) {
  22.289 +        return com.sun.tools.javadoc.Main.execute("javadoc", pw, pw, pw,
  22.290 +                "com.sun.tools.doclets.standard.Standard", opts.toArray(new String[opts.size()]));
  22.291 +    }
  22.292 +
  22.293 +    File writeFile(File f, String text) throws IOException {
  22.294 +        f.getParentFile().mkdirs();
  22.295 +        FileWriter fw = new FileWriter(f);
  22.296 +        try {
  22.297 +            fw.write(text);
  22.298 +        } finally {
  22.299 +            fw.close();
  22.300 +        }
  22.301 +        return f;
  22.302 +    }
  22.303 +
  22.304 +    void check(boolean cond, String errMessage) {
  22.305 +        if (!cond) {
  22.306 +            error(errMessage);
  22.307 +        }
  22.308 +    }
  22.309 +
  22.310 +    void error(String message) {
  22.311 +        out.println("Error: " + message);
  22.312 +        errors++;
  22.313 +    }
  22.314 +
  22.315 +    int errors = 0;
  22.316 +}
  22.317 +

mercurial