Skip to content

Commit 3c8c45e

Browse files
yukikimmuraPaul Hohensee
authored and
Paul Hohensee
committed
8259530: Generated docs contain MIT/GPL-licenced works without reproducing the licence
Reviewed-by: phh Backport-of: e9f3e32
1 parent 6dedd8a commit 3c8c45e

File tree

11 files changed

+288
-7
lines changed

11 files changed

+288
-7
lines changed

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java

+12
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ public class HtmlConfiguration extends BaseConfiguration {
122122
*/
123123
public String helpfile = "";
124124

125+
/**
126+
* Argument for command-line option "--legal-notices".
127+
*/
128+
public String legalnotices = "";
129+
125130
/**
126131
* Argument for command line option "-stylesheetfile".
127132
*/
@@ -656,6 +661,13 @@ public boolean process(String opt, List<String> args) {
656661
return true;
657662
}
658663
},
664+
new Option(resources, "--legal-notices", 1) {
665+
@Override
666+
public boolean process(String opt, List<String> args) {
667+
legalnotices = args.get(0);
668+
return true;
669+
}
670+
},
659671
new Option(resources, "-nohelp") {
660672
@Override
661673
public boolean process(String opt, List<String> args) {

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java

+49
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525

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

28+
import java.io.IOException;
29+
import java.io.OutputStream;
30+
import java.io.Writer;
31+
import java.nio.file.DirectoryStream;
32+
import java.nio.file.Files;
33+
import java.nio.file.InvalidPathException;
34+
import java.nio.file.Path;
2835
import java.util.*;
2936

3037
import javax.lang.model.element.ModuleElement;
@@ -206,6 +213,8 @@ protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
206213
f = DocFile.createFileForOutput(configuration, DocPaths.JQUERY_OVERRIDES_CSS);
207214
f.copyResource(DOCLET_RESOURCES.resolve(DocPaths.JQUERY_OVERRIDES_CSS), true, true);
208215
}
216+
217+
copyLegalFiles(configuration.createindex);
209218
}
210219

211220
private void copyJqueryFiles() throws DocletException {
@@ -228,6 +237,46 @@ private void copyJqueryFiles() throws DocletException {
228237
}
229238
}
230239

240+
private void copyLegalFiles(boolean includeJQuery) throws DocletException {
241+
Path legalNoticesDir;
242+
String legalNotices = configuration.legalnotices;
243+
switch (legalNotices) {
244+
case "":
245+
case "default" :
246+
Path javaHome = Path.of(System.getProperty("java.home"));
247+
legalNoticesDir = javaHome.resolve("legal").resolve(getClass().getModule().getName());
248+
break;
249+
case "none":
250+
return;
251+
default:
252+
try {
253+
legalNoticesDir = Path.of(legalNotices);
254+
} catch (InvalidPathException e) {
255+
messages.error("doclet.Error_invalid_path_for_legal_notices",
256+
legalNotices, e.getMessage());
257+
return;
258+
}
259+
}
260+
261+
if (Files.exists(legalNoticesDir)) {
262+
try (DirectoryStream<Path> ds = Files.newDirectoryStream(legalNoticesDir)) {
263+
for (Path entry: ds) {
264+
if (!Files.isRegularFile(entry)) {
265+
continue;
266+
}
267+
if (entry.getFileName().toString().startsWith("jquery") && !includeJQuery) {
268+
continue;
269+
}
270+
DocPath filePath = DocPaths.LEGAL.resolve(entry.getFileName().toString());
271+
DocFile df = DocFile.createFileForOutput(configuration, filePath);
272+
df.copyFile(DocFile.createFileForInput(configuration, entry));
273+
}
274+
} catch (IOException e) {
275+
messages.error("doclet.Error_copying_legal_notices", e);
276+
}
277+
}
278+
}
279+
231280
/**
232281
* {@inheritDoc}
233282
*/

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties

+10
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ doclet.Error_in_grouplist=Bad -group option: {0} {1}
235235
doclet.Groupname_already_used=In -group option, group name already used: {0}
236236
doclet.Same_element_name_used=Element name or pattern used twice: {0}
237237

238+
# 0: an exception
239+
doclet.Error_copying_legal_notices=Error while copying legal notices: {0}
240+
# 0: the path; 1: the detail message for the exception
241+
doclet.Error_invalid_path_for_legal_notices=Invalid path ''{0}'' for legal notices: {1}
242+
238243
# option specifiers
239244
doclet.usage.add-stylesheet.parameters=\
240245
<file>
@@ -321,6 +326,11 @@ doclet.usage.group.parameters=\
321326
doclet.usage.group.description=\
322327
Group specified elements together in overview page
323328

329+
doclet.usage.legal-notices.parameters=\
330+
'default' | 'none' | <directory>
331+
doclet.usage.legal-notices.description=\
332+
Control legal notices in the generated output
333+
324334
doclet.usage.nocomment.description=\
325335
Suppress description and tags, generate only declarations
326336

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFile.java

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.io.OutputStream;
3333
import java.io.UnsupportedEncodingException;
3434
import java.io.Writer;
35+
import java.nio.file.Path;
3536

3637
import javax.tools.FileObject;
3738
import javax.tools.JavaFileManager.Location;
@@ -61,6 +62,11 @@ public static DocFile createFileForInput(BaseConfiguration configuration, String
6162
return DocFileFactory.getFactory(configuration).createFileForInput(file);
6263
}
6364

65+
/** Create a DocFile for a file that will be opened for reading. */
66+
public static DocFile createFileForInput(BaseConfiguration configuration, Path file) {
67+
return DocFileFactory.getFactory(configuration).createFileForInput(file);
68+
}
69+
6470
/** Create a DocFile for a file that will be opened for writing. */
6571
public static DocFile createFileForOutput(BaseConfiguration configuration, DocPath path) {
6672
return DocFileFactory.getFactory(configuration).createFileForOutput(path);

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFileFactory.java

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

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

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

82+
/** Create a DocFile for a file that will be opened for reading. */
83+
abstract DocFile createFileForInput(Path file);
84+
8185
/** Create a DocFile for a file that will be opened for writing. */
8286
abstract DocFile createFileForOutput(DocPath path);
8387

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public static DocPath indexN(int n) {
115115
/** The name of the stylesheet file overriding jQuery UI stylesheet. */
116116
public static final DocPath JQUERY_OVERRIDES_CSS = DocPath.create("jquery-ui.overrides.css");
117117

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

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

133+
/** The name of the directory for legal files. */
134+
public static final DocPath LEGAL = DocPath.create("legal");
135+
133136
/** The name of the default jszip javascript file. */
134137
public static final DocPath JSZIP = DocPath.create("jszip/dist/jszip.js");
135138

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/StandardDocFileFactory.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ public DocFile createFileForInput(String file) {
109109
return new StandardDocFile(Paths.get(file));
110110
}
111111

112+
@Override
113+
public DocFile createFileForInput(Path file) {
114+
return new StandardDocFile(file);
115+
}
116+
112117
@Override
113118
public DocFile createFileForOutput(DocPath path) {
114119
return new StandardDocFile(DocumentationTool.Location.DOCUMENTATION_OUTPUT, path);
@@ -140,12 +145,12 @@ class StandardDocFile extends DocFile {
140145
private final Path file;
141146

142147
/** Create a StandardDocFile for a given file. */
143-
private StandardDocFile(Path file) {
148+
StandardDocFile(Path file) {
144149
this.file = file;
145150
}
146151

147152
/** Create a StandardDocFile for a given location and relative path. */
148-
private StandardDocFile(Location location, DocPath path) {
153+
StandardDocFile(Location location, DocPath path) {
149154
super(location, path);
150155
Assert.check(location == DocumentationTool.Location.DOCUMENTATION_OUTPUT);
151156
this.file = newFile(getDestDir(), path.getPath());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8259530
27+
* @summary Generated docs contain MIT/GPL-licenced works without reproducing the licence
28+
* @library /tools/lib ../lib
29+
* @modules jdk.javadoc/jdk.javadoc.internal.tool
30+
* @build toolbox.ToolBox JavadocTester
31+
* @run main TestLegalNotices
32+
*/
33+
34+
import java.io.IOException;
35+
import java.nio.file.DirectoryStream;
36+
import java.nio.file.Files;
37+
import java.nio.file.Path;
38+
import java.util.ArrayList;
39+
import java.util.Collections;
40+
import java.util.List;
41+
import java.util.Set;
42+
import java.util.TreeSet;
43+
import java.util.function.Predicate;
44+
45+
// import javadoc.tester.JavadocTester;
46+
import toolbox.ToolBox;
47+
48+
public class TestLegalNotices extends JavadocTester {
49+
public static void main(String... args) throws Exception {
50+
TestLegalNotices tester = new TestLegalNotices();
51+
tester.runTests(m -> new Object[]{Path.of(m.getName())});
52+
}
53+
54+
private final ToolBox tb = new ToolBox();
55+
56+
enum OptionKind {
57+
UNSET, DEFAULT, NONE, DIR
58+
}
59+
60+
enum IndexKind {
61+
INDEX, NO_INDEX
62+
}
63+
64+
65+
@Test
66+
public void testCombo(Path base) throws IOException {
67+
Path src = base.resolve("src");
68+
tb.writeJavaFiles(src, "package p; public class C { }");
69+
Path legal = base.resolve("toy-legal");
70+
tb.writeFile(legal.resolve("TOY-LICENSE"), "This is a demo license.");
71+
72+
for (var optionKind : OptionKind.values()) {
73+
for (var indexKind : IndexKind.values()) {
74+
test(base, src, legal, optionKind, indexKind);
75+
}
76+
}
77+
}
78+
79+
void test(Path base, Path src, Path legal, OptionKind optionKind, IndexKind indexKind) throws IOException {
80+
System.out.println("testing " + optionKind + " " + indexKind);
81+
Path out = base.resolve(optionKind + "-" + indexKind).resolve("out");
82+
List<String> args = new ArrayList<>();
83+
args.addAll(List.of(
84+
"-d", out.toString()));
85+
86+
if (indexKind == IndexKind.NO_INDEX) {
87+
args.add("-noindex");
88+
}
89+
90+
args.addAll(List.of(
91+
"-Xdoclint:-missing",
92+
"--source-path", src.toString(),
93+
"p"));
94+
95+
String value = null;
96+
switch (optionKind) {
97+
case UNSET:
98+
value = null;
99+
break;
100+
case DEFAULT:
101+
value = "default";
102+
break;
103+
case NONE:
104+
value = "none";
105+
break;
106+
case DIR:
107+
value= legal.toString();
108+
break;
109+
}
110+
if (value != null) {
111+
args.addAll(List.of("--legal-notices", value));
112+
}
113+
javadoc(args.toArray(new String[0]));
114+
115+
Set<Path> expectFiles = getExpectFiles(optionKind, indexKind, legal);
116+
Set<Path> foundFiles = listFiles(out.resolve("legal"));
117+
118+
checking("Checking legal notice files");
119+
super.out.println("Expected: " + expectFiles);
120+
super.out.println(" Found: " + foundFiles);
121+
if (foundFiles.equals(expectFiles)) {
122+
passed("Found all expected files");
123+
}
124+
}
125+
126+
Set<Path> getExpectFiles(OptionKind optionKind, IndexKind indexKind, Path legal) throws IOException {
127+
switch (optionKind) {
128+
case UNSET:
129+
case DEFAULT:
130+
Path javaHome = Path.of(System.getProperty("java.home"));
131+
Path legal_javadoc = javaHome.resolve("legal").resolve("jdk.javadoc");
132+
return listFiles(legal_javadoc, p -> {
133+
switch (indexKind) {
134+
case INDEX:
135+
return true;
136+
case NO_INDEX:
137+
return !p.getFileName().toString().contains("jquery");
138+
default:
139+
throw new AssertionError("Should not reach");
140+
} } );
141+
142+
/*
143+
return listFiles(legal_javadoc, p -> {
144+
if (indexKind==IndexKind.INDEX) {
145+
return true;
146+
}
147+
else if (indexKind==IndexKind.NO_INDEX) {
148+
return !p.getFileName().toString().contains("jquery");
149+
}
150+
else {
151+
return false;
152+
} } );
153+
*/
154+
155+
/*
156+
return listFiles(legal_javadoc, p ->
157+
(indexKind==IndexKind.INDEX) ? true
158+
: (indexKind==IndexKind.NO_INDEX) ? !p.getFileName().toString().contains("jquery") : false);
159+
*/
160+
161+
case NONE:
162+
return Collections.emptySet();
163+
case DIR:
164+
return listFiles(legal);
165+
}
166+
throw new IllegalStateException();
167+
}
168+
169+
Set<Path> listFiles(Path dir) throws IOException {
170+
return listFiles(dir, p -> true);
171+
}
172+
173+
Set<Path> listFiles(Path dir, Predicate<Path> filter) throws IOException {
174+
if (!Files.exists(dir)) {
175+
return Collections.emptySet();
176+
}
177+
178+
try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
179+
Set<Path> files = new TreeSet<>();
180+
for (Path p : ds) {
181+
if (!Files.isDirectory(p) && filter.test(p)) {
182+
files.add(p.getFileName());
183+
}
184+
}
185+
return files;
186+
}
187+
}
188+
}

0 commit comments

Comments
 (0)