Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8259530: Generated docs contain MIT/GPL-licenced works without reprod…
…ucing the licence

Reviewed-by: phh
Backport-of: e9f3e32
  • Loading branch information
yukikimmura authored and Paul Hohensee committed Mar 31, 2023
1 parent 6dedd8a commit 3c8c45e
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 7 deletions.
Expand Up @@ -122,6 +122,11 @@ public class HtmlConfiguration extends BaseConfiguration {
*/
public String helpfile = "";

/**
* Argument for command-line option "--legal-notices".
*/
public String legalnotices = "";

/**
* Argument for command line option "-stylesheetfile".
*/
Expand Down Expand Up @@ -656,6 +661,13 @@ public boolean process(String opt, List<String> args) {
return true;
}
},
new Option(resources, "--legal-notices", 1) {
@Override
public boolean process(String opt, List<String> args) {
legalnotices = args.get(0);
return true;
}
},
new Option(resources, "-nohelp") {
@Override
public boolean process(String opt, List<String> args) {
Expand Down
Expand Up @@ -25,6 +25,13 @@

package jdk.javadoc.internal.doclets.formats.html;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.*;

import javax.lang.model.element.ModuleElement;
Expand Down Expand Up @@ -206,6 +213,8 @@ protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
f = DocFile.createFileForOutput(configuration, DocPaths.JQUERY_OVERRIDES_CSS);
f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.JQUERY_OVERRIDES_CSS), true, true);
}

copyLegalFiles(configuration.createindex);
}

private void copyJqueryFiles() throws DocletException {
Expand All @@ -228,6 +237,46 @@ private void copyJqueryFiles() throws DocletException {
}
}

private void copyLegalFiles(boolean includeJQuery) throws DocletException {
Path legalNoticesDir;
String legalNotices = configuration.legalnotices;
switch (legalNotices) {
case "":
case "default" :
Path javaHome = Path.of(System.getProperty("java.home"));
legalNoticesDir = javaHome.resolve("legal").resolve(getClass().getModule().getName());
break;
case "none":
return;
default:
try {
legalNoticesDir = Path.of(legalNotices);
} catch (InvalidPathException e) {
messages.error("doclet.Error_invalid_path_for_legal_notices",
legalNotices, e.getMessage());
return;
}
}

if (Files.exists(legalNoticesDir)) {
try (DirectoryStream<Path> ds = Files.newDirectoryStream(legalNoticesDir)) {
for (Path entry: ds) {
if (!Files.isRegularFile(entry)) {
continue;
}
if (entry.getFileName().toString().startsWith("jquery") && !includeJQuery) {
continue;
}
DocPath filePath = DocPaths.LEGAL.resolve(entry.getFileName().toString());
DocFile df = DocFile.createFileForOutput(configuration, filePath);
df.copyFile(DocFile.createFileForInput(configuration, entry));
}
} catch (IOException e) {
messages.error("doclet.Error_copying_legal_notices", e);
}
}
}

/**
* {@inheritDoc}
*/
Expand Down
Expand Up @@ -235,6 +235,11 @@ doclet.Error_in_grouplist=Bad -group option: {0} {1}
doclet.Groupname_already_used=In -group option, group name already used: {0}
doclet.Same_element_name_used=Element name or pattern used twice: {0}

# 0: an exception
doclet.Error_copying_legal_notices=Error while copying legal notices: {0}
# 0: the path; 1: the detail message for the exception
doclet.Error_invalid_path_for_legal_notices=Invalid path ''{0}'' for legal notices: {1}

# option specifiers
doclet.usage.add-stylesheet.parameters=\
<file>
Expand Down Expand Up @@ -321,6 +326,11 @@ doclet.usage.group.parameters=\
doclet.usage.group.description=\
Group specified elements together in overview page

doclet.usage.legal-notices.parameters=\
'default' | 'none' | <directory>
doclet.usage.legal-notices.description=\
Control legal notices in the generated output

doclet.usage.nocomment.description=\
Suppress description and tags, generate only declarations

Expand Down
Expand Up @@ -32,6 +32,7 @@
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.file.Path;

import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
Expand Down Expand Up @@ -61,6 +62,11 @@ public static DocFile createFileForInput(BaseConfiguration configuration, String
return DocFileFactory.getFactory(configuration).createFileForInput(file);
}

/** Create a DocFile for a file that will be opened for reading. */
public static DocFile createFileForInput(BaseConfiguration configuration, Path file) {
return DocFileFactory.getFactory(configuration).createFileForInput(file);
}

/** Create a DocFile for a file that will be opened for writing. */
public static DocFile createFileForOutput(BaseConfiguration configuration, DocPath path) {
return DocFileFactory.getFactory(configuration).createFileForOutput(path);
Expand Down
Expand Up @@ -25,6 +25,7 @@

package jdk.javadoc.internal.doclets.toolkit.util;

import java.nio.file.Path;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileManager.Location;
import javax.tools.StandardJavaFileManager;
Expand Down Expand Up @@ -78,6 +79,9 @@ protected DocFileFactory(BaseConfiguration configuration) {
/** Create a DocFile for a file that will be opened for reading. */
abstract DocFile createFileForInput(String file);

/** Create a DocFile for a file that will be opened for reading. */
abstract DocFile createFileForInput(Path file);

/** Create a DocFile for a file that will be opened for writing. */
abstract DocFile createFileForOutput(DocPath path);

Expand Down
Expand Up @@ -115,7 +115,7 @@ public static DocPath indexN(int n) {
/** The name of the stylesheet file overriding jQuery UI stylesheet. */
public static final DocPath JQUERY_OVERRIDES_CSS = DocPath.create("jquery-ui.overrides.css");

/** The name of the directory for the jQuery. */
/** The name of the directory for the jQuery files. */
public static final DocPath JQUERY_FILES = DocPath.create("jquery");

/** The name of the default jQuery javascript file. */
Expand All @@ -130,6 +130,9 @@ public static DocPath indexN(int n) {
/** The name of the jQuery UI stylesheet file containing structural declarations. */
public static final DocPath JQUERY_UI_STRUCTURE_CSS = DocPath.create("jquery-ui.structure.min.css");

/** The name of the directory for legal files. */
public static final DocPath LEGAL = DocPath.create("legal");

/** The name of the default jszip javascript file. */
public static final DocPath JSZIP = DocPath.create("jszip/dist/jszip.js");

Expand Down
Expand Up @@ -109,6 +109,11 @@ public DocFile createFileForInput(String file) {
return new StandardDocFile(Paths.get(file));
}

@Override
public DocFile createFileForInput(Path file) {
return new StandardDocFile(file);
}

@Override
public DocFile createFileForOutput(DocPath path) {
return new StandardDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
Expand Down Expand Up @@ -140,12 +145,12 @@ class StandardDocFile extends DocFile {
private final Path file;

/** Create a StandardDocFile for a given file. */
private StandardDocFile(Path file) {
StandardDocFile(Path file) {
this.file = file;
}

/** Create a StandardDocFile for a given location and relative path. */
private StandardDocFile(Location location, DocPath path) {
StandardDocFile(Location location, DocPath path) {
super(location, path);
Assert.check(location == DocumentationTool.Location.DOCUMENTATION_OUTPUT);
this.file = newFile(getDestDir(), path.getPath());
Expand Down
@@ -0,0 +1,188 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8259530
* @summary Generated docs contain MIT/GPL-licenced works without reproducing the licence
* @library /tools/lib ../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build toolbox.ToolBox JavadocTester
* @run main TestLegalNotices
*/

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;

// import javadoc.tester.JavadocTester;
import toolbox.ToolBox;

public class TestLegalNotices extends JavadocTester {
public static void main(String... args) throws Exception {
TestLegalNotices tester = new TestLegalNotices();
tester.runTests(m -> new Object[]{Path.of(m.getName())});
}

private final ToolBox tb = new ToolBox();

enum OptionKind {
UNSET, DEFAULT, NONE, DIR
}

enum IndexKind {
INDEX, NO_INDEX
}


@Test
public void testCombo(Path base) throws IOException {
Path src = base.resolve("src");
tb.writeJavaFiles(src, "package p; public class C { }");
Path legal = base.resolve("toy-legal");
tb.writeFile(legal.resolve("TOY-LICENSE"), "This is a demo license.");

for (var optionKind : OptionKind.values()) {
for (var indexKind : IndexKind.values()) {
test(base, src, legal, optionKind, indexKind);
}
}
}

void test(Path base, Path src, Path legal, OptionKind optionKind, IndexKind indexKind) throws IOException {
System.out.println("testing " + optionKind + " " + indexKind);
Path out = base.resolve(optionKind + "-" + indexKind).resolve("out");
List<String> args = new ArrayList<>();
args.addAll(List.of(
"-d", out.toString()));

if (indexKind == IndexKind.NO_INDEX) {
args.add("-noindex");
}

args.addAll(List.of(
"-Xdoclint:-missing",
"--source-path", src.toString(),
"p"));

String value = null;
switch (optionKind) {
case UNSET:
value = null;
break;
case DEFAULT:
value = "default";
break;
case NONE:
value = "none";
break;
case DIR:
value= legal.toString();
break;
}
if (value != null) {
args.addAll(List.of("--legal-notices", value));
}
javadoc(args.toArray(new String[0]));

Set<Path> expectFiles = getExpectFiles(optionKind, indexKind, legal);
Set<Path> foundFiles = listFiles(out.resolve("legal"));

checking("Checking legal notice files");
super.out.println("Expected: " + expectFiles);
super.out.println(" Found: " + foundFiles);
if (foundFiles.equals(expectFiles)) {
passed("Found all expected files");
}
}

Set<Path> getExpectFiles(OptionKind optionKind, IndexKind indexKind, Path legal) throws IOException {
switch (optionKind) {
case UNSET:
case DEFAULT:
Path javaHome = Path.of(System.getProperty("java.home"));
Path legal_javadoc = javaHome.resolve("legal").resolve("jdk.javadoc");
return listFiles(legal_javadoc, p -> {
switch (indexKind) {
case INDEX:
return true;
case NO_INDEX:
return !p.getFileName().toString().contains("jquery");
default:
throw new AssertionError("Should not reach");
} } );

/*
return listFiles(legal_javadoc, p -> {
if (indexKind==IndexKind.INDEX) {
return true;
}
else if (indexKind==IndexKind.NO_INDEX) {
return !p.getFileName().toString().contains("jquery");
}
else {
return false;
} } );
*/

/*
return listFiles(legal_javadoc, p ->
(indexKind==IndexKind.INDEX) ? true
: (indexKind==IndexKind.NO_INDEX) ? !p.getFileName().toString().contains("jquery") : false);
*/

case NONE:
return Collections.emptySet();
case DIR:
return listFiles(legal);
}
throw new IllegalStateException();
}

Set<Path> listFiles(Path dir) throws IOException {
return listFiles(dir, p -> true);
}

Set<Path> listFiles(Path dir, Predicate<Path> filter) throws IOException {
if (!Files.exists(dir)) {
return Collections.emptySet();
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
Set<Path> files = new TreeSet<>();
for (Path p : ds) {
if (!Files.isDirectory(p) && filter.test(p)) {
files.add(p.getFileName());
}
}
return files;
}
}
}

1 comment on commit 3c8c45e

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.