undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
197
test/docs/jdk/javadoc/doccheck/DocCheck.java
Normal file
197
test/docs/jdk/javadoc/doccheck/DocCheck.java
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import doccheckutils.FileChecker;
|
||||
import doccheckutils.FileProcessor;
|
||||
import doccheckutils.HtmlFileChecker;
|
||||
import doccheckutils.checkers.BadCharacterChecker;
|
||||
import doccheckutils.checkers.DocTypeChecker;
|
||||
import doccheckutils.checkers.LinkChecker;
|
||||
import doccheckutils.checkers.TidyChecker;
|
||||
import doccheckutils.checkers.ExtLinkChecker;
|
||||
import toolbox.TestRunner;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* DocCheck
|
||||
* <p>
|
||||
* For the sake of brevity, to run all of these checkers use
|
||||
* <p>
|
||||
* `make test-docs_all TEST_DEPS=docs-jdk`
|
||||
* <p>
|
||||
* This collection of tests provide a variety of checks for JDK documentation bundle.
|
||||
* <p>
|
||||
* It is meant to provide a convenient way to alert users of any errors in their documentation
|
||||
* before a push and verify the quality of the documentation.
|
||||
* It is not meant to replace more authoritative checkers; instead,
|
||||
* it is more focused on providing a convenient, easy overview of any possible issues.
|
||||
* <p>
|
||||
* It supports the following checks:
|
||||
* <p>
|
||||
* *HTML* -- We use the standard `tidy` utility to check for HTML compliance,
|
||||
* according to the declared version of HTML.
|
||||
* The output from `tidy` is analysed to generate a report summarizing any issues that were found.
|
||||
* <p>
|
||||
* Version `5.9.20` of `tidy` is expected, or the output from the `--version` option should contain the string `version 5`.
|
||||
* The test warns the user if he is using an earlier version.
|
||||
* <p>
|
||||
* *Bad Characters* -- We assumee that HTML files are encoded in UTF-8,
|
||||
* and reports any character encoding issues that it finds.
|
||||
* <p>
|
||||
* *DocType* -- We assume that HTML files should use HTML5, and reports
|
||||
* any files for which that is not the case.
|
||||
* <p>
|
||||
* *Links* -- We check links within a set of files, and reports on links
|
||||
* to external resources, without otherwise checking them.
|
||||
* <p>
|
||||
* *External Links* -- We scan the files for URLs that refer to
|
||||
* external resources, and validates those references using a "golden file" that includes a list of vetted links.
|
||||
* <p>
|
||||
* Each external reference is only checked once; but if an issue is found, all the files containing the
|
||||
* reference will be reported.
|
||||
*/
|
||||
public class DocCheck extends TestRunner {
|
||||
|
||||
private static final String DOCCHECK_DIR = System.getProperty("doccheck.dir");
|
||||
private static final Path DIR = Path.of(DOCCHECK_DIR != null ? DOCCHECK_DIR : "");
|
||||
private static final Set<String> CHECKS_LIST = new HashSet<>();
|
||||
private static Path DOCS_DIR;
|
||||
|
||||
private static boolean html;
|
||||
private static boolean links;
|
||||
private static boolean badchars;
|
||||
private static boolean doctype;
|
||||
private static boolean extlinks;
|
||||
|
||||
private List<Path> files;
|
||||
|
||||
public DocCheck() {
|
||||
super(System.err);
|
||||
init();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
chooseCheckers();
|
||||
DocCheck docCheck = new DocCheck();
|
||||
docCheck.runTests();
|
||||
}
|
||||
|
||||
private static void chooseCheckers() {
|
||||
final String checks = System.getProperty("doccheck.checks");
|
||||
|
||||
if (!checks.isEmpty()) {
|
||||
if (checks.contains(",")) {
|
||||
CHECKS_LIST.addAll(Arrays.asList(checks.split(",")));
|
||||
} else {
|
||||
CHECKS_LIST.add(checks);
|
||||
}
|
||||
}
|
||||
|
||||
if (CHECKS_LIST.contains("all")) {
|
||||
html = true;
|
||||
links = true;
|
||||
badchars = true;
|
||||
doctype = true;
|
||||
extlinks = true;
|
||||
} else {
|
||||
if (CHECKS_LIST.contains("html")) {
|
||||
html = true;
|
||||
}
|
||||
if (CHECKS_LIST.contains("links")) {
|
||||
links = true;
|
||||
}
|
||||
if (CHECKS_LIST.contains("badchars")) {
|
||||
badchars = true;
|
||||
}
|
||||
if (CHECKS_LIST.contains("doctype")) {
|
||||
doctype = true;
|
||||
}
|
||||
if (CHECKS_LIST.contains("extlinks")) {
|
||||
extlinks = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
var fileTester = new FileProcessor();
|
||||
DOCS_DIR = DocTester.resolveDocs();
|
||||
var baseDir = DOCS_DIR.resolve(DIR);
|
||||
fileTester.processFiles(baseDir);
|
||||
files = fileTester.getFiles();
|
||||
if (html) {
|
||||
new TidyChecker();
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileChecker> getCheckers() {
|
||||
|
||||
List<FileChecker> checkers = new ArrayList<>();
|
||||
if (html) {
|
||||
checkers.add(new TidyChecker());
|
||||
}
|
||||
if (links) {
|
||||
var linkChecker = new LinkChecker();
|
||||
linkChecker.setBaseDir(DOCS_DIR);
|
||||
checkers.add(new HtmlFileChecker(linkChecker, DOCS_DIR));
|
||||
}
|
||||
|
||||
if (extlinks) {
|
||||
checkers.add(new HtmlFileChecker(new ExtLinkChecker(), DOCS_DIR));
|
||||
}
|
||||
|
||||
// there should be almost nothing reported from these two checkers
|
||||
// most reports should be broken anchors/links, missing files and errors in html
|
||||
if (badchars) {
|
||||
checkers.add(new BadCharacterChecker());
|
||||
}
|
||||
if (doctype) {
|
||||
checkers.add(new HtmlFileChecker(new DocTypeChecker(), DOCS_DIR));
|
||||
}
|
||||
|
||||
return checkers;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
List<FileChecker> checkers = getCheckers();
|
||||
runCheckersSequentially(checkers);
|
||||
}
|
||||
|
||||
private void runCheckersSequentially(List<FileChecker> checkers) throws Exception {
|
||||
List<Throwable> exceptions = new ArrayList<>();
|
||||
|
||||
for (FileChecker checker : checkers) {
|
||||
try (checker) {
|
||||
checker.checkFiles(files);
|
||||
} catch (Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!exceptions.isEmpty()) {
|
||||
throw new Exception("One or more HTML checkers failed: " + exceptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
772
test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt
Normal file
772
test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
# This file is used to check external links in the JDK generated documentation
|
||||
# to prevent broken links from backsliding into the JDK source.
|
||||
#
|
||||
# The file serves as a "whitelist" of links that have been checked to be working as intended
|
||||
# and JDK developers should add external links to this file whenever they add them to their documentation.
|
||||
#
|
||||
#
|
||||
# The links in this file are checked before every release.
|
||||
#
|
||||
#
|
||||
#
|
||||
http://cldr.unicode.org/
|
||||
http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
http://docs.oracle.com/javase/feedback.html
|
||||
http://docs.oracle.com/javase/jndi/tutorial/index.html
|
||||
http://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-12.html
|
||||
http://docs.oracle.com/javase/tutorial/collections/index.html
|
||||
http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html
|
||||
http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html
|
||||
http://docs.oracle.com/javase/tutorial/jdbc/
|
||||
http://docs.oracle.com/javase/tutorial/jdbc/basics/index.html
|
||||
http://docs.oracle.com/javase/tutorial/jdbc/basics/rowset.html
|
||||
http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html
|
||||
http://en.wikipedia.org/wiki/Skip_list
|
||||
http://jclark.com/xml/xmlns.htm
|
||||
http://jcp.org/en/jsr/detail?id=173
|
||||
http://jcp.org/en/jsr/detail?id=268
|
||||
http://relaxng.org/spec-20011203.html
|
||||
http://sax.sourceforge.net/?selected=get-set
|
||||
http://standards.iso.org/iso/9075/2002/12/sqlxml.xsd
|
||||
http://svn.python.org/projects/python/trunk/Objects/listsort.txt
|
||||
http://tools.ietf.org/html/rfc1421
|
||||
http://tools.ietf.org/html/rfc5869
|
||||
http://unicode.org/reports/tr35/
|
||||
http://unicode.org/reports/tr35/tr35-numbers.html
|
||||
http://web.archive.org/web/20051219043731/http://archive.ncsa.uiuc.edu/SDG/Software/Mosaic/Demo/url-primer.html
|
||||
http://www.cl.cam.ac.uk/~mgk25/time/utc-sls/
|
||||
http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf
|
||||
http://www.iana.org/
|
||||
http://www.iana.org/assignments/character-sets
|
||||
http://www.iana.org/assignments/character-sets/character-sets.xhtml
|
||||
http://www.iana.org/assignments/media-types/
|
||||
http://www.iana.org/assignments/uri-schemes.html
|
||||
http://www.ietf.org/
|
||||
https://www.ietf.org/rfc/rfc793.txt
|
||||
https://www.ietf.org/rfc/rfc822.txt
|
||||
http://www.ietf.org/rfc/rfc1122.txt
|
||||
http://www.ietf.org/rfc/rfc1123.txt
|
||||
http://www.ietf.org/rfc/rfc1323.txt
|
||||
http://www.ietf.org/rfc/rfc1349.txt
|
||||
http://www.ietf.org/rfc/rfc1521.txt
|
||||
http://www.ietf.org/rfc/rfc1522.txt
|
||||
http://www.ietf.org/rfc/rfc1918.txt
|
||||
http://www.ietf.org/rfc/rfc1950.txt
|
||||
http://www.ietf.org/rfc/rfc1950.txt.pdf
|
||||
http://www.ietf.org/rfc/rfc1951.txt
|
||||
http://www.ietf.org/rfc/rfc1951.txt.pdf
|
||||
http://www.ietf.org/rfc/rfc1952.txt
|
||||
http://www.ietf.org/rfc/rfc1952.txt.pdf
|
||||
http://www.ietf.org/rfc/rfc1964.txt
|
||||
http://www.ietf.org/rfc/rfc2045.txt
|
||||
http://www.ietf.org/rfc/rfc2046.txt
|
||||
http://www.ietf.org/rfc/rfc2078.txt
|
||||
http://www.ietf.org/rfc/rfc2104.txt
|
||||
http://www.ietf.org/rfc/rfc2109.txt
|
||||
http://www.ietf.org/rfc/rfc2222.txt
|
||||
http://www.ietf.org/rfc/rfc2236.txt
|
||||
http://www.ietf.org/rfc/rfc2245.txt
|
||||
http://www.ietf.org/rfc/rfc2246.txt
|
||||
http://www.ietf.org/rfc/rfc2251.txt
|
||||
http://www.ietf.org/rfc/rfc2253.txt
|
||||
http://www.ietf.org/rfc/rfc2254.txt
|
||||
http://www.ietf.org/rfc/rfc2255.txt
|
||||
http://www.ietf.org/rfc/rfc2268.txt
|
||||
http://www.ietf.org/rfc/rfc2278.txt
|
||||
http://www.ietf.org/rfc/rfc2279.txt
|
||||
http://www.ietf.org/rfc/rfc2296.txt
|
||||
http://www.ietf.org/rfc/rfc2365.txt
|
||||
http://www.ietf.org/rfc/rfc2373.txt
|
||||
http://www.ietf.org/rfc/rfc2396.txt
|
||||
http://www.ietf.org/rfc/rfc2440.txt
|
||||
http://www.ietf.org/rfc/rfc2474.txt
|
||||
http://www.ietf.org/rfc/rfc2609.txt
|
||||
http://www.ietf.org/rfc/rfc2616.txt
|
||||
https://www.ietf.org/rfc/rfc2696.txt
|
||||
http://www.ietf.org/rfc/rfc2710.txt
|
||||
http://www.ietf.org/rfc/rfc2732.txt
|
||||
http://www.ietf.org/rfc/rfc2743.txt
|
||||
http://www.ietf.org/rfc/rfc2781.txt
|
||||
http://www.ietf.org/rfc/rfc2782.txt
|
||||
http://www.ietf.org/rfc/rfc2830.txt
|
||||
http://www.ietf.org/rfc/rfc2831.txt
|
||||
http://www.ietf.org/rfc/rfc2853.txt
|
||||
http://www.ietf.org/rfc/rfc2891.txt
|
||||
http://www.ietf.org/rfc/rfc2898.txt
|
||||
http://www.ietf.org/rfc/rfc2965.txt
|
||||
http://www.ietf.org/rfc/rfc3023.txt
|
||||
http://www.ietf.org/rfc/rfc3111.txt
|
||||
http://www.ietf.org/rfc/rfc3275.txt
|
||||
http://www.ietf.org/rfc/rfc3279.txt
|
||||
http://www.ietf.org/rfc/rfc3296.txt
|
||||
http://www.ietf.org/rfc/rfc3330.txt
|
||||
http://www.ietf.org/rfc/rfc3376.txt
|
||||
http://www.ietf.org/rfc/rfc3454.txt
|
||||
http://www.ietf.org/rfc/rfc3490.txt
|
||||
http://www.ietf.org/rfc/rfc3491.txt
|
||||
http://www.ietf.org/rfc/rfc3492.txt
|
||||
http://www.ietf.org/rfc/rfc3530.txt
|
||||
http://www.ietf.org/rfc/rfc3720.txt
|
||||
http://www.ietf.org/rfc/rfc3720.txt.pdf
|
||||
http://www.ietf.org/rfc/rfc3758.txt
|
||||
http://www.ietf.org/rfc/rfc3810.txt
|
||||
http://www.ietf.org/rfc/rfc3986.txt
|
||||
http://www.ietf.org/rfc/rfc4120.txt
|
||||
http://www.ietf.org/rfc/rfc4122.txt
|
||||
http://www.ietf.org/rfc/rfc4366.txt
|
||||
http://www.ietf.org/rfc/rfc4512.txt
|
||||
http://www.ietf.org/rfc/rfc4648.txt
|
||||
http://www.ietf.org/rfc/rfc5116.txt
|
||||
http://www.ietf.org/rfc/rfc5280.txt
|
||||
http://www.ietf.org/rfc/rfc5890.txt
|
||||
http://www.ietf.org/rfc/rfc6066.txt
|
||||
http://www.ietf.org/rfc/rfc7301.txt
|
||||
http://www.ietf.org/rfc/rfc790.txt
|
||||
http://www.ietf.org/rfc/rfc793.txt
|
||||
http://www.ietf.org/rfc/rfc822.txt
|
||||
http://www.ietf.org/rfc/rfc919.txt
|
||||
http://www.info-zip.org/doc/appnote-19970311-iz.zip
|
||||
http://www.ioplex.com/utilities/keytab.txt
|
||||
http://www.iso.org/iso/home/standards/currency_codes.htm
|
||||
http://www.jcp.org
|
||||
http://www.jcp.org/en/jsr/detail?id=203
|
||||
http://www.jpeg.org
|
||||
http://www.libpng.org/pub/png/spec/
|
||||
http://www.microsoft.com/typography/otspec/
|
||||
http://www.midi.org
|
||||
http://www.oasis-open.org/committees/entity/spec-2001-08-06.html
|
||||
http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=dss
|
||||
http://www.opengroup.org
|
||||
http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html
|
||||
http://www.oracle.com/technetwork/java/architecture-142923.html
|
||||
http://www.oracle.com/technetwork/java/javase/documentation/serialized-criteria-137781.html
|
||||
http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
|
||||
http://www.oracle.com/technetwork/java/javase/javasecarootcertsprogram-1876540.html
|
||||
http://www.oracle.com/technetwork/java/javase/tech/javamanagement-140525.html
|
||||
http://www.oracle.com/technetwork/java/painting-140037.html
|
||||
http://www.oracle.com/technetwork/java/persistence2-141443.html
|
||||
http://www.oracle.com/technetwork/java/persistence3-139471.html
|
||||
http://www.oracle.com/technetwork/java/persistence4-140124.html
|
||||
http://www.oreilly.com/catalog/regex/
|
||||
http://www.oreilly.com/catalog/regex3/
|
||||
http://www.reactive-streams.org/
|
||||
http://www.relaxng.org/
|
||||
http://www.rfc-editor.org/rfc/bcp/bcp47.txt
|
||||
http://www.saxproject.org
|
||||
http://www.saxproject.org/
|
||||
http://www.unicode.org
|
||||
http://www.unicode.org/
|
||||
http://www.unicode.org/glossary/
|
||||
http://www.unicode.org/reports/tr15/
|
||||
http://www.unicode.org/reports/tr18/
|
||||
http://www.unicode.org/reports/tr24/
|
||||
http://www.unicode.org/reports/tr27/
|
||||
http://www.unicode.org/reports/tr36/
|
||||
http://www.unicode.org/reports/tr44/
|
||||
http://www.unicode.org/standard/standard.html
|
||||
http://www.w3.org/2000/09/xmldsig
|
||||
http://www.w3.org/2000/xmlns/
|
||||
http://www.w3.org/2001/04/xmldsig-more
|
||||
http://www.w3.org/2001/04/xmlenc
|
||||
http://www.w3.org/2001/05/xmlschema-errata
|
||||
http://www.w3.org/2001/10/xml-exc-c14n
|
||||
http://www.w3.org/2002/06/xmldsig-filter2
|
||||
http://www.w3.org/2007/05/xmldsig-more
|
||||
http://www.w3.org/2009/xmldsig11
|
||||
http://www.w3.org/2021/04/xmldsig-more
|
||||
http://www.w3.org/Graphics/GIF/spec-gif89a.txt
|
||||
http://www.w3.org/TR/1998/REC-CSS2-19980512
|
||||
http://www.w3.org/TR/1999/REC-html401-19991224/
|
||||
http://www.w3.org/TR/1999/REC-xml-names-19990114/
|
||||
http://www.w3.org/TR/1999/REC-xpath-19991116
|
||||
http://www.w3.org/TR/1999/REC-xslt-19991116
|
||||
http://www.w3.org/TR/2000/CR-DOM-Level-2-20000510
|
||||
http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113
|
||||
http://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113
|
||||
http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113
|
||||
http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113
|
||||
http://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113
|
||||
http://www.w3.org/TR/2001/REC-xml-c14n-20010315
|
||||
http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/
|
||||
http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107
|
||||
http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109
|
||||
http://www.w3.org/TR/2003/REC-SVG11-20030114/
|
||||
http://www.w3.org/TR/2003/REC-xptr-framework-20030325/
|
||||
http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407
|
||||
http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html
|
||||
http://www.w3.org/TR/2004/REC-DOM-Level-3-LS-20040407
|
||||
http://www.w3.org/TR/2004/REC-DOM-Level-3-Val-20040127/
|
||||
http://www.w3.org/TR/2004/REC-xml-20040204
|
||||
http://www.w3.org/TR/2004/REC-xml-infoset-20040204
|
||||
http://www.w3.org/TR/2004/REC-xml-infoset-20040204/
|
||||
http://www.w3.org/TR/2004/REC-xml-names11-20040204/
|
||||
http://www.w3.org/TR/2004/REC-xml11-20040204/
|
||||
http://www.w3.org/TR/DOM-Level-2
|
||||
http://www.w3.org/TR/DOM-Level-2-Core/
|
||||
http://www.w3.org/TR/DOM-Level-3-Core
|
||||
http://www.w3.org/TR/DOM-Level-3-LS
|
||||
http://www.w3.org/TR/ElementTraversal/
|
||||
http://www.w3.org/TR/NOTE-datetime
|
||||
http://www.w3.org/TR/REC-CSS1
|
||||
http://www.w3.org/TR/REC-html32.html
|
||||
http://www.w3.org/TR/REC-xml
|
||||
http://www.w3.org/TR/REC-xml-names
|
||||
http://www.w3.org/TR/REC-xml-names/
|
||||
http://www.w3.org/TR/REC-xml/
|
||||
http://www.w3.org/TR/html4/
|
||||
http://www.w3.org/TR/html40/appendix/notes.html
|
||||
http://www.w3.org/TR/xinclude/
|
||||
http://www.w3.org/TR/xml-exc-c14n/
|
||||
http://www.w3.org/TR/xml-names11/
|
||||
http://www.w3.org/TR/xml-stylesheet/
|
||||
http://www.w3.org/TR/xml11/
|
||||
http://www.w3.org/TR/xmldsig-core/
|
||||
http://www.w3.org/TR/xmldsig-filter2
|
||||
http://www.w3.org/TR/xmldsig-filter2/
|
||||
http://www.w3.org/TR/xmlschema-1
|
||||
http://www.w3.org/TR/xmlschema-1/
|
||||
http://www.w3.org/TR/xmlschema-2/
|
||||
http://www.w3.org/TR/xpath
|
||||
http://www.w3.org/TR/xpath-datamodel
|
||||
http://www.w3.org/TR/xpath/
|
||||
http://www.w3.org/TR/xslt
|
||||
http://www.w3.org/XML/1998/namespace
|
||||
http://www.w3.org/XML/Schema
|
||||
http://www.w3.org/XML/xml-V10-2e-errata
|
||||
http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
|
||||
http://www.w3.org/pub/WWW/Protocols/
|
||||
http://xmlns.jcp.org/xml/ns//jdbc/webrowset.xsd
|
||||
https://bugreport.java.com/bugreport/
|
||||
https://bugs.openjdk.org/secure/attachment/75649/JVM_CodeHeap_StateAnalytics_V2.pdf
|
||||
https://cldr.unicode.org/index/downloads
|
||||
https://csrc.nist.gov/publications/PubsFIPS.html
|
||||
https://csrc.nist.gov/publications/fips/archive/fips186-2/fips186-2.pdf
|
||||
https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
|
||||
https://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
|
||||
https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
https://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
|
||||
https://csrc.nist.gov/publications/fips/fips81/fips81.htm
|
||||
https://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||
https://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
https://csrc.nist.gov/pubs/fips/203/final
|
||||
https://csrc.nist.gov/pubs/fips/204/final
|
||||
https://datatracker.ietf.org/doc/html/rfc5646
|
||||
https://datatracker.ietf.org/doc/html/rfc8017
|
||||
https://developer.apple.com/documentation
|
||||
https://docs.oracle.com/en/java/javase/11/tools/java.html
|
||||
https://docs.oracle.com/en/java/javase/12/language/index.html
|
||||
https://docs.oracle.com/en/java/javase/12/tools/java.html
|
||||
https://docs.oracle.com/en/java/javase/12/vm/compiler-control1.html
|
||||
https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/14/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/15/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/16/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/18/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/20/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/22/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/Double.html
|
||||
https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/math/BigDecimal.html
|
||||
https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/24/docs/specs/man/java.html
|
||||
https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/api/java.base/java/lang/String.html
|
||||
https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/specs/javadoc/javadoc-search-spec.html
|
||||
https://docs.oracle.com/en/java/javase/@@JAVASE_VERSION@@/docs/specs/man/javadoc.html
|
||||
https://docs.oracle.com/en/java/javase/index.html
|
||||
https://docs.oracle.com/javase/10/tools/java.htm
|
||||
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
|
||||
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
|
||||
https://docs.oracle.com/javase/9/tools/java.htm
|
||||
https://docs.oracle.com/javase/specs/
|
||||
https://docs.oracle.com/javase/specs/jls/se10/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se11/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se12/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se13/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se14/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se15/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se16/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se17/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se18/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se19/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se20/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se21/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-13.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-14.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-15.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-17.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-3.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-4.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-5.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-6.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-8.html
|
||||
https://docs.oracle.com/javase/specs/jls/se22/html/jls-9.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-10.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-11.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-12.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-14.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-15.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-16.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-18.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-2.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-3.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-5.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-6.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-7.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-8.html
|
||||
https://docs.oracle.com/javase/specs/jls/se23/html/jls-9.html
|
||||
https://docs.oracle.com/javase/specs/jls/se24/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se24/html/jls-9.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-10.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-11.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-12.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-13.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-14.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-15.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-17.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-18.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-3.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-4.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-5.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-6.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-7.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-8.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/html/jls-9.html
|
||||
https://docs.oracle.com/javase/specs/jls/se@@JAVASE_VERSION@@/jls@@JAVASE_VERSION@@.pdf
|
||||
https://docs.oracle.com/javase/specs/jls/se6/html/j3TOC.html
|
||||
https://docs.oracle.com/javase/specs/jls/se7/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se8/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jls/se9/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se10/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se11/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se12/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se13/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se14/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se15/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se16/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se17/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se18/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se19/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se20/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se21/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se22/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se23/html
|
||||
https://docs.oracle.com/javase/specs/jvms/se23/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-5.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se24/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se24/html/jvms-4.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-1.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-2.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-3.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-4.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-5.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/html/jvms-6.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se@@JAVASE_VERSION@@/jvms@@JAVASE_VERSION@@.pdf
|
||||
https://docs.oracle.com/javase/specs/jvms/se7/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
|
||||
https://docs.oracle.com/javase/specs/jvms/se9/html/index.html
|
||||
https://docs.oracle.com/javase/tutorial/
|
||||
https://docs.oracle.com/javase/tutorial/2d/text/fonts.html
|
||||
https://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html
|
||||
https://docs.oracle.com/javase/tutorial/index.html
|
||||
https://docs.oracle.com/javase/tutorial/javabeans/
|
||||
https://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html
|
||||
https://docs.oracle.com/javase/tutorial/sound/
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/applet.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/border.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/button.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/frame.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/icon.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/internalframe.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/jcomponent.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/label.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/list.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/menu.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/panel.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/progress.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/slider.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/spinner.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/splitpane.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/table.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/text.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/toplevel.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/components/tree.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/componentlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/containerlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/index.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/internalframelistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/itemlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/treeexpansionlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/treemodellistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/treeselectionlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/treewillexpandlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/events/windowlistener.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/index.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
|
||||
https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=GUID-FE2D2E28-C991-4EF9-9DBE-2A4982726313
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=homepage
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=i18n_overview
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=imf_overview
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=jndi_ldap_gl_prop
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=jndi_overview
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=logging_overview
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=monitoring_and_management_using_jmx_technology
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=rmi_guide
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=secure_coding_guidelines_javase
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_impl_provider
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jca
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jca_provider
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jdk_providers
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_jgss_tutorial
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_overview
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_pki
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_sasl
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=security_guide_tools
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=serialization_filter_guide
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=serialver_tool_reference
|
||||
https://docs.oracle.com/pls/topic/lookup?ctx=javase@@JAVASE_VERSION@@&id=using_jconsole
|
||||
https://ftp.pwg.org/pub/pwg/candidates/cs-ippoutputbin10-20010207-5100.2.pdf
|
||||
https://ftp.pwg.org/pub/pwg/standards/temp_archive/pwg5100.3.pdf
|
||||
https://github.github.com/gfm/
|
||||
https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles
|
||||
https://html.spec.whatwg.org
|
||||
https://html.spec.whatwg.org/multipage/
|
||||
https://html.spec.whatwg.org/multipage/introduction.html
|
||||
https://html.spec.whatwg.org/multipage/sections.html
|
||||
https://html.spec.whatwg.org/multipage/semantics.html
|
||||
https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index.html
|
||||
https://jcp.org/aboutJava/communityprocess/maintenance/jsr924/index2.html
|
||||
https://jcp.org/aboutJava/communityprocess/mrel/jsr160/index2.html
|
||||
https://jcp.org/en/jsr/detail?id=14
|
||||
https://jcp.org/en/jsr/detail?id=175
|
||||
https://jcp.org/en/jsr/detail?id=201
|
||||
https://jcp.org/en/jsr/detail?id=221
|
||||
https://jcp.org/en/jsr/detail?id=269
|
||||
https://jcp.org/en/jsr/detail?id=334
|
||||
https://jcp.org/en/jsr/detail?id=335
|
||||
https://jcp.org/en/jsr/detail?id=376
|
||||
https://jcp.org/en/jsr/detail?id=41
|
||||
https://jcp.org/en/procedures/jcp2
|
||||
https://mermaid.js.org
|
||||
https://msdn.microsoft.com/en-us/library/cc236621.aspx
|
||||
https://msdn.microsoft.com/en-us/library/dd183391.aspx
|
||||
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-2.pdf
|
||||
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
||||
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
|
||||
https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
|
||||
https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf
|
||||
https://openjdk.org/jeps/11
|
||||
https://openjdk.org/jeps/12
|
||||
https://openjdk.org/jeps/181
|
||||
https://openjdk.org/jeps/213
|
||||
https://openjdk.org/jeps/225
|
||||
https://openjdk.org/jeps/261
|
||||
https://openjdk.org/jeps/286
|
||||
https://openjdk.org/jeps/306
|
||||
https://openjdk.org/jeps/323
|
||||
https://openjdk.org/jeps/361
|
||||
https://openjdk.org/jeps/371
|
||||
https://openjdk.org/jeps/378
|
||||
https://openjdk.org/jeps/394
|
||||
https://openjdk.org/jeps/395
|
||||
https://openjdk.org/jeps/396
|
||||
https://openjdk.org/jeps/403
|
||||
https://openjdk.org/jeps/409
|
||||
https://openjdk.org/jeps/421
|
||||
https://openjdk.org/jeps/440
|
||||
https://openjdk.org/jeps/441
|
||||
https://openjdk.org/jeps/454
|
||||
https://openjdk.org/jeps/456
|
||||
https://openjdk.org/jeps/458
|
||||
https://openjdk.org/jeps/467
|
||||
https://openjdk.org/jeps/478
|
||||
https://openjdk.org/jeps/487
|
||||
https://openjdk.org/jeps/488
|
||||
https://openjdk.org/jeps/492
|
||||
https://openjdk.org/jeps/494
|
||||
https://openjdk.org/jeps/495
|
||||
https://openjdk.org/jeps/499
|
||||
https://prismjs.com
|
||||
https://pubs.opengroup.org/onlinepubs/9699919799/functions/inet_addr.html
|
||||
https://relaxng.org/
|
||||
https://reproducible-builds.org/
|
||||
https://spec.commonmark.org/0.31.2
|
||||
https://spec.commonmark.org/0.31.2/
|
||||
https://standards.ieee.org/ieee/754/6210/
|
||||
https://standards.iso.org/ittf/PubliclyAvailableStandards/c055982_ISO_IEC_19757-3_2016.zip
|
||||
https://standards.iso.org/ittf/PubliclyAvailableStandards/index.html
|
||||
https://support.pkware.com/pkzip/appnote
|
||||
https://tools.ietf.org/html/rfc1319
|
||||
https://tools.ietf.org/html/rfc1321
|
||||
https://tools.ietf.org/html/rfc1779
|
||||
https://tools.ietf.org/html/rfc2040
|
||||
https://tools.ietf.org/html/rfc2104
|
||||
https://tools.ietf.org/html/rfc2195
|
||||
https://tools.ietf.org/html/rfc2222
|
||||
https://tools.ietf.org/html/rfc2246
|
||||
https://tools.ietf.org/html/rfc2253
|
||||
https://tools.ietf.org/html/rfc2595
|
||||
https://tools.ietf.org/html/rfc2616
|
||||
https://tools.ietf.org/html/rfc2712
|
||||
https://tools.ietf.org/html/rfc2818
|
||||
https://tools.ietf.org/html/rfc2830
|
||||
https://tools.ietf.org/html/rfc2831
|
||||
https://tools.ietf.org/html/rfc3217
|
||||
https://tools.ietf.org/html/rfc3278
|
||||
https://tools.ietf.org/html/rfc3394
|
||||
https://tools.ietf.org/html/rfc3986
|
||||
https://tools.ietf.org/html/rfc4086
|
||||
https://tools.ietf.org/html/rfc4121
|
||||
https://tools.ietf.org/html/rfc4162
|
||||
https://tools.ietf.org/html/rfc4178
|
||||
https://tools.ietf.org/html/rfc4234
|
||||
https://tools.ietf.org/html/rfc4279
|
||||
https://tools.ietf.org/html/rfc4346
|
||||
https://tools.ietf.org/html/rfc4347
|
||||
https://tools.ietf.org/html/rfc4492
|
||||
https://tools.ietf.org/html/rfc4512
|
||||
https://tools.ietf.org/html/rfc4647
|
||||
https://tools.ietf.org/html/rfc4785
|
||||
https://tools.ietf.org/html/rfc4960
|
||||
https://tools.ietf.org/html/rfc5054
|
||||
https://tools.ietf.org/html/rfc5061
|
||||
https://tools.ietf.org/html/rfc5084
|
||||
https://tools.ietf.org/html/rfc5246
|
||||
https://tools.ietf.org/html/rfc5280
|
||||
https://tools.ietf.org/html/rfc5288
|
||||
https://tools.ietf.org/html/rfc5289
|
||||
https://tools.ietf.org/html/rfc5469
|
||||
https://tools.ietf.org/html/rfc5487
|
||||
https://tools.ietf.org/html/rfc5489
|
||||
https://tools.ietf.org/html/rfc5639
|
||||
https://tools.ietf.org/html/rfc5646
|
||||
https://tools.ietf.org/html/rfc5649
|
||||
https://tools.ietf.org/html/rfc5746
|
||||
https://tools.ietf.org/html/rfc5932
|
||||
https://tools.ietf.org/html/rfc6209
|
||||
https://tools.ietf.org/html/rfc6347
|
||||
https://tools.ietf.org/html/rfc6367
|
||||
https://tools.ietf.org/html/rfc6454
|
||||
https://tools.ietf.org/html/rfc6455
|
||||
https://tools.ietf.org/html/rfc6655
|
||||
https://tools.ietf.org/html/rfc6931
|
||||
https://tools.ietf.org/html/rfc7230
|
||||
https://tools.ietf.org/html/rfc7231
|
||||
https://tools.ietf.org/html/rfc7251
|
||||
https://tools.ietf.org/html/rfc7292
|
||||
https://tools.ietf.org/html/rfc7507
|
||||
https://tools.ietf.org/html/rfc7539
|
||||
https://tools.ietf.org/html/rfc7540
|
||||
https://tools.ietf.org/html/rfc7748
|
||||
https://tools.ietf.org/html/rfc7905
|
||||
https://tools.ietf.org/html/rfc7919
|
||||
https://tools.ietf.org/html/rfc8017
|
||||
https://tools.ietf.org/html/rfc8018
|
||||
https://tools.ietf.org/html/rfc8032
|
||||
https://tools.ietf.org/html/rfc8103
|
||||
https://tools.ietf.org/html/rfc8353
|
||||
https://tools.ietf.org/html/rfc8422
|
||||
https://tools.ietf.org/html/rfc8446
|
||||
https://tools.ietf.org/html/rfc8554
|
||||
https://tools.ietf.org/id/draft-kaukonen-cipher-arcfour-03.txt
|
||||
https://tools.ietf.org/rfc/rfc5280.txt
|
||||
https://tools.ietf.org/rfc/rfc8017.txt
|
||||
https://unicode.org/reports/tr31/
|
||||
https://unicode.org/reports/tr35/
|
||||
https://unicode.org/reports/tr35/tr35-dates.html
|
||||
https://unicode.org/reports/tr35/tr35-numbers.html
|
||||
https://unicode.org/reports/tr51/
|
||||
https://web.mit.edu/kerberos/
|
||||
https://webhome.phy.duke.edu/~rgb/General/dieharder.php
|
||||
https://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf
|
||||
https://www.color.org
|
||||
https://www.color.org/ICC1V42.pdf
|
||||
https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml
|
||||
https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
|
||||
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
|
||||
https://www.iana.org/time-zones
|
||||
https://www.ietf.org/rfc/rfc2616.txt
|
||||
https://www.ietf.org/rfc/rfc2818.txt
|
||||
https://www.ietf.org/rfc/rfc6931.txt
|
||||
https://www.ietf.org/rfc/rfc6943.html
|
||||
https://www.iso.org/home.html
|
||||
https://www.iso.org/iso-4217-currency-codes.html
|
||||
https://www.iso.org/iso-8601-date-and-time-format.html
|
||||
https://www.iso.org/standard/18114.html
|
||||
https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf
|
||||
https://www.itu.int/rec/T-REC-X.509/en
|
||||
https://www.netlib.org/fdlibm/
|
||||
https://www.oasis-open.org
|
||||
https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html
|
||||
https://www.oracle.com/java/javase/terms/license/java@@JAVASE_VERSION@@speclicense.html
|
||||
https://www.oracle.com/java/technologies/a-swing-architecture.html
|
||||
https://www.oracle.com/java/technologies/javase/seccodeguide.html
|
||||
https://www.oracle.com/java/technologies/javase/training-support.html
|
||||
https://www.oracle.com/pls/topic/lookup?ctx=en/java/javase&id=security_guide_implement_provider_jca
|
||||
https://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
|
||||
https://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html
|
||||
https://www.oracle.com/technetwork/java/redist-137594.html
|
||||
https://www.oracle.com/technetwork/java/seccodeguide-139067.html
|
||||
https://www.owasp.org
|
||||
https://www.rfc-editor.org/info/rfc1122
|
||||
https://www.rfc-editor.org/info/rfc1123
|
||||
https://www.rfc-editor.org/info/rfc1323
|
||||
https://www.rfc-editor.org/info/rfc1349
|
||||
https://www.rfc-editor.org/info/rfc1738
|
||||
https://www.rfc-editor.org/info/rfc1779
|
||||
https://www.rfc-editor.org/info/rfc1918
|
||||
https://www.rfc-editor.org/info/rfc1950
|
||||
https://www.rfc-editor.org/info/rfc1951
|
||||
https://www.rfc-editor.org/info/rfc1952
|
||||
https://www.rfc-editor.org/info/rfc2040
|
||||
https://www.rfc-editor.org/info/rfc2045
|
||||
https://www.rfc-editor.org/info/rfc2046
|
||||
https://www.rfc-editor.org/info/rfc2109
|
||||
https://www.rfc-editor.org/info/rfc2236
|
||||
https://www.rfc-editor.org/info/rfc2246
|
||||
https://www.rfc-editor.org/info/rfc2253
|
||||
https://www.rfc-editor.org/info/rfc2268
|
||||
https://www.rfc-editor.org/info/rfc2278
|
||||
https://www.rfc-editor.org/info/rfc2279
|
||||
https://www.rfc-editor.org/info/rfc2296
|
||||
https://www.rfc-editor.org/info/rfc2306
|
||||
https://www.rfc-editor.org/info/rfc2365
|
||||
https://www.rfc-editor.org/info/rfc2368
|
||||
https://www.rfc-editor.org/info/rfc2373
|
||||
https://www.rfc-editor.org/info/rfc2396
|
||||
https://www.rfc-editor.org/info/rfc2474
|
||||
https://www.rfc-editor.org/info/rfc2560
|
||||
https://www.rfc-editor.org/info/rfc2616
|
||||
https://www.rfc-editor.org/info/rfc2710
|
||||
https://www.rfc-editor.org/info/rfc2732
|
||||
https://www.rfc-editor.org/info/rfc2781
|
||||
https://www.rfc-editor.org/info/rfc2898
|
||||
https://www.rfc-editor.org/info/rfc2911
|
||||
https://www.rfc-editor.org/info/rfc2965
|
||||
https://www.rfc-editor.org/info/rfc3279
|
||||
https://www.rfc-editor.org/info/rfc3330
|
||||
https://www.rfc-editor.org/info/rfc3376
|
||||
https://www.rfc-editor.org/info/rfc3454
|
||||
https://www.rfc-editor.org/info/rfc3490
|
||||
https://www.rfc-editor.org/info/rfc3491
|
||||
https://www.rfc-editor.org/info/rfc3492
|
||||
https://www.rfc-editor.org/info/rfc3530
|
||||
https://www.rfc-editor.org/info/rfc3720
|
||||
https://www.rfc-editor.org/info/rfc3810
|
||||
https://www.rfc-editor.org/info/rfc3986
|
||||
https://www.rfc-editor.org/info/rfc4007
|
||||
https://www.rfc-editor.org/info/rfc4086
|
||||
https://www.rfc-editor.org/info/rfc4122
|
||||
https://www.rfc-editor.org/info/rfc4234
|
||||
https://www.rfc-editor.org/info/rfc4366
|
||||
https://www.rfc-editor.org/info/rfc4512
|
||||
https://www.rfc-editor.org/info/rfc4647
|
||||
https://www.rfc-editor.org/info/rfc4648
|
||||
https://www.rfc-editor.org/info/rfc5116
|
||||
https://www.rfc-editor.org/info/rfc5280
|
||||
https://www.rfc-editor.org/info/rfc5646
|
||||
https://www.rfc-editor.org/info/rfc5869
|
||||
https://www.rfc-editor.org/info/rfc5890
|
||||
https://www.rfc-editor.org/info/rfc6066
|
||||
https://www.rfc-editor.org/info/rfc7301
|
||||
https://www.rfc-editor.org/info/rfc7539
|
||||
https://www.rfc-editor.org/info/rfc790
|
||||
https://www.rfc-editor.org/info/rfc793
|
||||
https://www.rfc-editor.org/info/rfc8017
|
||||
https://www.rfc-editor.org/info/rfc8032
|
||||
https://www.rfc-editor.org/info/rfc822
|
||||
https://www.rfc-editor.org/info/rfc919
|
||||
https://www.rfc-editor.org/info/rfc9231
|
||||
https://www.rfc-editor.org/rfc/rfc2315.txt
|
||||
https://www.rfc-editor.org/rfc/rfc5208.html
|
||||
https://www.rfc-editor.org/rfc/rfc5280.html
|
||||
https://www.rfc-editor.org/rfc/rfc5646
|
||||
https://www.rfc-editor.org/rfc/rfc5646.html
|
||||
https://www.rfc-editor.org/rfc/rfc5869
|
||||
https://www.rfc-editor.org/rfc/rfc6943.html
|
||||
https://www.rfc-editor.org/rfc/rfc8017
|
||||
https://www.rfc-editor.org/rfc/rfc8017.html
|
||||
https://www.rfc-editor.org/rfc/rfc9180
|
||||
https://www.schneier.com/blowfish.html
|
||||
https://www.secg.org/sec2-v2.pdf
|
||||
https://www.unicode.org/reports/tr15
|
||||
https://www.unicode.org/reports/tr15/
|
||||
https://www.unicode.org/reports/tr18
|
||||
https://www.unicode.org/reports/tr24
|
||||
https://www.unicode.org/reports/tr27
|
||||
https://www.unicode.org/reports/tr29/
|
||||
https://www.unicode.org/reports/tr31
|
||||
https://www.unicode.org/reports/tr35
|
||||
https://www.unicode.org/reports/tr35/
|
||||
https://www.unicode.org/reports/tr35/tr35-collation.html
|
||||
https://www.unicode.org/reports/tr35/tr35-dates.html
|
||||
https://www.unicode.org/reports/tr35/tr35-general.html
|
||||
https://www.unicode.org/reports/tr35/tr35.html
|
||||
https://www.unicode.org/reports/tr36
|
||||
https://www.unicode.org/reports/tr44
|
||||
https://www.unicode.org/reports/tr44/
|
||||
https://www.usno.navy.mil/USNO
|
||||
https://www.usno.navy.mil/USNO/time/master-clock/systems-of-time
|
||||
https://www.w3.org
|
||||
https://www.w3.org/Daemon/User/Config/Logging.html
|
||||
https://www.w3.org/TR/1998/REC-html40-19980424/
|
||||
https://www.w3.org/TR/1999/REC-xpath-19991116/
|
||||
https://www.w3.org/TR/2001/REC-xml-c14n-20010315
|
||||
https://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/
|
||||
https://www.w3.org/TR/2002/REC-xmldsig-filter2-20021108/
|
||||
https://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html
|
||||
https://www.w3.org/TR/CSS22
|
||||
https://www.w3.org/TR/CSS22/syndata.html
|
||||
https://www.w3.org/TR/DOM-Level-3-XPath/
|
||||
https://www.w3.org/TR/NOTE-datetime
|
||||
https://www.w3.org/TR/REC-CSS1
|
||||
https://www.w3.org/TR/REC-html32.html
|
||||
https://www.w3.org/TR/REC-xml-names/
|
||||
https://www.w3.org/TR/html4
|
||||
https://www.w3.org/TR/html52
|
||||
https://www.w3.org/TR/html52/dom.html
|
||||
https://www.w3.org/TR/html52/syntax.html
|
||||
https://www.w3.org/TR/xml
|
||||
https://www.w3.org/TR/xml-c14n11/
|
||||
https://www.w3.org/TR/xml/
|
||||
https://www.w3.org/TR/xmldsig-core/
|
||||
https://www.w3.org/TR/xmlschema-2
|
||||
https://www.w3.org/WAI/standards-guidelines/wcag/
|
||||
https://www.w3.org/XML/Schema
|
||||
https://www.w3.org/XML/xml-names-19990114-errata.html
|
||||
https://www.wapforum.org/what/technical/SPEC-WAESpec-19990524.pdf
|
||||
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckExtlinks.java
Normal file
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckExtlinks.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8337109
|
||||
* @summary Check external links in the generated documentation
|
||||
* @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester
|
||||
* @build DocTester toolbox.TestRunner
|
||||
* @run main/othervm -Ddoccheck.checks=extlinks DocCheck
|
||||
*/
|
||||
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java
Normal file
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8337109
|
||||
* @summary Check the html in the generated documentation
|
||||
* @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester
|
||||
* @build DocTester toolbox.TestRunner jtreg.SkippedException
|
||||
* @run main/othervm -Ddoccheck.checks=html DocCheck
|
||||
*/
|
||||
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckLinks.java
Normal file
31
test/docs/jdk/javadoc/doccheck/checks/jdkCheckLinks.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8337109 8349369
|
||||
* @summary Check Links in the generated documentation
|
||||
* @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester
|
||||
* @build DocTester toolbox.TestRunner
|
||||
* @run main/othervm -Ddoccheck.checks=links DocCheck
|
||||
*/
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8337109
|
||||
* @summary Check doctype and character encoding in the generated documentation
|
||||
* @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester
|
||||
* @build DocTester toolbox.TestRunner
|
||||
* @run main/othervm -Ddoccheck.checks=doctype,badchars DocCheck
|
||||
*/
|
||||
39
test/docs/jdk/javadoc/doccheck/doccheckutils/Checker.java
Normal file
39
test/docs/jdk/javadoc/doccheck/doccheckutils/Checker.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* Base class for {@link FileChecker file checkers} and
|
||||
*/
|
||||
public interface Checker extends Closeable {
|
||||
|
||||
/**
|
||||
* Writes a report at the end of a run, to summarize the results of the
|
||||
* checking done by this checker.
|
||||
*/
|
||||
void report();
|
||||
|
||||
boolean isOK();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
public interface FileChecker extends Checker {
|
||||
void checkFiles(List<Path> files);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FileProcessor {
|
||||
private final List<Path> files;
|
||||
|
||||
public FileProcessor() {
|
||||
files = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Path> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void processFiles(Path directory) {
|
||||
try {
|
||||
Files.walkFileTree(directory, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
|
||||
if (file.toString().endsWith(".html"))
|
||||
files.add(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class for HTML checkers.
|
||||
* <p>
|
||||
* For details on HTML syntax and the terms used in this API, see
|
||||
* W3C <a href="https://html.spec.whatwg.org/multipage/syntax.html#syntax">The HTML syntax</a>.
|
||||
*/
|
||||
public interface HtmlChecker extends Checker {
|
||||
/**
|
||||
* Starts checking a new file,
|
||||
* <p>
|
||||
* The file becomes the <em>current</em> file until {@link #endFile endFile}
|
||||
* is called.
|
||||
*
|
||||
* @param path the file.
|
||||
*/
|
||||
void startFile(Path path);
|
||||
|
||||
/**
|
||||
* Ends checking the current file.
|
||||
*/
|
||||
void endFile();
|
||||
|
||||
/**
|
||||
* Checks the content of a {@code <?xml ... ?>} declaration in the
|
||||
* current file.
|
||||
*
|
||||
* @param line the line number on which the declaration was found
|
||||
* @param attrs the content of the declaration
|
||||
*/
|
||||
void xml(int line, Map<String, String> attrs);
|
||||
|
||||
/**
|
||||
* Checks the content of a {@code <!doctype ... >} declaration in the
|
||||
* current file.
|
||||
*
|
||||
* @param line the line number on which the declaration was found
|
||||
* @param docType the content of the declaration
|
||||
*/
|
||||
void docType(int line, String docType);
|
||||
|
||||
/**
|
||||
* Checks the start of an HTML tag in the current file.
|
||||
*
|
||||
* @param line the line number on which the start tag for an element was found
|
||||
* @param name the name of the tag
|
||||
* @param attrs the attributes of the tag
|
||||
* @param selfClosing whether the tag is self-closing
|
||||
*/
|
||||
void startElement(int line, String name, Map<String, String> attrs, boolean selfClosing);
|
||||
|
||||
/**
|
||||
* Checks the end of an HTML tag in the current file.
|
||||
*
|
||||
* @param line the line number on which the end tag for an element was found
|
||||
* @param name the name of the tag
|
||||
*/
|
||||
void endElement(int line, String name);
|
||||
|
||||
/**
|
||||
* Checks the content appearing in between HTML tags.
|
||||
*
|
||||
* @param line the line number on which the content was found
|
||||
* @param content the content
|
||||
*/
|
||||
default void content(int line, String content) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,389 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Reads an HTML file, and calls a series of{@link HtmlChecker HTML checkers}
|
||||
* for the HTML constructs found therein.
|
||||
*/
|
||||
public class HtmlFileChecker implements FileChecker {
|
||||
private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.IGNORE)
|
||||
.onUnmappableCharacter(CodingErrorAction.IGNORE);
|
||||
|
||||
private final Log log;
|
||||
private final HtmlChecker htmlChecker;
|
||||
private Path path;
|
||||
private BufferedReader in;
|
||||
private int ch;
|
||||
private int lineNumber;
|
||||
private boolean inScript;
|
||||
private boolean xml;
|
||||
|
||||
public HtmlFileChecker(HtmlChecker htmlChecker, Path BaseDir) {
|
||||
this.log = new Log();
|
||||
log.setBaseDirectory(BaseDir);
|
||||
this.htmlChecker = htmlChecker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkFiles(List<Path> files) {
|
||||
for (Path file : files) {
|
||||
read(file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
System.err.println(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// report();
|
||||
htmlChecker.close();
|
||||
}
|
||||
|
||||
private void read(Path path) {
|
||||
try (BufferedReader r = new BufferedReader(
|
||||
new InputStreamReader(Files.newInputStream(path), decoder))) {
|
||||
this.path = path;
|
||||
this.in = r;
|
||||
StringBuilder content = new StringBuilder();
|
||||
|
||||
startFile(path);
|
||||
try {
|
||||
lineNumber = 1;
|
||||
xml = false;
|
||||
nextChar();
|
||||
|
||||
while (ch != -1) {
|
||||
if (ch == '<') {
|
||||
content(content.toString());
|
||||
content.setLength(0);
|
||||
html();
|
||||
} else {
|
||||
content.append((char) ch);
|
||||
if (ch == '\n') {
|
||||
content(content.toString());
|
||||
content.setLength(0);
|
||||
}
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
endFile();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.log(path, lineNumber, e);
|
||||
} catch (Throwable t) {
|
||||
log.log(path, lineNumber, t);
|
||||
log.log(String.valueOf(t));
|
||||
}
|
||||
}
|
||||
|
||||
private void startFile(Path path) {
|
||||
htmlChecker.startFile(path);
|
||||
}
|
||||
|
||||
private void endFile() {
|
||||
htmlChecker.endFile();
|
||||
}
|
||||
|
||||
private void docType(String s) {
|
||||
htmlChecker.docType(lineNumber, s);
|
||||
}
|
||||
|
||||
private void startElement(String name, Map<String, String> attrs, boolean selfClosing) {
|
||||
htmlChecker.startElement(lineNumber, name, attrs, selfClosing);
|
||||
}
|
||||
|
||||
private void endElement(String name) {
|
||||
htmlChecker.endElement(lineNumber, name);
|
||||
}
|
||||
|
||||
private void content(String s) {
|
||||
htmlChecker.content(lineNumber, s);
|
||||
}
|
||||
|
||||
private void nextChar() throws IOException {
|
||||
ch = in.read();
|
||||
if (ch == '\n')
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the start or end of an HTML tag, or an HTML comment
|
||||
* {@literal <identifier attrs> } or {@literal </identifier> }
|
||||
*
|
||||
* @throws IOException if there is a problem reading the file
|
||||
*/
|
||||
protected void html() throws IOException {
|
||||
nextChar();
|
||||
if (isIdentifierStart((char) ch)) {
|
||||
String name = readIdentifier().toLowerCase(Locale.US);
|
||||
Map<String, String> attrs = htmlAttrs();
|
||||
if (attrs != null) {
|
||||
boolean selfClosing = false;
|
||||
if (ch == '/') {
|
||||
nextChar();
|
||||
selfClosing = true;
|
||||
}
|
||||
if (ch == '>') {
|
||||
nextChar();
|
||||
startElement(name, attrs, selfClosing);
|
||||
if (name.equals("script")) {
|
||||
inScript = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
nextChar();
|
||||
if (isIdentifierStart((char) ch)) {
|
||||
String name = readIdentifier().toLowerCase(Locale.US);
|
||||
skipWhitespace();
|
||||
if (ch == '>') {
|
||||
nextChar();
|
||||
endElement(name);
|
||||
if (name.equals("script")) {
|
||||
inScript = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (ch == '!') {
|
||||
nextChar();
|
||||
if (ch == '-') {
|
||||
nextChar();
|
||||
if (ch == '-') {
|
||||
nextChar();
|
||||
while (ch != -1) {
|
||||
int dash = 0;
|
||||
while (ch == '-') {
|
||||
dash++;
|
||||
nextChar();
|
||||
}
|
||||
// Strictly speaking, a comment should not contain "--"
|
||||
// so dash > 2 is an error, dash == 2 implies ch == '>'
|
||||
// See http://www.w3.org/TR/html-markup/syntax.html#syntax-comments
|
||||
// for more details.
|
||||
if (dash >= 2 && ch == '>') {
|
||||
nextChar();
|
||||
return;
|
||||
}
|
||||
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
} else if (ch == '[') {
|
||||
nextChar();
|
||||
if (ch == 'C') {
|
||||
nextChar();
|
||||
if (ch == 'D') {
|
||||
nextChar();
|
||||
if (ch == 'A') {
|
||||
nextChar();
|
||||
if (ch == 'T') {
|
||||
nextChar();
|
||||
if (ch == 'A') {
|
||||
nextChar();
|
||||
if (ch == '[') {
|
||||
while (true) {
|
||||
nextChar();
|
||||
if (ch == ']') {
|
||||
nextChar();
|
||||
if (ch == ']') {
|
||||
nextChar();
|
||||
if (ch == '>') {
|
||||
nextChar();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (ch != -1 && ch != '>') {
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
}
|
||||
Pattern p = Pattern.compile("(?is)doctype\\s+html\\s?.*");
|
||||
String s = sb.toString();
|
||||
if (p.matcher(s).matches()) {
|
||||
xml = s.contains("XHTML");
|
||||
docType(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (ch == '?') {
|
||||
nextChar();
|
||||
if (ch == 'x') {
|
||||
nextChar();
|
||||
if (ch == 'm') {
|
||||
nextChar();
|
||||
if (ch == 'l') {
|
||||
nextChar();
|
||||
if (ch == '?') {
|
||||
nextChar();
|
||||
if (ch == '>') {
|
||||
nextChar();
|
||||
xml = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!inScript) {
|
||||
log.log(path, lineNumber, "bad html");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a series of HTML attributes, terminated by {@literal > }.
|
||||
* Each attribute is of the form {@literal identifier[=value] }.
|
||||
* "value" may be unquoted, single-quoted, or double-quoted.
|
||||
*/
|
||||
protected Map<String, String> htmlAttrs() throws IOException {
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
skipWhitespace();
|
||||
|
||||
while (isIdentifierStart((char) ch)) {
|
||||
String name = readAttributeName().toLowerCase(Locale.US);
|
||||
skipWhitespace();
|
||||
String value = null;
|
||||
if (ch == '=') {
|
||||
nextChar();
|
||||
skipWhitespace();
|
||||
if (ch == '\'' || ch == '"') {
|
||||
char quote = (char) ch;
|
||||
nextChar();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (ch != -1 && ch != quote) {
|
||||
// if (ch == '\n') {
|
||||
// error(path, lineNumber, "unterminated string");
|
||||
// // No point trying to read more.
|
||||
// // In fact, all attrs get discarded by the caller
|
||||
// // and superseded by a malformed.html node because
|
||||
// // the html tag itself is not terminated correctly.
|
||||
// break loop;
|
||||
// }
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
}
|
||||
value = sb.toString() // hack to replace common entities
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("&", "&");
|
||||
nextChar();
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (ch != -1 && !isUnquotedAttrValueTerminator((char) ch)) {
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
}
|
||||
value = sb.toString();
|
||||
}
|
||||
skipWhitespace();
|
||||
}
|
||||
map.put(name, value);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
protected boolean isIdentifierStart(char ch) {
|
||||
return Character.isUnicodeIdentifierStart(ch);
|
||||
}
|
||||
|
||||
protected String readIdentifier() throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
while (ch != -1 && Character.isUnicodeIdentifierPart(ch)) {
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String readAttributeName() throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
while ((ch != -1 && Character.isUnicodeIdentifierPart(ch))
|
||||
|| ch == '-'
|
||||
|| (xml && ch == ':')) {
|
||||
sb.append((char) ch);
|
||||
nextChar();
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected boolean isWhitespace(char ch) {
|
||||
return Character.isWhitespace(ch);
|
||||
}
|
||||
|
||||
protected void skipWhitespace() throws IOException {
|
||||
while (isWhitespace((char) ch)) {
|
||||
nextChar();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isUnquotedAttrValueTerminator(char ch) {
|
||||
return switch (ch) {
|
||||
case '\f', '\n', '\r', '\t', ' ', '"', '\'', '`', '=', '<', '>' -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
95
test/docs/jdk/javadoc/doccheck/doccheckutils/Log.java
Normal file
95
test/docs/jdk/javadoc/doccheck/doccheckutils/Log.java
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Log {
|
||||
private final ArrayList<String> errors;
|
||||
|
||||
private Path baseDir;
|
||||
|
||||
public Log() {
|
||||
errors = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<String> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
public void log(Path path, int line, String message, Object... args) {
|
||||
errors.add(formatErrorMessage(path, line, message, args));
|
||||
}
|
||||
|
||||
|
||||
public String formatErrorMessage(Path path, int line, String message, Object... args) {
|
||||
return path + ":" + line + ": " + formatErrorMessage(message, args);
|
||||
}
|
||||
|
||||
public String formatErrorMessage(Path path, int line, Throwable t) {
|
||||
return path + ":" + line + ": " + t;
|
||||
}
|
||||
|
||||
public String formatErrorMessage(Path path, Throwable t) {
|
||||
return path + ": " + t;
|
||||
}
|
||||
|
||||
|
||||
public String formatErrorMessage(String message, Object... args) {
|
||||
return String.format(message, args);
|
||||
}
|
||||
|
||||
public void log(String message) {
|
||||
errors.add(message);
|
||||
}
|
||||
|
||||
public void log(Path path, int lineNumber, String s, int errorsOnLine) {
|
||||
log(formatErrorMessage(path, lineNumber, s, errorsOnLine));
|
||||
}
|
||||
|
||||
public void log(Path path, int line, Throwable t) {
|
||||
log(formatErrorMessage(path, line, t));
|
||||
}
|
||||
|
||||
public void log(Path path, Throwable t) {
|
||||
log(formatErrorMessage(path, t));
|
||||
}
|
||||
|
||||
public void log(String message, Object... args) {
|
||||
log(formatErrorMessage(message, args));
|
||||
}
|
||||
|
||||
public void setBaseDirectory(Path baseDir) {
|
||||
this.baseDir = baseDir.toAbsolutePath();
|
||||
}
|
||||
|
||||
public Path relativize(Path path) {
|
||||
return baseDir != null && path.startsWith(baseDir) ? baseDir.relativize(path) : path;
|
||||
}
|
||||
|
||||
public boolean noErrors() {
|
||||
return errors.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils.checkers;
|
||||
|
||||
import doccheckutils.FileChecker;
|
||||
import doccheckutils.Log;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Checks the contents of an HTML file for bad/unmappable characters.
|
||||
* <p>
|
||||
* The file encoding is determined from the file contents.
|
||||
*/
|
||||
public class BadCharacterChecker implements FileChecker, AutoCloseable {
|
||||
private static final Pattern doctype = Pattern.compile("(?i)<!doctype html>");
|
||||
private static final Pattern metaCharset = Pattern.compile("(?i)<meta\\s+charset=\"([^\"]+)\">");
|
||||
private static final Pattern metaContentType = Pattern.compile("(?i)<meta\\s+http-equiv=\"Content-Type\"\\s+content=\"text/html;charset=([^\"]+)\">");
|
||||
private final Log errors;
|
||||
private int files = 0;
|
||||
private int badFiles = 0;
|
||||
|
||||
public BadCharacterChecker() {
|
||||
errors = new Log();
|
||||
}
|
||||
|
||||
public void checkFile(Path path) {
|
||||
files++;
|
||||
boolean ok = true;
|
||||
try (InputStream in = new BufferedInputStream(Files.newInputStream(path))) {
|
||||
CharsetDecoder d = getCharset(in).newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(in, d));
|
||||
int lineNumber = 0;
|
||||
String line;
|
||||
try {
|
||||
while ((line = r.readLine()) != null) {
|
||||
lineNumber++;
|
||||
int errorsOnLine = 0;
|
||||
for (int i = 0; i < line.length(); i++) {
|
||||
char ch = line.charAt(i);
|
||||
if (ch == 0xFFFD) {
|
||||
errorsOnLine++;
|
||||
}
|
||||
}
|
||||
if (errorsOnLine > 0) {
|
||||
errors.log(path, lineNumber, "found %d invalid characters", errorsOnLine);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
errors.log(path, lineNumber, e);
|
||||
ok = false;
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
errors.log(path, e);
|
||||
ok = false;
|
||||
}
|
||||
if (!ok)
|
||||
badFiles++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkFiles(List<Path> files) {
|
||||
for (Path file : files) {
|
||||
checkFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
private Charset getCharset(InputStream in) throws IOException {
|
||||
CharsetDecoder initial = StandardCharsets.US_ASCII.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE);
|
||||
|
||||
in.mark(1024);
|
||||
try {
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(in, initial));
|
||||
char[] buf = new char[1024];
|
||||
int n = r.read(buf, 0, buf.length);
|
||||
String head = new String(buf, 0, n);
|
||||
boolean html5 = doctype.matcher(head).find();
|
||||
Matcher m1 = metaCharset.matcher(head);
|
||||
if (m1.find()) {
|
||||
return Charset.forName(m1.group(1));
|
||||
}
|
||||
Matcher m2 = metaContentType.matcher(head);
|
||||
if (m2.find()) {
|
||||
return Charset.forName(m2.group(1));
|
||||
}
|
||||
return html5 ? StandardCharsets.UTF_8 : StandardCharsets.ISO_8859_1;
|
||||
} finally {
|
||||
in.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
if (!errors.noErrors() && files > 0) {
|
||||
System.err.println("Bad characters found in the generated HTML");
|
||||
|
||||
System.err.println(MessageFormat.format(
|
||||
"""
|
||||
Bad Characters Report
|
||||
{0} files read
|
||||
{1} files contained bad characters"
|
||||
{2} bad characters or other errors found
|
||||
""",
|
||||
files, badFiles, files));
|
||||
|
||||
for (String s : errors.getErrors()) {
|
||||
System.err.println(s);
|
||||
}
|
||||
throw new RuntimeException("Bad character found in the generated HTML");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return errors.noErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
report();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils.checkers;
|
||||
|
||||
import doccheckutils.HtmlChecker;
|
||||
import doccheckutils.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Checks the DocType declared at the head of an HTML file.
|
||||
*
|
||||
* @see <a href="https://www.w3.org/TR/html5/syntax.html#syntax-doctype">
|
||||
* W3C HTML5 8.1.1 The DOCTYPE</a>
|
||||
*/
|
||||
public class DocTypeChecker implements HtmlChecker {
|
||||
private final Log log;
|
||||
private final Map<String, Integer> counts = new HashMap<>();
|
||||
private int html5;
|
||||
private int html5_legacy;
|
||||
private int xml;
|
||||
private int other;
|
||||
|
||||
private Path path;
|
||||
|
||||
public DocTypeChecker() {
|
||||
log = new Log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFile(Path path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFile() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void xml(int line, Map<String, String> attrs) {
|
||||
xml++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void docType(int line, String docType) {
|
||||
if (docType.equalsIgnoreCase("doctype html")) {
|
||||
html5++;
|
||||
} else {
|
||||
Pattern p = Pattern.compile("(?i)doctype"
|
||||
+ "\\s+html"
|
||||
+ "\\s+([a-z]+)"
|
||||
+ "\\s+(?:\"([^\"]+)\"|'([^']+)')"
|
||||
+ "(?:\\s+(?:\"([^\"]+)\"|'([^']+)'))?"
|
||||
+ "\\s*");
|
||||
Matcher m = p.matcher(docType);
|
||||
if (m.matches()) {
|
||||
// See http://www.w3.org/tr/html52/syntax.html#the-doctype
|
||||
if (m.group(1).equalsIgnoreCase("system")
|
||||
&& m.group(2).equals("about:legacy-compat")) {
|
||||
html5_legacy++;
|
||||
} else {
|
||||
String version = m.group(2);
|
||||
List<String> allowedVersions = List.of(
|
||||
"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
);
|
||||
if (allowedVersions.stream().noneMatch(v -> v.equals(version))) {
|
||||
log.log(path, line, "unexpected doctype: " + version);
|
||||
}
|
||||
counts.put(version, counts.getOrDefault(version, 0) + 1);
|
||||
}
|
||||
} else {
|
||||
log.log(path, line, "doctype not recognized: " + docType);
|
||||
other++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(int line, String name, Map<String, String> attrs, boolean selfClosing) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(int line, String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
log.log("DocType Report");
|
||||
if (xml > 0) {
|
||||
log.log("%6d: XHTML%n", xml);
|
||||
}
|
||||
if (html5 > 0) {
|
||||
log.log("%6d: HTML5%n", html5);
|
||||
}
|
||||
if (html5_legacy > 0) {
|
||||
log.log("%6d: HTML5 (legacy)%n", html5_legacy);
|
||||
}
|
||||
|
||||
Map<Integer, Set<String>> sortedCounts = new TreeMap<>(Comparator.reverseOrder());
|
||||
|
||||
for (Map.Entry<String, Integer> e : counts.entrySet()) {
|
||||
String s = e.getKey();
|
||||
Integer n = e.getValue();
|
||||
Set<String> set = sortedCounts.computeIfAbsent(n, k -> new TreeSet<>());
|
||||
set.add(s);
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, Set<String>> e : sortedCounts.entrySet()) {
|
||||
for (String p : e.getValue()) {
|
||||
log.log("%6d: %s%n", e.getKey(), p);
|
||||
}
|
||||
}
|
||||
|
||||
if (other > 0) {
|
||||
log.log("%6d: other/unrecognized%n", other);
|
||||
}
|
||||
|
||||
for (var line : log.getErrors()) {
|
||||
System.err.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return counts.isEmpty() && (other == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (!isOK()) {
|
||||
report();
|
||||
throw new RuntimeException("Found HTML files with missing doctype declaration");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package doccheckutils.checkers;
|
||||
|
||||
|
||||
import doccheckutils.HtmlChecker;
|
||||
import doccheckutils.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Checks the external links referenced in HTML files.
|
||||
*/
|
||||
public class ExtLinkChecker implements HtmlChecker, AutoCloseable {
|
||||
private static final Path testBasePath = Path.of(System.getProperty("test.src"));
|
||||
private static final Set<String> extLinks = new HashSet<>();
|
||||
|
||||
private static final String currentVersion = String.valueOf(Runtime.version().feature());
|
||||
|
||||
static {
|
||||
String input = null;
|
||||
try {
|
||||
input = Files.readString(testBasePath.getParent().resolve("ExtLinksJdk.txt"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
extLinks.addAll(input.lines()
|
||||
.filter(line -> !line.startsWith("#"))
|
||||
.map(line -> line.replaceAll("\\@\\@JAVASE_VERSION\\@\\@", currentVersion))
|
||||
.collect(Collectors.toUnmodifiableSet()));
|
||||
}
|
||||
|
||||
private final Log log;
|
||||
private final Map<URI, Set<Path>> allURIs;
|
||||
private int badURIs;
|
||||
private Path currFile;
|
||||
|
||||
public ExtLinkChecker() {
|
||||
this.log = new Log();
|
||||
allURIs = new TreeMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFile(Path path) {
|
||||
currFile = path.toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFile() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void xml(int line, Map<String, String> attrs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void docType(int line, String doctype) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void startElement(int line, String name, Map<String, String> attrs, boolean selfClosing) {
|
||||
switch (name) {
|
||||
case "a":
|
||||
case "link":
|
||||
String href = attrs.get("href");
|
||||
if (href != null) {
|
||||
foundReference(line, href);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(int line, String name) {
|
||||
}
|
||||
|
||||
private void foundReference(int line, String ref) {
|
||||
try {
|
||||
String uriPath = ref;
|
||||
String fragment = null;
|
||||
|
||||
// The checker runs into a problem with links that have more than one hash character.
|
||||
// You cannot create a URI unless the second hash is escaped.
|
||||
|
||||
int firstHashIndex = ref.indexOf('#');
|
||||
int lastHashIndex = ref.lastIndexOf('#');
|
||||
if (firstHashIndex != -1 && firstHashIndex != lastHashIndex) {
|
||||
uriPath = ref.substring(0, firstHashIndex);
|
||||
fragment = ref.substring(firstHashIndex + 1).replace("#", "%23");
|
||||
} else if (firstHashIndex != -1) {
|
||||
uriPath = ref.substring(0, firstHashIndex);
|
||||
fragment = ref.substring(firstHashIndex + 1);
|
||||
}
|
||||
|
||||
URI uri = new URI(uriPath);
|
||||
if (fragment != null) {
|
||||
uri = new URI(uri + "#" + fragment);
|
||||
}
|
||||
|
||||
if (uri.isAbsolute()) {
|
||||
if (Objects.equals(uri.getScheme(), "javascript")) {
|
||||
// ignore JavaScript URIs
|
||||
return;
|
||||
}
|
||||
String rawFragment = uri.getRawFragment();
|
||||
URI noFrag = new URI(uri.toString().replaceAll("#\\Q" + rawFragment + "\\E$", ""));
|
||||
allURIs.computeIfAbsent(noFrag, _ -> new LinkedHashSet<>()).add(currFile);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
log.log(currFile, line, "invalid URI: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
checkURIs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return badURIs == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
report();
|
||||
}
|
||||
|
||||
private void checkURIs() {
|
||||
System.err.println("ExtLinkChecker: checking external links");
|
||||
allURIs.forEach(this::checkURI);
|
||||
System.err.println("ExtLinkChecker: finished checking external links");
|
||||
}
|
||||
|
||||
private void checkURI(URI uri, Set<Path> files) {
|
||||
try {
|
||||
switch (uri.getScheme()) {
|
||||
case "ftp":
|
||||
case "http":
|
||||
case "https":
|
||||
isVettedLink(uri, files);
|
||||
break;
|
||||
default:
|
||||
warning(files, uri);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
badURIs++;
|
||||
error(files, uri, t);
|
||||
}
|
||||
}
|
||||
|
||||
private void isVettedLink(URI uri, Set<Path> files) {
|
||||
if (!extLinks.contains(uri.toString())) {
|
||||
System.err.println(MessageFormat.format("""
|
||||
The external link {0} needs to be added to the whitelist test/docs/jdk/javadoc/doccheck/ExtLinksJdk.txt in order to be checked regularly\s
|
||||
The link is present in:
|
||||
{1}\n
|
||||
""", uri, files.stream().map(Path::toString).collect(Collectors.joining("\n "))));
|
||||
}
|
||||
}
|
||||
|
||||
private void warning(Set<Path> files, Object... args) {
|
||||
Iterator<Path> iter = files.iterator();
|
||||
Path first = iter.next();
|
||||
log.log(String.valueOf(first), "URI not supported: %s", args);
|
||||
reportAlsoFoundIn(iter);
|
||||
}
|
||||
|
||||
private void error(Set<Path> files, Object... args) {
|
||||
Iterator<Path> iter = files.iterator();
|
||||
Path first = iter.next();
|
||||
log.log(String.valueOf(first), "Exception accessing uri: %s%n [%s]", args);
|
||||
reportAlsoFoundIn(iter);
|
||||
}
|
||||
|
||||
private void reportAlsoFoundIn(Iterator<Path> iter) {
|
||||
int MAX_EXTRA = 10;
|
||||
int n = 0;
|
||||
while (iter.hasNext()) {
|
||||
log.log(" Also found in %s", log.relativize(iter.next()));
|
||||
if (n++ == MAX_EXTRA) {
|
||||
int rest = 0;
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
rest++;
|
||||
}
|
||||
log.log(" ... and %d more", rest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils.checkers;
|
||||
|
||||
|
||||
import doccheckutils.HtmlChecker;
|
||||
import doccheckutils.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Checks the links defined by and referenced in HTML files.
|
||||
*/
|
||||
public class LinkChecker implements HtmlChecker {
|
||||
|
||||
private final Log log;
|
||||
private final Map<Path, IDTable> allFiles;
|
||||
private final Map<URI, IDTable> allURIs;
|
||||
// left for debugging
|
||||
private final boolean checkInwardReferencesOnly = false;
|
||||
private int files;
|
||||
private int links;
|
||||
private int duplicateIds;
|
||||
private int missingFiles;
|
||||
private int missingIds;
|
||||
private int badSchemes;
|
||||
private Path currFile;
|
||||
private IDTable currTable;
|
||||
private boolean html5;
|
||||
public LinkChecker() {
|
||||
this.log = new Log();
|
||||
allFiles = new HashMap<>();
|
||||
allURIs = new HashMap<>();
|
||||
}
|
||||
|
||||
public void setBaseDir(Path dir) {
|
||||
log.setBaseDirectory(dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFile(Path path) {
|
||||
currFile = path.toAbsolutePath().normalize();
|
||||
currTable = allFiles.computeIfAbsent(currFile, p -> new IDTable(log.relativize(p)));
|
||||
html5 = false;
|
||||
files++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFile() {
|
||||
currTable.check();
|
||||
}
|
||||
|
||||
|
||||
//unused
|
||||
public List<Path> getUncheckedFiles() {
|
||||
return allFiles.entrySet().stream()
|
||||
.filter(e -> !e.getValue().checked
|
||||
&& e.getKey().toString().endsWith(".html")
|
||||
&& Files.exists(e.getKey()))
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<Path> getMissingFiles() {
|
||||
return allFiles.keySet().stream()
|
||||
.filter(idTable -> !Files.exists(idTable)).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void xml(int line, Map<String, String> attrs) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void docType(int line, String doctype) {
|
||||
html5 = doctype.matches("(?i)<\\?doctype\\s+html>");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void startElement(int line, String name, Map<String, String> attrs, boolean selfClosing) {
|
||||
switch (name) {
|
||||
case "a":
|
||||
String nameAttr = html5 ? null : attrs.get("name");
|
||||
if (nameAttr != null) {
|
||||
foundAnchor(line, nameAttr);
|
||||
}
|
||||
// fallthrough
|
||||
case "link":
|
||||
String href = attrs.get("href");
|
||||
if (href != null && !checkInwardReferencesOnly) {
|
||||
foundReference(line, href);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
String idAttr = attrs.get("id");
|
||||
if (idAttr != null) {
|
||||
foundAnchor(line, idAttr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(int line, String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void content(int line, String content) {
|
||||
HtmlChecker.super.content(line, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
List<Path> pathList = getMissingFiles();
|
||||
log.log("");
|
||||
log.log("Link Checker Report");
|
||||
|
||||
if (!pathList.isEmpty()) {
|
||||
log.log("");
|
||||
log.log("Missing files: (" + pathList.size() + ")");
|
||||
pathList.stream()
|
||||
.sorted()
|
||||
.forEach(this::reportMissingFile);
|
||||
}
|
||||
|
||||
int anchors = 0;
|
||||
for (IDTable t : allFiles.values()) {
|
||||
anchors += (int) t.map.values().stream()
|
||||
.filter(e -> !e.getReferences().isEmpty())
|
||||
.count();
|
||||
}
|
||||
for (IDTable t : allURIs.values()) {
|
||||
anchors += (int) t.map.values().stream()
|
||||
.filter(e -> !e.references.isEmpty())
|
||||
.count();
|
||||
}
|
||||
|
||||
log.log("Checked " + files + " files.");
|
||||
log.log("Found " + links + " references to " + anchors + " anchors "
|
||||
+ "in " + allFiles.size() + " files and " + allURIs.size() + " other URIs.");
|
||||
if (!pathList.isEmpty()) {
|
||||
log.log("%6d missing files", pathList.size());
|
||||
}
|
||||
if (duplicateIds > 0) {
|
||||
log.log("%6d duplicate ids", duplicateIds);
|
||||
|
||||
}
|
||||
if (missingIds > 0) {
|
||||
log.log("%6d missing ids", missingIds);
|
||||
|
||||
}
|
||||
|
||||
Map<String, Integer> hostCounts = new TreeMap<>(new HostComparator());
|
||||
for (URI uri : allURIs.keySet()) {
|
||||
String host = uri.getHost();
|
||||
if (host != null) {
|
||||
hostCounts.put(host, hostCounts.computeIfAbsent(host, h -> 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// if (hostCounts.size() > 0) {
|
||||
// log.log("");
|
||||
// log.log("Hosts");
|
||||
// hostCounts.forEach((h, n) -> log.log("%6d %s", n, h));
|
||||
// }
|
||||
|
||||
|
||||
for (String message : log.getErrors()) {
|
||||
System.err.println(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void reportMissingFile(Path file) {
|
||||
log.log(log.relativize(file).toString());
|
||||
IDTable table = allFiles.get(file);
|
||||
Set<Path> refs = new TreeSet<>();
|
||||
for (IDInfo id : table.map.values()) {
|
||||
if (id.references != null) {
|
||||
for (Position ref : id.references) {
|
||||
refs.add(ref.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
int n = 0;
|
||||
int MAX_REFS = 10;
|
||||
for (Path ref : refs) {
|
||||
log.log(" in " + log.relativize(ref));
|
||||
if (++n == MAX_REFS) {
|
||||
log.log(" ... and %d more", refs.size() - n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
missingFiles++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return log.noErrors() && (missingFiles == 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (!log.noErrors()) {
|
||||
report();
|
||||
throw new RuntimeException("LinkChecker encountered errors; see log above.");
|
||||
}
|
||||
}
|
||||
|
||||
private void foundAnchor(int line, String name) {
|
||||
currTable.addID(line, name);
|
||||
}
|
||||
|
||||
private void foundReference(int line, String ref) {
|
||||
links++;
|
||||
try {
|
||||
String uriPath = ref;
|
||||
String fragment = null;
|
||||
|
||||
// The checker runs into a problem with links that have more than one hash character.
|
||||
// You cannot create a URI unless the second hash is escaped.
|
||||
|
||||
int firstHashIndex = ref.indexOf('#');
|
||||
int lastHashIndex = ref.lastIndexOf('#');
|
||||
if (firstHashIndex != -1 && firstHashIndex != lastHashIndex) {
|
||||
uriPath = ref.substring(0, firstHashIndex);
|
||||
fragment = ref.substring(firstHashIndex + 1).replace("#", "%23");
|
||||
} else if (firstHashIndex != -1) {
|
||||
uriPath = ref.substring(0, firstHashIndex);
|
||||
fragment = ref.substring(firstHashIndex + 1);
|
||||
}
|
||||
|
||||
URI uri = new URI(uriPath);
|
||||
if (fragment != null) {
|
||||
uri = new URI(uri + "#" + fragment);
|
||||
}
|
||||
|
||||
if (uri.isAbsolute()) {
|
||||
foundReference(line, uri);
|
||||
} else {
|
||||
Path p;
|
||||
String resolvedUriPath = uri.getPath();
|
||||
if (resolvedUriPath == null || resolvedUriPath.isEmpty()) {
|
||||
p = currFile;
|
||||
} else {
|
||||
p = currFile.getParent().resolve(resolvedUriPath).normalize();
|
||||
}
|
||||
|
||||
if (!Files.exists(p)) {
|
||||
log.log(currFile, line, "missing file reference: " + log.relativize(p));
|
||||
return;
|
||||
}
|
||||
|
||||
if (fragment != null && !fragment.isEmpty()) {
|
||||
foundReference(line, p, fragment);
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
System.err.println("Failed to create URI: " + ref);
|
||||
log.log(currFile, line, "invalid URI: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void foundReference(int line, Path p, String fragment) {
|
||||
IDTable t = allFiles.computeIfAbsent(p, key -> new IDTable(log.relativize(key)));
|
||||
t.addReference(fragment, currFile, line);
|
||||
}
|
||||
|
||||
private void foundReference(int line, URI uri) {
|
||||
if (!isSchemeOK(uri.getScheme()) && !checkInwardReferencesOnly) {
|
||||
log.log(currFile, line, "bad scheme in URI");
|
||||
badSchemes++;
|
||||
}
|
||||
|
||||
String fragment = uri.getRawFragment();
|
||||
if (fragment != null && !fragment.isEmpty()) {
|
||||
try {
|
||||
URI noFrag = new URI(uri.toString().replaceAll("#\\Q" + fragment + "\\E$", ""));
|
||||
IDTable t = allURIs.computeIfAbsent(noFrag, IDTable::new);
|
||||
t.addReference(fragment, currFile, line);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSchemeOK(String uriScheme) {
|
||||
if (uriScheme == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return switch (uriScheme) {
|
||||
case "ftp", "http", "https", "javascript" -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
static class Position implements Comparable<Position> {
|
||||
Path path;
|
||||
int line;
|
||||
|
||||
Position(Path path, int line) {
|
||||
this.path = path;
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Position o) {
|
||||
int v = path.compareTo(o.path);
|
||||
return v != 0 ? v : Integer.compare(line, o.line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
} else if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
} else {
|
||||
final Position other = (Position) obj;
|
||||
return Objects.equals(this.path, other.path)
|
||||
&& this.line == other.line;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(path) * 37 + line;
|
||||
}
|
||||
}
|
||||
|
||||
static class IDInfo {
|
||||
boolean declared;
|
||||
Set<Position> references;
|
||||
|
||||
Set<Position> getReferences() {
|
||||
return references == null ? Collections.emptySet() : references;
|
||||
}
|
||||
}
|
||||
|
||||
static class HostComparator implements Comparator<String> {
|
||||
@Override
|
||||
public int compare(String h1, String h2) {
|
||||
List<String> l1 = new ArrayList<>(Arrays.asList(h1.split("\\.")));
|
||||
Collections.reverse(l1);
|
||||
String r1 = String.join(".", l1);
|
||||
List<String> l2 = new ArrayList<>(Arrays.asList(h2.split("\\.")));
|
||||
Collections.reverse(l2);
|
||||
String r2 = String.join(".", l2);
|
||||
return r1.compareTo(r2);
|
||||
}
|
||||
}
|
||||
|
||||
class IDTable {
|
||||
private final Map<String, IDInfo> map = new HashMap<>();
|
||||
private final String pathOrURI;
|
||||
private boolean checked;
|
||||
|
||||
IDTable(Path path) {
|
||||
this.pathOrURI = path.toString();
|
||||
}
|
||||
|
||||
IDTable(URI uri) {
|
||||
this.pathOrURI = uri.toString();
|
||||
}
|
||||
|
||||
void addID(int line, String name) {
|
||||
if (checked) {
|
||||
throw new IllegalStateException("Adding ID after file has been checked");
|
||||
}
|
||||
Objects.requireNonNull(name);
|
||||
IDInfo info = map.computeIfAbsent(name, _ -> new IDInfo());
|
||||
if (info.declared) {
|
||||
if (info.references != null || !checkInwardReferencesOnly) {
|
||||
// don't report error if we're only checking inbound references
|
||||
// and there are no references to this ID.
|
||||
log.log(log.relativize(currFile), line, "name already declared: " + name);
|
||||
duplicateIds++;
|
||||
}
|
||||
} else {
|
||||
info.declared = true;
|
||||
}
|
||||
}
|
||||
|
||||
void addReference(String name, Path from, int line) {
|
||||
if (checked) {
|
||||
if (name != null) {
|
||||
IDInfo id = map.get(name);
|
||||
if (id == null || !id.declared) {
|
||||
log.log(log.relativize(from), line,
|
||||
"id not found: " + this.pathOrURI + "#" + name);
|
||||
LinkChecker.this.missingIds++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IDInfo id = map.computeIfAbsent(name, x -> new IDInfo());
|
||||
if (id.references == null) {
|
||||
id.references = new TreeSet<>();
|
||||
}
|
||||
id.references.add(new Position(from, line));
|
||||
}
|
||||
}
|
||||
|
||||
void check() {
|
||||
map.forEach((name, id) -> {
|
||||
if (name != null && !id.declared) {
|
||||
for (Position ref : id.references) {
|
||||
log.log(log.relativize(ref.path), ref.line,
|
||||
"id not found: " + this.pathOrURI + "#" + name);
|
||||
}
|
||||
missingIds++;
|
||||
}
|
||||
});
|
||||
checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package doccheckutils.checkers;
|
||||
|
||||
|
||||
import doccheckutils.FileChecker;
|
||||
import doccheckutils.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jtreg.SkippedException;
|
||||
|
||||
public class TidyChecker implements FileChecker, AutoCloseable {
|
||||
private final Path TIDY;
|
||||
final Map<Pattern, Integer> counts = new HashMap<>();
|
||||
final Pattern okPattern = Pattern.compile("No warnings or errors were found.");
|
||||
final Pattern countPattern = Pattern.compile("([0-9]+) warnings, ([0-9]+) errors were found!.*?(Not all warnings/errors were shown.)?");
|
||||
final Pattern countPattern2 = Pattern.compile("Tidy found ([0-9]+) warning[s]? and ([0-9]+) error[s]?!.*?(Not all warnings/errors were shown.)?");
|
||||
final Pattern cssPattern = Pattern.compile("You are recommended to use CSS.*");
|
||||
final Pattern guardPattern = Pattern.compile("(line [0-9]+ column [0-9]+ - |[^:]+:[0-9]+:[0-9]+: )(Error|Warning):.*");
|
||||
|
||||
final Pattern[] patterns = {
|
||||
Pattern.compile(".*Error: <.*> is not recognized!"),
|
||||
Pattern.compile(".*Error: missing quote mark for attribute value"),
|
||||
Pattern.compile(".*Warning: '<' \\+ '/' \\+ letter not allowed here"),
|
||||
Pattern.compile(".*Warning: <.*> anchor \".*\" already defined"),
|
||||
Pattern.compile(".*Warning: <.*> attribute \".*\" has invalid value \".*\""),
|
||||
Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
|
||||
Pattern.compile(".*Warning: <.*> attribute \".*\" lacks value"),
|
||||
Pattern.compile(".*Warning: <.*> attribute with missing trailing quote mark"),
|
||||
Pattern.compile(".*Warning: <.*> dropping value \".*\" for repeated attribute \".*\""),
|
||||
Pattern.compile(".*Warning: <.*> inserting \".*\" attribute"),
|
||||
Pattern.compile(".*Warning: <.*> is probably intended as </.*>"),
|
||||
Pattern.compile(".*Warning: <.*> isn't allowed in <.*> elements"),
|
||||
Pattern.compile(".*Warning: <.*> lacks \".*\" attribute"),
|
||||
Pattern.compile(".*Warning: <.*> missing '>' for end of tag"),
|
||||
Pattern.compile(".*Warning: <.*> proprietary attribute \".*\""),
|
||||
Pattern.compile(".*Warning: <.*> unexpected or duplicate quote mark"),
|
||||
Pattern.compile(".*Warning: <a> id and name attribute value mismatch"),
|
||||
Pattern.compile(".*Warning: <a> cannot copy name attribute to id"),
|
||||
Pattern.compile(".*Warning: <a> escaping malformed URI reference"),
|
||||
Pattern.compile(".*Warning: <blockquote> proprietary attribute \"pre\""),
|
||||
Pattern.compile(".*Warning: discarding unexpected <.*>"),
|
||||
Pattern.compile(".*Warning: discarding unexpected </.*>"),
|
||||
Pattern.compile(".*Warning: entity \".*\" doesn't end in ';'"),
|
||||
Pattern.compile(".*Warning: inserting implicit <.*>"),
|
||||
Pattern.compile(".*Warning: inserting missing 'title' element"),
|
||||
Pattern.compile(".*Warning: missing <!DOCTYPE> declaration"),
|
||||
Pattern.compile(".*Warning: missing <.*>"),
|
||||
Pattern.compile(".*Warning: missing </.*> before <.*>"),
|
||||
Pattern.compile(".*Warning: nested emphasis <.*>"),
|
||||
Pattern.compile(".*Warning: plain text isn't allowed in <.*> elements"),
|
||||
Pattern.compile(".*Warning: removing whitespace preceding XML Declaration"),
|
||||
Pattern.compile(".*Warning: replacing <p> (by|with) <br>"),
|
||||
Pattern.compile(".*Warning: replacing invalid numeric character reference .*"),
|
||||
Pattern.compile(".*Warning: replacing obsolete element <xmp> with <pre>"),
|
||||
Pattern.compile(".*Warning: replacing unexpected .* (by|with) </.*>"),
|
||||
Pattern.compile(".*Warning: trimming empty <.*>"),
|
||||
Pattern.compile(".*Warning: unescaped & or unknown entity \".*\""),
|
||||
Pattern.compile(".*Warning: unescaped & which should be written as &"),
|
||||
Pattern.compile(".*Warning: using <br> in place of <p>"),
|
||||
Pattern.compile(".*Warning: <.*> element removed from HTML5"),
|
||||
Pattern.compile(".*Warning: <.*> attribute \".*\" not allowed for HTML5"),
|
||||
Pattern.compile(".*Warning: The summary attribute on the <table> element is obsolete in HTML5"),
|
||||
Pattern.compile(".*Warning: replacing invalid UTF-8 bytes \\(char. code U\\+.*\\)")
|
||||
};
|
||||
private final Log errors;
|
||||
private int files = 0;
|
||||
private int ok;
|
||||
private int warns;
|
||||
private int errs;
|
||||
private int css;
|
||||
private int overflow;
|
||||
|
||||
public TidyChecker() {
|
||||
TIDY = initTidy();
|
||||
errors = new Log();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkFiles(List<Path> sb) {
|
||||
files += sb.size();
|
||||
try {
|
||||
for (int i = 0; i < sb.size(); i += 1024) {
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(TIDY.toString());
|
||||
command.add("-q");
|
||||
command.add("-e");
|
||||
command.add("--gnu-emacs");
|
||||
command.add("true");
|
||||
List<Path> sublist = sb.subList(i, Math.min(i + 1024, sb.size()));
|
||||
for (Path p : sublist) {
|
||||
command.add(p.toString());
|
||||
}
|
||||
Process p = new ProcessBuilder()
|
||||
.command(command)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
try (BufferedReader r =
|
||||
new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) {
|
||||
checkLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
private Path initTidy() {
|
||||
Path tidyExePath;
|
||||
String tidyProperty = System.getProperty("tidy");
|
||||
if (tidyProperty != null) {
|
||||
tidyExePath = Path.of(tidyProperty);
|
||||
if (!Files.exists(tidyExePath)) {
|
||||
System.err.println("tidy not found: " + tidyExePath);
|
||||
}
|
||||
if (!Files.isExecutable(tidyExePath)) {
|
||||
System.err.println("tidy not executable: " + tidyExePath);
|
||||
}
|
||||
} else {
|
||||
boolean isWindows = System.getProperty("os.name")
|
||||
.toLowerCase(Locale.US)
|
||||
.startsWith("windows");
|
||||
String tidyExe = isWindows ? "tidy.exe" : "tidy";
|
||||
Optional<Path> p = Stream.of(System.getenv("PATH")
|
||||
.split(File.pathSeparator))
|
||||
.map(Path::of)
|
||||
.map(d -> d.resolve(tidyExe))
|
||||
.filter(Files::exists)
|
||||
.filter(Files::isExecutable)
|
||||
.findFirst();
|
||||
if (p.isPresent()) {
|
||||
tidyExePath = p.get();
|
||||
} else {
|
||||
throw new jtreg.SkippedException("tidy not found on PATH");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Process p = new ProcessBuilder()
|
||||
.command(tidyExePath.toString(), "-version")
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
try (BufferedReader r =
|
||||
new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
List<String> lines = r.lines().collect(Collectors.toList());
|
||||
// Look for a line containing "version" and a dotted identifier beginning 5.
|
||||
// If not found, look for known old/bad versions, to report in error message
|
||||
Pattern version = Pattern.compile("version.* [5678]\\.\\d+(\\.\\d+)");
|
||||
if (lines.stream().noneMatch(line -> version.matcher(line).find())) {
|
||||
Pattern oldVersion = Pattern.compile("2006"); // 2006 implies old macOS version
|
||||
String lineSep = System.lineSeparator();
|
||||
String message = lines.stream().anyMatch(line -> oldVersion.matcher(line).find())
|
||||
? "old version of 'tidy' found on the PATH\n"
|
||||
: "could not determine the version of 'tidy' on the PATH\n";
|
||||
System.err.println(message + String.join(lineSep, lines));
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not execute 'tidy -version': " + e);
|
||||
}
|
||||
|
||||
return tidyExePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void report() {
|
||||
if (files > 0) {
|
||||
System.err.println("Tidy found errors in the generated HTML");
|
||||
if (!errors.noErrors()) {
|
||||
for (String s : errors.getErrors()) {
|
||||
System.err.println(s);
|
||||
}
|
||||
System.err.println("Tidy output end.");
|
||||
System.err.println();
|
||||
System.err.println();
|
||||
throw new RuntimeException("Tidy found errors in the generated HTML");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOK() {
|
||||
return (ok == files)
|
||||
&& (overflow == 0)
|
||||
&& (errs == 0)
|
||||
&& (warns == 0)
|
||||
&& (css == 0);
|
||||
}
|
||||
|
||||
void checkLine(String line) {
|
||||
Matcher m;
|
||||
if (okPattern.matcher(line).matches()) {
|
||||
ok++;
|
||||
} else if ((m = countPattern.matcher(line)).matches() || (m = countPattern2.matcher(line)).matches()) {
|
||||
warns += Integer.parseInt(m.group(1));
|
||||
errs += Integer.parseInt(m.group(2));
|
||||
if (m.group(3) != null)
|
||||
overflow++;
|
||||
} else if (guardPattern.matcher(line).matches()) {
|
||||
boolean found = false;
|
||||
for (Pattern p : patterns) {
|
||||
if (p.matcher(line).matches()) {
|
||||
errors.log("%s", line);
|
||||
found = true;
|
||||
count(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
errors.log("unrecognized line: " + line);
|
||||
} else if (cssPattern.matcher(line).matches()) {
|
||||
css++;
|
||||
}
|
||||
}
|
||||
|
||||
void count(Pattern p) {
|
||||
Integer i = counts.get(p);
|
||||
counts.put(p, (i == null) ? 1 : i + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
report();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue