Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/java/src/dev/selenium/tools/javadoc/JavadocJarMaker.java
1865 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
package dev.selenium.tools.javadoc;
19
20
import static java.nio.charset.StandardCharsets.UTF_8;
21
22
import com.github.bazelbuild.rules_jvm_external.zip.StableZipEntry;
23
import java.io.File;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.OutputStream;
27
import java.io.StringWriter;
28
import java.io.UncheckedIOException;
29
import java.io.Writer;
30
import java.nio.file.Files;
31
import java.nio.file.Path;
32
import java.nio.file.Paths;
33
import java.util.ArrayList;
34
import java.util.Comparator;
35
import java.util.HashSet;
36
import java.util.List;
37
import java.util.Locale;
38
import java.util.Set;
39
import java.util.stream.Collectors;
40
import java.util.stream.Stream;
41
import java.util.zip.ZipEntry;
42
import java.util.zip.ZipInputStream;
43
import java.util.zip.ZipOutputStream;
44
import javax.tools.DocumentationTool;
45
import javax.tools.JavaFileObject;
46
import javax.tools.StandardJavaFileManager;
47
import javax.tools.StandardLocation;
48
import javax.tools.ToolProvider;
49
import org.openqa.selenium.io.TemporaryFilesystem;
50
51
public class JavadocJarMaker {
52
53
public static void main(String[] args) throws IOException {
54
Set<Path> sourceJars = new HashSet<>();
55
Path out = null;
56
Set<Path> classpath = new HashSet<>();
57
58
int argCount = args.length;
59
for (int i = 0; i < argCount; i++) {
60
String flag = args[i];
61
String next = args[++i];
62
63
switch (flag) {
64
case "--cp":
65
classpath.add(Paths.get(next));
66
break;
67
68
case "--in":
69
sourceJars.add(Paths.get(next));
70
break;
71
72
case "--out":
73
out = Paths.get(next);
74
break;
75
}
76
}
77
78
if (sourceJars.isEmpty()) {
79
throw new IllegalArgumentException(
80
"At least one input just must be specified via the --in flag");
81
}
82
83
if (out == null) {
84
throw new IllegalArgumentException(
85
"The output jar location must be specified via the --out flag");
86
}
87
88
TemporaryFilesystem tmpFS = TemporaryFilesystem.getDefaultTmpFS();
89
Set<File> tempDirs = new HashSet<>();
90
File dir = tmpFS.createTempDir("javadocs", "");
91
tempDirs.add(dir);
92
93
DocumentationTool tool = ToolProvider.getSystemDocumentationTool();
94
try (StandardJavaFileManager fileManager =
95
tool.getStandardFileManager(null, Locale.getDefault(), UTF_8)) {
96
fileManager.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, List.of(dir));
97
fileManager.setLocation(
98
StandardLocation.CLASS_PATH,
99
classpath.stream().map(Path::toFile).collect(Collectors.toSet()));
100
101
Set<JavaFileObject> sources = new HashSet<>();
102
Set<String> topLevelPackages = new HashSet<>();
103
104
File unpackTo = tmpFS.createTempDir("unpacked-sources", "");
105
tempDirs.add(unpackTo);
106
Set<String> fileNames = new HashSet<>();
107
readSourceFiles(
108
unpackTo.toPath(), fileManager, sourceJars, sources, topLevelPackages, fileNames);
109
110
// True if we're just exporting a set of modules
111
if (sources.isEmpty()) {
112
try (OutputStream os = Files.newOutputStream(out);
113
ZipOutputStream zos = new ZipOutputStream(os)) {
114
// It's enough to just create the thing
115
}
116
return;
117
}
118
119
List<String> options = new ArrayList<>();
120
if (!classpath.isEmpty()) {
121
options.add("-cp");
122
options.add(
123
classpath.stream()
124
.map(String::valueOf)
125
.collect(Collectors.joining(File.pathSeparator)));
126
}
127
options.addAll(
128
List.of(
129
"-html5",
130
"--frames",
131
"-notimestamp",
132
"-use",
133
"-quiet",
134
"-Xdoclint:-missing",
135
"-encoding",
136
"UTF8"));
137
138
File outputTo = tmpFS.createTempDir("output-dir", "");
139
tempDirs.add(outputTo);
140
Path outputToPath = outputTo.toPath();
141
142
options.addAll(List.of("-d", outputTo.getAbsolutePath()));
143
144
sources.forEach(obj -> options.add(obj.getName()));
145
146
Writer writer = new StringWriter();
147
DocumentationTool.DocumentationTask task =
148
tool.getTask(writer, fileManager, null, null, options, sources);
149
Boolean result = task.call();
150
if (result == null || !result) {
151
System.err.println("javadoc " + String.join(" ", options));
152
System.err.println(writer);
153
return;
154
}
155
156
try (OutputStream os = Files.newOutputStream(out);
157
ZipOutputStream zos = new ZipOutputStream(os);
158
Stream<Path> walk = Files.walk(outputToPath)) {
159
walk.sorted(Comparator.naturalOrder())
160
.forEachOrdered(
161
path -> {
162
if (path.equals(outputToPath)) {
163
return;
164
}
165
166
try {
167
if (Files.isDirectory(path)) {
168
String name = outputToPath.relativize(path) + "/";
169
ZipEntry entry = new StableZipEntry(name);
170
zos.putNextEntry(entry);
171
zos.closeEntry();
172
} else {
173
String name = outputToPath.relativize(path).toString();
174
ZipEntry entry = new StableZipEntry(name);
175
zos.putNextEntry(entry);
176
try (InputStream is = Files.newInputStream(path)) {
177
is.transferTo(zos);
178
}
179
zos.closeEntry();
180
}
181
} catch (IOException e) {
182
throw new UncheckedIOException(e);
183
}
184
});
185
}
186
}
187
188
tempDirs.forEach(tmpFS::deleteTempDir);
189
}
190
191
private static void readSourceFiles(
192
Path unpackTo,
193
StandardJavaFileManager fileManager,
194
Set<Path> sourceJars,
195
Set<JavaFileObject> sources,
196
Set<String> topLevelPackages,
197
Set<String> fileNames)
198
throws IOException {
199
200
for (Path jar : sourceJars) {
201
if (!Files.exists(jar)) {
202
continue;
203
}
204
205
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(jar))) {
206
for (ZipEntry entry = zis.getNextEntry(); entry != null; entry = zis.getNextEntry()) {
207
String name = entry.getName();
208
if (!name.endsWith(".java")) {
209
continue;
210
}
211
212
Path target = unpackTo.resolve(name).normalize();
213
if (!target.startsWith(unpackTo)) {
214
throw new IOException("Attempt to write out of working directory");
215
}
216
217
Files.createDirectories(target.getParent());
218
try (OutputStream out = Files.newOutputStream(target)) {
219
zis.transferTo(out);
220
}
221
222
fileManager.getJavaFileObjects(target).forEach(sources::add);
223
224
String[] segments = name.split("/");
225
if (segments.length > 0 && !"META-INF".equals(segments[0])) {
226
topLevelPackages.add(segments[0]);
227
}
228
229
fileNames.add(name);
230
}
231
}
232
}
233
}
234
}
235
236