author | alanb |
Thu, 01 Dec 2016 08:57:53 +0000 | |
changeset 42338 | a60f280f803c |
parent 41916 | eb4aa81c6c5f |
child 42468 | 7a9555a7e080 |
permissions | -rw-r--r-- |
36511 | 1 |
/* |
2 |
* Copyright (c) 2015, 2016, 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. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.tools.jmod; |
|
27 |
||
28 |
import java.io.ByteArrayInputStream; |
|
29 |
import java.io.ByteArrayOutputStream; |
|
30 |
import java.io.File; |
|
31 |
import java.io.IOException; |
|
32 |
import java.io.InputStream; |
|
33 |
import java.io.OutputStream; |
|
34 |
import java.io.PrintStream; |
|
41484
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
35 |
import java.io.PrintWriter; |
36511 | 36 |
import java.io.UncheckedIOException; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
37 |
import java.lang.module.Configuration; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
38 |
import java.lang.module.ModuleReader; |
36511 | 39 |
import java.lang.module.ModuleReference; |
40 |
import java.lang.module.ModuleFinder; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
41 |
import java.lang.module.ModuleDescriptor; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
42 |
import java.lang.module.ModuleDescriptor.Exports; |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
43 |
import java.lang.module.ModuleDescriptor.Opens; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
44 |
import java.lang.module.ModuleDescriptor.Provides; |
36511 | 45 |
import java.lang.module.ModuleDescriptor.Requires; |
46 |
import java.lang.module.ModuleDescriptor.Version; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
47 |
import java.lang.module.ResolutionException; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
48 |
import java.lang.module.ResolvedModule; |
36511 | 49 |
import java.net.URI; |
50 |
import java.nio.file.FileSystems; |
|
41916 | 51 |
import java.nio.file.FileVisitOption; |
36511 | 52 |
import java.nio.file.FileVisitResult; |
53 |
import java.nio.file.Files; |
|
54 |
import java.nio.file.InvalidPathException; |
|
55 |
import java.nio.file.Path; |
|
56 |
import java.nio.file.PathMatcher; |
|
57 |
import java.nio.file.Paths; |
|
58 |
import java.nio.file.SimpleFileVisitor; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
59 |
import java.nio.file.StandardCopyOption; |
36511 | 60 |
import java.nio.file.attribute.BasicFileAttributes; |
61 |
import java.text.MessageFormat; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
62 |
import java.util.ArrayDeque; |
36511 | 63 |
import java.util.ArrayList; |
64 |
import java.util.Collection; |
|
65 |
import java.util.Collections; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
66 |
import java.util.Comparator; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
67 |
import java.util.Deque; |
36511 | 68 |
import java.util.HashMap; |
69 |
import java.util.HashSet; |
|
70 |
import java.util.List; |
|
71 |
import java.util.Locale; |
|
72 |
import java.util.Map; |
|
73 |
import java.util.MissingResourceException; |
|
74 |
import java.util.Optional; |
|
75 |
import java.util.ResourceBundle; |
|
76 |
import java.util.Set; |
|
77 |
import java.util.function.Consumer; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
78 |
import java.util.function.Function; |
36511 | 79 |
import java.util.function.Predicate; |
80 |
import java.util.function.Supplier; |
|
81 |
import java.util.jar.JarEntry; |
|
82 |
import java.util.jar.JarFile; |
|
41352 | 83 |
import java.util.jar.JarOutputStream; |
36511 | 84 |
import java.util.stream.Collectors; |
85 |
import java.util.regex.Pattern; |
|
86 |
import java.util.regex.PatternSyntaxException; |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
87 |
import java.util.stream.Stream; |
36511 | 88 |
import java.util.zip.ZipEntry; |
89 |
import java.util.zip.ZipException; |
|
90 |
import java.util.zip.ZipFile; |
|
91 |
||
41352 | 92 |
import jdk.internal.jmod.JmodFile; |
93 |
import jdk.internal.jmod.JmodFile.Section; |
|
36511 | 94 |
import jdk.internal.joptsimple.BuiltinHelpFormatter; |
95 |
import jdk.internal.joptsimple.NonOptionArgumentSpec; |
|
96 |
import jdk.internal.joptsimple.OptionDescriptor; |
|
97 |
import jdk.internal.joptsimple.OptionException; |
|
98 |
import jdk.internal.joptsimple.OptionParser; |
|
99 |
import jdk.internal.joptsimple.OptionSet; |
|
100 |
import jdk.internal.joptsimple.OptionSpec; |
|
101 |
import jdk.internal.joptsimple.ValueConverter; |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
102 |
import jdk.internal.loader.ResourceHelper; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
103 |
import jdk.internal.misc.JavaLangModuleAccess; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
104 |
import jdk.internal.misc.SharedSecrets; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
105 |
import jdk.internal.module.ModuleHashes; |
36511 | 106 |
import jdk.internal.module.ModuleInfoExtender; |
39042 | 107 |
import jdk.tools.jlink.internal.Utils; |
36511 | 108 |
|
109 |
import static java.util.stream.Collectors.joining; |
|
110 |
||
111 |
/** |
|
112 |
* Implementation for the jmod tool. |
|
113 |
*/ |
|
114 |
public class JmodTask { |
|
115 |
||
116 |
static class CommandException extends RuntimeException { |
|
117 |
private static final long serialVersionUID = 0L; |
|
118 |
boolean showUsage; |
|
119 |
||
120 |
CommandException(String key, Object... args) { |
|
121 |
super(getMessageOrKey(key, args)); |
|
122 |
} |
|
123 |
||
124 |
CommandException showUsage(boolean b) { |
|
125 |
showUsage = b; |
|
126 |
return this; |
|
127 |
} |
|
128 |
||
129 |
private static String getMessageOrKey(String key, Object... args) { |
|
130 |
try { |
|
131 |
return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args); |
|
132 |
} catch (MissingResourceException e) { |
|
133 |
return key; |
|
134 |
} |
|
135 |
} |
|
136 |
} |
|
137 |
||
138 |
private static final String PROGNAME = "jmod"; |
|
139 |
private static final String MODULE_INFO = "module-info.class"; |
|
140 |
||
141 |
private Options options; |
|
41484
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
142 |
private PrintWriter out = new PrintWriter(System.out, true); |
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
143 |
void setLog(PrintWriter out, PrintWriter err) { |
36511 | 144 |
this.out = out; |
145 |
} |
|
146 |
||
147 |
/* Result codes. */ |
|
148 |
static final int EXIT_OK = 0, // Completed with no errors. |
|
149 |
EXIT_ERROR = 1, // Completed but reported errors. |
|
150 |
EXIT_CMDERR = 2, // Bad command-line arguments |
|
151 |
EXIT_SYSERR = 3, // System error or resource exhaustion. |
|
152 |
EXIT_ABNORMAL = 4;// terminated abnormally |
|
153 |
||
154 |
enum Mode { |
|
155 |
CREATE, |
|
156 |
LIST, |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
157 |
DESCRIBE, |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
158 |
HASH |
36511 | 159 |
}; |
160 |
||
161 |
static class Options { |
|
162 |
Mode mode; |
|
163 |
Path jmodFile; |
|
164 |
boolean help; |
|
165 |
boolean version; |
|
166 |
List<Path> classpath; |
|
167 |
List<Path> cmds; |
|
168 |
List<Path> configs; |
|
169 |
List<Path> libs; |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
170 |
List<Path> headerFiles; |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
171 |
List<Path> manPages; |
36511 | 172 |
ModuleFinder moduleFinder; |
173 |
Version moduleVersion; |
|
174 |
String mainClass; |
|
175 |
String osName; |
|
176 |
String osArch; |
|
177 |
String osVersion; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
178 |
Pattern modulesToHash; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
179 |
boolean dryrun; |
36511 | 180 |
List<PathMatcher> excludes; |
181 |
} |
|
182 |
||
183 |
public int run(String[] args) { |
|
184 |
||
185 |
try { |
|
186 |
handleOptions(args); |
|
187 |
if (options == null) { |
|
188 |
showUsageSummary(); |
|
189 |
return EXIT_CMDERR; |
|
190 |
} |
|
191 |
if (options.help) { |
|
192 |
showHelp(); |
|
193 |
return EXIT_OK; |
|
194 |
} |
|
195 |
if (options.version) { |
|
196 |
showVersion(); |
|
197 |
return EXIT_OK; |
|
198 |
} |
|
199 |
||
200 |
boolean ok; |
|
201 |
switch (options.mode) { |
|
202 |
case CREATE: |
|
203 |
ok = create(); |
|
204 |
break; |
|
205 |
case LIST: |
|
206 |
ok = list(); |
|
207 |
break; |
|
208 |
case DESCRIBE: |
|
209 |
ok = describe(); |
|
210 |
break; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
211 |
case HASH: |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
212 |
ok = hashModules(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
213 |
break; |
36511 | 214 |
default: |
215 |
throw new AssertionError("Unknown mode: " + options.mode.name()); |
|
216 |
} |
|
217 |
||
218 |
return ok ? EXIT_OK : EXIT_ERROR; |
|
219 |
} catch (CommandException e) { |
|
220 |
reportError(e.getMessage()); |
|
221 |
if (e.showUsage) |
|
222 |
showUsageSummary(); |
|
223 |
return EXIT_CMDERR; |
|
224 |
} catch (Exception x) { |
|
225 |
reportError(x.getMessage()); |
|
226 |
x.printStackTrace(); |
|
227 |
return EXIT_ABNORMAL; |
|
228 |
} finally { |
|
229 |
out.flush(); |
|
230 |
} |
|
231 |
} |
|
232 |
||
233 |
private boolean list() throws IOException { |
|
234 |
ZipFile zip = null; |
|
235 |
try { |
|
236 |
try { |
|
237 |
zip = new ZipFile(options.jmodFile.toFile()); |
|
238 |
} catch (IOException x) { |
|
239 |
throw new IOException("error opening jmod file", x); |
|
240 |
} |
|
241 |
||
242 |
// Trivially print the archive entries for now, pending a more complete implementation |
|
243 |
zip.stream().forEach(e -> out.println(e.getName())); |
|
244 |
return true; |
|
245 |
} finally { |
|
246 |
if (zip != null) |
|
247 |
zip.close(); |
|
248 |
} |
|
249 |
} |
|
250 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
251 |
private boolean hashModules() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
252 |
return new Hasher(options.moduleFinder).run(); |
36511 | 253 |
} |
254 |
||
255 |
private boolean describe() throws IOException { |
|
41352 | 256 |
try (JmodFile jf = new JmodFile(options.jmodFile)) { |
257 |
try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) { |
|
258 |
ModuleDescriptor md = ModuleDescriptor.read(in); |
|
259 |
printModuleDescriptor(md); |
|
260 |
return true; |
|
261 |
} catch (IOException e) { |
|
262 |
throw new CommandException("err.module.descriptor.not.found"); |
|
36511 | 263 |
} |
264 |
} |
|
265 |
} |
|
266 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
267 |
static <T> String toString(Collection<T> c) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
268 |
if (c.isEmpty()) { return ""; } |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
269 |
return c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT)) |
36511 | 270 |
.collect(joining(" ")); |
271 |
} |
|
272 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
273 |
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
274 |
|
41352 | 275 |
private void printModuleDescriptor(ModuleDescriptor md) |
36511 | 276 |
throws IOException |
277 |
{ |
|
41352 | 278 |
StringBuilder sb = new StringBuilder(); |
279 |
sb.append("\n").append(md.toNameAndVersion()); |
|
36511 | 280 |
|
41352 | 281 |
md.requires().stream() |
282 |
.sorted(Comparator.comparing(Requires::name)) |
|
283 |
.forEach(r -> { |
|
284 |
sb.append("\n requires "); |
|
285 |
if (!r.modifiers().isEmpty()) |
|
286 |
sb.append(toString(r.modifiers())).append(" "); |
|
287 |
sb.append(r.name()); |
|
288 |
}); |
|
36511 | 289 |
|
41352 | 290 |
md.uses().stream().sorted() |
291 |
.forEach(s -> sb.append("\n uses ").append(s)); |
|
36511 | 292 |
|
41352 | 293 |
md.exports().stream() |
294 |
.sorted(Comparator.comparing(Exports::source)) |
|
295 |
.forEach(p -> sb.append("\n exports ").append(p)); |
|
296 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
297 |
md.opens().stream() |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
298 |
.sorted(Comparator.comparing(Opens::source)) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
299 |
.forEach(p -> sb.append("\n opens ").append(p)); |
36511 | 300 |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
301 |
Set<String> concealed = new HashSet<>(md.packages()); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
302 |
md.exports().stream().map(Exports::source).forEach(concealed::remove); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
303 |
md.opens().stream().map(Opens::source).forEach(concealed::remove); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
304 |
concealed.stream().sorted() |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
305 |
.forEach(p -> sb.append("\n contains ").append(p)); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
306 |
|
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
307 |
md.provides().stream() |
41352 | 308 |
.sorted(Comparator.comparing(Provides::service)) |
309 |
.forEach(p -> sb.append("\n provides ").append(p.service()) |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
310 |
.append(" with ") |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
311 |
.append(toString(p.providers()))); |
36511 | 312 |
|
41352 | 313 |
md.mainClass().ifPresent(v -> sb.append("\n main-class " + v)); |
36511 | 314 |
|
41352 | 315 |
md.osName().ifPresent(v -> sb.append("\n operating-system-name " + v)); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
316 |
|
41352 | 317 |
md.osArch().ifPresent(v -> sb.append("\n operating-system-architecture " + v)); |
318 |
||
319 |
md.osVersion().ifPresent(v -> sb.append("\n operating-system-version " + v)); |
|
36511 | 320 |
|
41352 | 321 |
JLMA.hashes(md).ifPresent( |
322 |
hashes -> hashes.names().stream().sorted().forEach( |
|
323 |
mod -> sb.append("\n hashes ").append(mod).append(" ") |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
324 |
.append(hashes.algorithm()).append(" ") |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
325 |
.append(hashes.hashFor(mod)))); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
326 |
|
41352 | 327 |
out.println(sb.toString()); |
36511 | 328 |
} |
329 |
||
330 |
private boolean create() throws IOException { |
|
331 |
JmodFileWriter jmod = new JmodFileWriter(); |
|
332 |
||
333 |
// create jmod with temporary name to avoid it being examined |
|
334 |
// when scanning the module path |
|
335 |
Path target = options.jmodFile; |
|
336 |
Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp"); |
|
337 |
try { |
|
41352 | 338 |
try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) { |
339 |
jmod.write(jos); |
|
36511 | 340 |
} |
341 |
Files.move(tempTarget, target); |
|
342 |
} catch (Exception e) { |
|
343 |
if (Files.exists(tempTarget)) { |
|
344 |
try { |
|
345 |
Files.delete(tempTarget); |
|
346 |
} catch (IOException ioe) { |
|
347 |
e.addSuppressed(ioe); |
|
348 |
} |
|
349 |
} |
|
350 |
throw e; |
|
351 |
} |
|
352 |
return true; |
|
353 |
} |
|
354 |
||
355 |
private class JmodFileWriter { |
|
356 |
final List<Path> cmds = options.cmds; |
|
357 |
final List<Path> libs = options.libs; |
|
358 |
final List<Path> configs = options.configs; |
|
359 |
final List<Path> classpath = options.classpath; |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
360 |
final List<Path> headerFiles = options.headerFiles; |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
361 |
final List<Path> manPages = options.manPages; |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
362 |
|
36511 | 363 |
final Version moduleVersion = options.moduleVersion; |
364 |
final String mainClass = options.mainClass; |
|
365 |
final String osName = options.osName; |
|
366 |
final String osArch = options.osArch; |
|
367 |
final String osVersion = options.osVersion; |
|
368 |
final List<PathMatcher> excludes = options.excludes; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
369 |
final Hasher hasher = hasher(); |
36511 | 370 |
|
371 |
JmodFileWriter() { } |
|
372 |
||
373 |
/** |
|
374 |
* Writes the jmod to the given output stream. |
|
375 |
*/ |
|
41352 | 376 |
void write(JmodOutputStream out) throws IOException { |
377 |
// module-info.class |
|
378 |
writeModuleInfo(out, findPackages(classpath)); |
|
36511 | 379 |
|
41352 | 380 |
// classes |
381 |
processClasses(out, classpath); |
|
36511 | 382 |
|
41352 | 383 |
processSection(out, Section.NATIVE_CMDS, cmds); |
384 |
processSection(out, Section.NATIVE_LIBS, libs); |
|
385 |
processSection(out, Section.CONFIG, configs); |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
386 |
processSection(out, Section.HEADER_FILES, headerFiles); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
387 |
processSection(out, Section.MAN_PAGES, manPages); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
388 |
|
36511 | 389 |
} |
390 |
||
391 |
/** |
|
392 |
* Returns a supplier of an input stream to the module-info.class |
|
393 |
* on the class path of directories and JAR files. |
|
394 |
*/ |
|
395 |
Supplier<InputStream> newModuleInfoSupplier() throws IOException { |
|
396 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
397 |
for (Path e: classpath) { |
|
398 |
if (Files.isDirectory(e)) { |
|
399 |
Path mi = e.resolve(MODULE_INFO); |
|
400 |
if (Files.isRegularFile(mi)) { |
|
401 |
Files.copy(mi, baos); |
|
402 |
break; |
|
403 |
} |
|
404 |
} else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) { |
|
405 |
try (JarFile jf = new JarFile(e.toFile())) { |
|
406 |
ZipEntry entry = jf.getEntry(MODULE_INFO); |
|
407 |
if (entry != null) { |
|
408 |
jf.getInputStream(entry).transferTo(baos); |
|
409 |
break; |
|
410 |
} |
|
411 |
} catch (ZipException x) { |
|
412 |
// Skip. Do nothing. No packages will be added. |
|
413 |
} |
|
414 |
} |
|
415 |
} |
|
416 |
if (baos.size() == 0) { |
|
417 |
return null; |
|
418 |
} else { |
|
419 |
byte[] bytes = baos.toByteArray(); |
|
420 |
return () -> new ByteArrayInputStream(bytes); |
|
421 |
} |
|
422 |
} |
|
423 |
||
424 |
/** |
|
425 |
* Writes the updated module-info.class to the ZIP output stream. |
|
426 |
* |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
427 |
* The updated module-info.class will have a Packages attribute |
36511 | 428 |
* with the set of module-private/non-exported packages. |
429 |
* |
|
430 |
* If --module-version, --main-class, or other options were provided |
|
431 |
* then the corresponding class file attributes are added to the |
|
432 |
* module-info here. |
|
433 |
*/ |
|
41352 | 434 |
void writeModuleInfo(JmodOutputStream out, Set<String> packages) |
36511 | 435 |
throws IOException |
436 |
{ |
|
437 |
Supplier<InputStream> miSupplier = newModuleInfoSupplier(); |
|
438 |
if (miSupplier == null) { |
|
439 |
throw new IOException(MODULE_INFO + " not found"); |
|
440 |
} |
|
441 |
||
442 |
ModuleDescriptor descriptor; |
|
443 |
try (InputStream in = miSupplier.get()) { |
|
444 |
descriptor = ModuleDescriptor.read(in); |
|
445 |
} |
|
446 |
||
447 |
// copy the module-info.class into the jmod with the additional |
|
448 |
// attributes for the version, main class and other meta data |
|
449 |
try (InputStream in = miSupplier.get()) { |
|
450 |
ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in); |
|
451 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
452 |
// Add (or replace) the Packages attribute |
36511 | 453 |
if (packages != null) { |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
454 |
extender.packages(packages); |
36511 | 455 |
} |
456 |
||
457 |
// --main-class |
|
458 |
if (mainClass != null) |
|
459 |
extender.mainClass(mainClass); |
|
460 |
||
461 |
// --os-name, --os-arch, --os-version |
|
462 |
if (osName != null || osArch != null || osVersion != null) |
|
463 |
extender.targetPlatform(osName, osArch, osVersion); |
|
464 |
||
465 |
// --module-version |
|
466 |
if (moduleVersion != null) |
|
467 |
extender.version(moduleVersion); |
|
468 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
469 |
if (hasher != null) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
470 |
ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
471 |
if (moduleHashes != null) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
472 |
extender.hashes(moduleHashes); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
473 |
} else { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
474 |
warning("warn.no.module.hashes", descriptor.name()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
475 |
} |
36511 | 476 |
} |
477 |
||
478 |
// write the (possibly extended or modified) module-info.class |
|
41352 | 479 |
out.writeEntry(extender.toByteArray(), Section.CLASSES, MODULE_INFO); |
36511 | 480 |
} |
481 |
} |
|
482 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
483 |
/* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
484 |
* Hasher resolves a module graph using the --hash-modules PATTERN |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
485 |
* as the roots. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
486 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
487 |
* The jmod file is being created and does not exist in the |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
488 |
* given modulepath. |
36511 | 489 |
*/ |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
490 |
private Hasher hasher() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
491 |
if (options.modulesToHash == null) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
492 |
return null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
493 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
494 |
try { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
495 |
Supplier<InputStream> miSupplier = newModuleInfoSupplier(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
496 |
if (miSupplier == null) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
497 |
throw new IOException(MODULE_INFO + " not found"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
498 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
499 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
500 |
ModuleDescriptor descriptor; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
501 |
try (InputStream in = miSupplier.get()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
502 |
descriptor = ModuleDescriptor.read(in); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
503 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
504 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
505 |
URI uri = options.jmodFile.toUri(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
506 |
ModuleReference mref = new ModuleReference(descriptor, uri, new Supplier<>() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
507 |
@Override |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
508 |
public ModuleReader get() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
509 |
throw new UnsupportedOperationException(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
510 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
511 |
}); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
512 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
513 |
// compose a module finder with the module path and also |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
514 |
// a module finder that can find the jmod file being created |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
515 |
ModuleFinder finder = ModuleFinder.compose(options.moduleFinder, |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
516 |
new ModuleFinder() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
517 |
@Override |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
518 |
public Optional<ModuleReference> find(String name) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
519 |
if (descriptor.name().equals(name)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
520 |
return Optional.of(mref); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
521 |
else return Optional.empty(); |
36511 | 522 |
} |
523 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
524 |
@Override |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
525 |
public Set<ModuleReference> findAll() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
526 |
return Collections.singleton(mref); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
527 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
528 |
}); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
529 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
530 |
return new Hasher(finder); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
531 |
} catch (IOException e) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
532 |
throw new UncheckedIOException(e); |
36511 | 533 |
} |
534 |
} |
|
535 |
||
536 |
/** |
|
537 |
* Returns the set of all packages on the given class path. |
|
538 |
*/ |
|
539 |
Set<String> findPackages(List<Path> classpath) { |
|
540 |
Set<String> packages = new HashSet<>(); |
|
541 |
for (Path path : classpath) { |
|
542 |
if (Files.isDirectory(path)) { |
|
543 |
packages.addAll(findPackages(path)); |
|
544 |
} else if (Files.isRegularFile(path) && path.toString().endsWith(".jar")) { |
|
545 |
try (JarFile jf = new JarFile(path.toString())) { |
|
546 |
packages.addAll(findPackages(jf)); |
|
547 |
} catch (ZipException x) { |
|
548 |
// Skip. Do nothing. No packages will be added. |
|
549 |
} catch (IOException ioe) { |
|
550 |
throw new UncheckedIOException(ioe); |
|
551 |
} |
|
552 |
} |
|
553 |
} |
|
554 |
return packages; |
|
555 |
} |
|
556 |
||
557 |
/** |
|
558 |
* Returns the set of packages in the given directory tree. |
|
559 |
*/ |
|
560 |
Set<String> findPackages(Path dir) { |
|
561 |
try { |
|
562 |
return Files.find(dir, Integer.MAX_VALUE, |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
563 |
((path, attrs) -> attrs.isRegularFile())) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
564 |
.map(dir::relativize) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
565 |
.filter(path -> isResource(path.toString())) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
566 |
.map(path -> toPackageName(path)) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
567 |
.filter(pkg -> pkg.length() > 0) |
36511 | 568 |
.distinct() |
569 |
.collect(Collectors.toSet()); |
|
570 |
} catch (IOException ioe) { |
|
571 |
throw new UncheckedIOException(ioe); |
|
572 |
} |
|
573 |
} |
|
574 |
||
575 |
/** |
|
576 |
* Returns the set of packages in the given JAR file. |
|
577 |
*/ |
|
578 |
Set<String> findPackages(JarFile jf) { |
|
579 |
return jf.stream() |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
580 |
.filter(e -> !e.isDirectory() && isResource(e.getName())) |
36511 | 581 |
.map(e -> toPackageName(e)) |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
582 |
.filter(pkg -> pkg.length() > 0) |
36511 | 583 |
.distinct() |
584 |
.collect(Collectors.toSet()); |
|
585 |
} |
|
586 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
587 |
/** |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
588 |
* Returns true if it's a .class or a resource with an effective |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
589 |
* package name. |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
590 |
*/ |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
591 |
boolean isResource(String name) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
592 |
name = name.replace(File.separatorChar, '/'); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
593 |
return name.endsWith(".class") || !ResourceHelper.isSimpleResource(name); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
594 |
} |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
595 |
|
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
596 |
|
36511 | 597 |
String toPackageName(Path path) { |
598 |
String name = path.toString(); |
|
599 |
int index = name.lastIndexOf(File.separatorChar); |
|
600 |
if (index != -1) |
|
601 |
return name.substring(0, index).replace(File.separatorChar, '.'); |
|
602 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
603 |
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { |
36511 | 604 |
IOException e = new IOException(name + " in the unnamed package"); |
605 |
throw new UncheckedIOException(e); |
|
606 |
} |
|
607 |
return ""; |
|
608 |
} |
|
609 |
||
610 |
String toPackageName(ZipEntry entry) { |
|
611 |
String name = entry.getName(); |
|
612 |
int index = name.lastIndexOf("/"); |
|
613 |
if (index != -1) |
|
614 |
return name.substring(0, index).replace('/', '.'); |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
615 |
|
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
616 |
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
617 |
IOException e = new IOException(name + " in the unnamed package"); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
618 |
throw new UncheckedIOException(e); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
619 |
} |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
620 |
return ""; |
36511 | 621 |
} |
622 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
623 |
void processClasses(JmodOutputStream out, List<Path> classpaths) |
36511 | 624 |
throws IOException |
625 |
{ |
|
626 |
if (classpaths == null) |
|
627 |
return; |
|
628 |
||
629 |
for (Path p : classpaths) { |
|
630 |
if (Files.isDirectory(p)) { |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
631 |
processSection(out, Section.CLASSES, p); |
36511 | 632 |
} else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) { |
633 |
try (JarFile jf = new JarFile(p.toFile())) { |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
634 |
JarEntryConsumer jec = new JarEntryConsumer(out, jf); |
36511 | 635 |
jf.stream().filter(jec).forEach(jec); |
636 |
} |
|
637 |
} |
|
638 |
} |
|
639 |
} |
|
640 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
641 |
void processSection(JmodOutputStream out, Section section, List<Path> paths) |
36511 | 642 |
throws IOException |
643 |
{ |
|
644 |
if (paths == null) |
|
645 |
return; |
|
646 |
||
647 |
for (Path p : paths) |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
648 |
processSection(out, section, p); |
36511 | 649 |
} |
650 |
||
41352 | 651 |
void processSection(JmodOutputStream out, Section section, Path top) |
36511 | 652 |
throws IOException |
653 |
{ |
|
41916 | 654 |
Files.walkFileTree(top, Set.of(FileVisitOption.FOLLOW_LINKS), |
655 |
Integer.MAX_VALUE, new SimpleFileVisitor<Path>() { |
|
36511 | 656 |
@Override |
657 |
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) |
|
658 |
throws IOException |
|
659 |
{ |
|
660 |
Path relPath = top.relativize(file); |
|
39882
2a5433a2eca5
8134779: (jmod) ZipException is thrown if there are duplicate resources
chegar
parents:
39150
diff
changeset
|
661 |
if (relPath.toString().equals(MODULE_INFO) |
41352 | 662 |
&& !Section.CLASSES.equals(section)) |
39882
2a5433a2eca5
8134779: (jmod) ZipException is thrown if there are duplicate resources
chegar
parents:
39150
diff
changeset
|
663 |
warning("warn.ignore.entry", MODULE_INFO, section); |
2a5433a2eca5
8134779: (jmod) ZipException is thrown if there are duplicate resources
chegar
parents:
39150
diff
changeset
|
664 |
|
36511 | 665 |
if (!relPath.toString().equals(MODULE_INFO) |
41352 | 666 |
&& !matches(relPath, excludes)) { |
36511 | 667 |
try (InputStream in = Files.newInputStream(file)) { |
41352 | 668 |
out.writeEntry(in, section, relPath.toString()); |
669 |
} catch (IOException x) { |
|
670 |
if (x.getMessage().contains("duplicate entry")) { |
|
671 |
warning("warn.ignore.duplicate.entry", relPath.toString(), section); |
|
672 |
return FileVisitResult.CONTINUE; |
|
673 |
} |
|
674 |
throw x; |
|
36511 | 675 |
} |
676 |
} |
|
677 |
return FileVisitResult.CONTINUE; |
|
678 |
} |
|
679 |
}); |
|
680 |
} |
|
681 |
||
682 |
boolean matches(Path path, List<PathMatcher> matchers) { |
|
683 |
if (matchers != null) { |
|
684 |
for (PathMatcher pm : matchers) { |
|
685 |
if (pm.matches(path)) |
|
686 |
return true; |
|
687 |
} |
|
688 |
} |
|
689 |
return false; |
|
690 |
} |
|
691 |
||
692 |
class JarEntryConsumer implements Consumer<JarEntry>, Predicate<JarEntry> { |
|
41352 | 693 |
final JmodOutputStream out; |
36511 | 694 |
final JarFile jarfile; |
41352 | 695 |
JarEntryConsumer(JmodOutputStream out, JarFile jarfile) { |
696 |
this.out = out; |
|
36511 | 697 |
this.jarfile = jarfile; |
698 |
} |
|
699 |
@Override |
|
700 |
public void accept(JarEntry je) { |
|
701 |
try (InputStream in = jarfile.getInputStream(je)) { |
|
41352 | 702 |
out.writeEntry(in, Section.CLASSES, je.getName()); |
36511 | 703 |
} catch (IOException e) { |
704 |
throw new UncheckedIOException(e); |
|
705 |
} |
|
706 |
} |
|
707 |
@Override |
|
708 |
public boolean test(JarEntry je) { |
|
709 |
String name = je.getName(); |
|
710 |
// ## no support for excludes. Is it really needed? |
|
711 |
return !name.endsWith(MODULE_INFO) && !je.isDirectory(); |
|
712 |
} |
|
713 |
} |
|
714 |
} |
|
715 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
716 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
717 |
* Compute and record hashes |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
718 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
719 |
private class Hasher { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
720 |
final ModuleFinder moduleFinder; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
721 |
final Map<String, Path> moduleNameToPath; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
722 |
final Set<String> modules; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
723 |
final Configuration configuration; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
724 |
final boolean dryrun = options.dryrun; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
725 |
Hasher(ModuleFinder finder) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
726 |
this.moduleFinder = finder; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
727 |
// Determine the modules that matches the pattern {@code modulesToHash} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
728 |
this.modules = moduleFinder.findAll().stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
729 |
.map(mref -> mref.descriptor().name()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
730 |
.filter(mn -> options.modulesToHash.matcher(mn).find()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
731 |
.collect(Collectors.toSet()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
732 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
733 |
// a map from a module name to Path of the packaged module |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
734 |
this.moduleNameToPath = moduleFinder.findAll().stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
735 |
.map(mref -> mref.descriptor().name()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
736 |
.collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn))); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
737 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
738 |
// get a resolved module graph |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
739 |
Configuration config = null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
740 |
try { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
741 |
config = Configuration.empty() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
742 |
.resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
743 |
} catch (ResolutionException e) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
744 |
warning("warn.module.resolution.fail", e.getMessage()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
745 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
746 |
this.configuration = config; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
747 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
748 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
749 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
750 |
* This method is for jmod hash command. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
751 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
752 |
* Identify the base modules in the module graph, i.e. no outgoing edge |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
753 |
* to any of the modules to be hashed. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
754 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
755 |
* For each base module M, compute the hashes of all modules that depend |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
756 |
* upon M directly or indirectly. Then update M's module-info.class |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
757 |
* to record the hashes. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
758 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
759 |
boolean run() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
760 |
if (configuration == null) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
761 |
return false; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
762 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
763 |
// transposed graph containing the the packaged modules and |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
764 |
// its transitive dependences matching --hash-modules |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
765 |
Map<String, Set<String>> graph = new HashMap<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
766 |
for (String root : modules) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
767 |
Deque<String> deque = new ArrayDeque<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
768 |
deque.add(root); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
769 |
Set<String> visited = new HashSet<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
770 |
while (!deque.isEmpty()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
771 |
String mn = deque.pop(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
772 |
if (!visited.contains(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
773 |
visited.add(mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
774 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
775 |
if (modules.contains(mn)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
776 |
graph.computeIfAbsent(mn, _k -> new HashSet<>()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
777 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
778 |
ResolvedModule resolvedModule = configuration.findModule(mn).get(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
779 |
for (ResolvedModule dm : resolvedModule.reads()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
780 |
String name = dm.name(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
781 |
if (!visited.contains(name)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
782 |
deque.push(name); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
783 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
784 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
785 |
// reverse edge |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
786 |
if (modules.contains(name) && modules.contains(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
787 |
graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
788 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
789 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
790 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
791 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
792 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
793 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
794 |
if (dryrun) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
795 |
out.println("Dry run:"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
796 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
797 |
// each node in a transposed graph is a matching packaged module |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
798 |
// in which the hash of the modules that depend upon it is recorded |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
799 |
graph.entrySet().stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
800 |
.filter(e -> !e.getValue().isEmpty()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
801 |
.forEach(e -> { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
802 |
String mn = e.getKey(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
803 |
Map<String, Path> modulesForHash = e.getValue().stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
804 |
.collect(Collectors.toMap(Function.identity(), |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
805 |
moduleNameToPath::get)); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
806 |
ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
807 |
if (dryrun) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
808 |
out.format("%s%n", mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
809 |
hashes.names().stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
810 |
.sorted() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
811 |
.forEach(name -> out.format(" hashes %s %s %s%n", |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
812 |
name, hashes.algorithm(), hashes.hashFor(name))); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
813 |
} else { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
814 |
try { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
815 |
updateModuleInfo(mn, hashes); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
816 |
} catch (IOException ex) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
817 |
throw new UncheckedIOException(ex); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
818 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
819 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
820 |
}); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
821 |
return true; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
822 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
823 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
824 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
825 |
* Compute hashes of the specified module. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
826 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
827 |
* It records the hashing modules that depend upon the specified |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
828 |
* module directly or indirectly. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
829 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
830 |
ModuleHashes computeHashes(String name) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
831 |
if (configuration == null) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
832 |
return null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
833 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
834 |
// the transposed graph includes all modules in the resolved graph |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
835 |
Map<String, Set<String>> graph = transpose(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
836 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
837 |
// find the modules that transitively depend upon the specified name |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
838 |
Deque<String> deque = new ArrayDeque<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
839 |
deque.add(name); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
840 |
Set<String> mods = visitNodes(graph, deque); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
841 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
842 |
// filter modules matching the pattern specified --hash-modules |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
843 |
// as well as itself as the jmod file is being generated |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
844 |
Map<String, Path> modulesForHash = mods.stream() |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
845 |
.filter(mn -> !mn.equals(name) && modules.contains(mn)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
846 |
.collect(Collectors.toMap(Function.identity(), moduleNameToPath::get)); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
847 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
848 |
if (modulesForHash.isEmpty()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
849 |
return null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
850 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
851 |
return ModuleHashes.generate(modulesForHash, "SHA-256"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
852 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
853 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
854 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
855 |
* Returns all nodes traversed from the given roots. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
856 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
857 |
private Set<String> visitNodes(Map<String, Set<String>> graph, |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
858 |
Deque<String> roots) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
859 |
Set<String> visited = new HashSet<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
860 |
while (!roots.isEmpty()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
861 |
String mn = roots.pop(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
862 |
if (!visited.contains(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
863 |
visited.add(mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
864 |
// the given roots may not be part of the graph |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
865 |
if (graph.containsKey(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
866 |
for (String dm : graph.get(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
867 |
if (!visited.contains(dm)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
868 |
roots.push(dm); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
869 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
870 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
871 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
872 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
873 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
874 |
return visited; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
875 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
876 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
877 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
878 |
* Returns a transposed graph from the resolved module graph. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
879 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
880 |
private Map<String, Set<String>> transpose() { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
881 |
Map<String, Set<String>> transposedGraph = new HashMap<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
882 |
Deque<String> deque = new ArrayDeque<>(modules); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
883 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
884 |
Set<String> visited = new HashSet<>(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
885 |
while (!deque.isEmpty()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
886 |
String mn = deque.pop(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
887 |
if (!visited.contains(mn)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
888 |
visited.add(mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
889 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
890 |
transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
891 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
892 |
ResolvedModule resolvedModule = configuration.findModule(mn).get(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
893 |
for (ResolvedModule dm : resolvedModule.reads()) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
894 |
String name = dm.name(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
895 |
if (!visited.contains(name)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
896 |
deque.push(name); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
897 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
898 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
899 |
// reverse edge |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
900 |
transposedGraph.computeIfAbsent(name, _k -> new HashSet<>()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
901 |
.add(mn); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
902 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
903 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
904 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
905 |
return transposedGraph; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
906 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
907 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
908 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
909 |
* Reads the given input stream of module-info.class and write |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
910 |
* the extended module-info.class with the given ModuleHashes |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
911 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
912 |
* @param in InputStream of module-info.class |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
913 |
* @param out OutputStream to write the extended module-info.class |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
914 |
* @param hashes ModuleHashes |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
915 |
*/ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
916 |
private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
917 |
throws IOException |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
918 |
{ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
919 |
ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
920 |
extender.hashes(hashes); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
921 |
extender.write(out); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
922 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
923 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
924 |
private void updateModuleInfo(String name, ModuleHashes moduleHashes) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
925 |
throws IOException |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
926 |
{ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
927 |
Path target = moduleNameToPath.get(name); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
928 |
Path tempTarget = target.resolveSibling(target.getFileName() + ".tmp"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
929 |
try { |
41352 | 930 |
if (target.getFileName().toString().endsWith(".jmod")) { |
931 |
updateJmodFile(target, tempTarget, moduleHashes); |
|
932 |
} else { |
|
933 |
updateModularJar(target, tempTarget, moduleHashes); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
934 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
935 |
} catch (IOException|RuntimeException e) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
936 |
if (Files.exists(tempTarget)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
937 |
try { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
938 |
Files.delete(tempTarget); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
939 |
} catch (IOException ioe) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
940 |
e.addSuppressed(ioe); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
941 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
942 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
943 |
throw e; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
944 |
} |
41352 | 945 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
946 |
out.println(getMessage("module.hashes.recorded", name)); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
947 |
Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
948 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
949 |
|
41352 | 950 |
private void updateModularJar(Path target, Path tempTarget, |
951 |
ModuleHashes moduleHashes) |
|
952 |
throws IOException |
|
953 |
{ |
|
954 |
try (JarFile jf = new JarFile(target.toFile()); |
|
955 |
OutputStream out = Files.newOutputStream(tempTarget); |
|
956 |
JarOutputStream jos = new JarOutputStream(out)) |
|
957 |
{ |
|
958 |
jf.stream().forEach(e -> { |
|
959 |
try (InputStream in = jf.getInputStream(e)) { |
|
960 |
if (e.getName().equals(MODULE_INFO)) { |
|
961 |
// what about module-info.class in versioned entries? |
|
962 |
ZipEntry ze = new ZipEntry(e.getName()); |
|
963 |
ze.setTime(System.currentTimeMillis()); |
|
964 |
jos.putNextEntry(ze); |
|
965 |
recordHashes(in, jos, moduleHashes); |
|
966 |
jos.closeEntry(); |
|
967 |
} else { |
|
968 |
jos.putNextEntry(e); |
|
969 |
jos.write(in.readAllBytes()); |
|
970 |
jos.closeEntry(); |
|
971 |
} |
|
972 |
} catch (IOException x) { |
|
973 |
throw new UncheckedIOException(x); |
|
974 |
} |
|
975 |
}); |
|
976 |
} |
|
977 |
} |
|
978 |
||
979 |
private void updateJmodFile(Path target, Path tempTarget, |
|
980 |
ModuleHashes moduleHashes) |
|
981 |
throws IOException |
|
982 |
{ |
|
983 |
||
984 |
try (JmodFile jf = new JmodFile(target); |
|
985 |
JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) |
|
986 |
{ |
|
987 |
jf.stream().forEach(e -> { |
|
988 |
try (InputStream in = jf.getInputStream(e.section(), e.name())) { |
|
989 |
if (e.name().equals(MODULE_INFO)) { |
|
990 |
// replace module-info.class |
|
991 |
ModuleInfoExtender extender = |
|
992 |
ModuleInfoExtender.newExtender(in); |
|
993 |
extender.hashes(moduleHashes); |
|
994 |
jos.writeEntry(extender.toByteArray(), e.section(), e.name()); |
|
995 |
} else { |
|
996 |
jos.writeEntry(in, e); |
|
997 |
} |
|
998 |
} catch (IOException x) { |
|
999 |
throw new UncheckedIOException(x); |
|
1000 |
} |
|
1001 |
}); |
|
1002 |
} |
|
1003 |
} |
|
1004 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1005 |
private Path moduleToPath(String name) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1006 |
ModuleReference mref = moduleFinder.find(name).orElseThrow( |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1007 |
() -> new InternalError("Selected module " + name + " not on module path")); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1008 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1009 |
URI uri = mref.location().get(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1010 |
Path path = Paths.get(uri); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1011 |
String fn = path.getFileName().toString(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1012 |
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1013 |
throw new InternalError(path + " is not a modular JAR or jmod file"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1014 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1015 |
return path; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1016 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1017 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1018 |
|
36511 | 1019 |
static class ClassPathConverter implements ValueConverter<Path> { |
1020 |
static final ValueConverter<Path> INSTANCE = new ClassPathConverter(); |
|
1021 |
||
1022 |
private static final Path CWD = Paths.get(""); |
|
1023 |
||
1024 |
@Override |
|
1025 |
public Path convert(String value) { |
|
1026 |
try { |
|
1027 |
Path path = CWD.resolve(value); |
|
1028 |
if (Files.notExists(path)) |
|
1029 |
throw new CommandException("err.path.not.found", path); |
|
1030 |
if (! (Files.isDirectory(path) || |
|
1031 |
(Files.isRegularFile(path) && path.toString().endsWith(".jar")))) |
|
1032 |
throw new CommandException("err.invalid.class.path.entry", path); |
|
1033 |
return path; |
|
1034 |
} catch (InvalidPathException x) { |
|
1035 |
throw new CommandException("err.path.not.valid", value); |
|
1036 |
} |
|
1037 |
} |
|
1038 |
||
1039 |
@Override public Class<Path> valueType() { return Path.class; } |
|
1040 |
||
1041 |
@Override public String valuePattern() { return "path"; } |
|
1042 |
} |
|
1043 |
||
1044 |
static class DirPathConverter implements ValueConverter<Path> { |
|
1045 |
static final ValueConverter<Path> INSTANCE = new DirPathConverter(); |
|
1046 |
||
1047 |
private static final Path CWD = Paths.get(""); |
|
1048 |
||
1049 |
@Override |
|
1050 |
public Path convert(String value) { |
|
1051 |
try { |
|
1052 |
Path path = CWD.resolve(value); |
|
1053 |
if (Files.notExists(path)) |
|
1054 |
throw new CommandException("err.path.not.found", path); |
|
1055 |
if (!Files.isDirectory(path)) |
|
1056 |
throw new CommandException("err.path.not.a.dir", path); |
|
1057 |
return path; |
|
1058 |
} catch (InvalidPathException x) { |
|
1059 |
throw new CommandException("err.path.not.valid", value); |
|
1060 |
} |
|
1061 |
} |
|
1062 |
||
1063 |
@Override public Class<Path> valueType() { return Path.class; } |
|
1064 |
||
1065 |
@Override public String valuePattern() { return "path"; } |
|
1066 |
} |
|
1067 |
||
1068 |
static class ModuleVersionConverter implements ValueConverter<Version> { |
|
1069 |
@Override |
|
1070 |
public Version convert(String value) { |
|
1071 |
try { |
|
1072 |
return Version.parse(value); |
|
1073 |
} catch (IllegalArgumentException x) { |
|
1074 |
throw new CommandException("err.invalid.version", x.getMessage()); |
|
1075 |
} |
|
1076 |
} |
|
1077 |
||
1078 |
@Override public Class<Version> valueType() { return Version.class; } |
|
1079 |
||
1080 |
@Override public String valuePattern() { return "module-version"; } |
|
1081 |
} |
|
1082 |
||
1083 |
static class PatternConverter implements ValueConverter<Pattern> { |
|
1084 |
@Override |
|
1085 |
public Pattern convert(String value) { |
|
1086 |
try { |
|
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1087 |
if (value.startsWith("regex:")) { |
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1088 |
value = value.substring("regex:".length()).trim(); |
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1089 |
} |
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1090 |
|
36511 | 1091 |
return Pattern.compile(value); |
1092 |
} catch (PatternSyntaxException e) { |
|
1093 |
throw new CommandException("err.bad.pattern", value); |
|
1094 |
} |
|
1095 |
} |
|
1096 |
||
1097 |
@Override public Class<Pattern> valueType() { return Pattern.class; } |
|
1098 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1099 |
@Override public String valuePattern() { return "regex-pattern"; } |
36511 | 1100 |
} |
1101 |
||
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1102 |
static class PathMatcherConverter implements ValueConverter<PathMatcher> { |
36511 | 1103 |
@Override |
1104 |
public PathMatcher convert(String pattern) { |
|
1105 |
try { |
|
39042 | 1106 |
return Utils.getPathMatcher(FileSystems.getDefault(), pattern); |
36511 | 1107 |
} catch (PatternSyntaxException e) { |
1108 |
throw new CommandException("err.bad.pattern", pattern); |
|
1109 |
} |
|
1110 |
} |
|
1111 |
||
1112 |
@Override public Class<PathMatcher> valueType() { return PathMatcher.class; } |
|
1113 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1114 |
@Override public String valuePattern() { return "pattern-list"; } |
36511 | 1115 |
} |
1116 |
||
1117 |
/* Support for @<file> in jmod help */ |
|
1118 |
private static final String CMD_FILENAME = "@<filename>"; |
|
1119 |
||
1120 |
/** |
|
1121 |
* This formatter is adding the @filename option and does the required |
|
1122 |
* formatting. |
|
1123 |
*/ |
|
1124 |
private static final class JmodHelpFormatter extends BuiltinHelpFormatter { |
|
1125 |
||
1126 |
private JmodHelpFormatter() { super(80, 2); } |
|
1127 |
||
1128 |
@Override |
|
1129 |
public String format(Map<String, ? extends OptionDescriptor> options) { |
|
1130 |
Map<String, OptionDescriptor> all = new HashMap<>(); |
|
1131 |
all.putAll(options); |
|
1132 |
all.put(CMD_FILENAME, new OptionDescriptor() { |
|
1133 |
@Override |
|
1134 |
public Collection<String> options() { |
|
1135 |
List<String> ret = new ArrayList<>(); |
|
1136 |
ret.add(CMD_FILENAME); |
|
1137 |
return ret; |
|
1138 |
} |
|
1139 |
@Override |
|
1140 |
public String description() { return getMessage("main.opt.cmdfile"); } |
|
1141 |
@Override |
|
1142 |
public List<?> defaultValues() { return Collections.emptyList(); } |
|
1143 |
@Override |
|
1144 |
public boolean isRequired() { return false; } |
|
1145 |
@Override |
|
1146 |
public boolean acceptsArguments() { return false; } |
|
1147 |
@Override |
|
1148 |
public boolean requiresArgument() { return false; } |
|
1149 |
@Override |
|
1150 |
public String argumentDescription() { return null; } |
|
1151 |
@Override |
|
1152 |
public String argumentTypeIndicator() { return null; } |
|
1153 |
@Override |
|
1154 |
public boolean representsNonOptions() { return false; } |
|
1155 |
}); |
|
1156 |
String content = super.format(all); |
|
1157 |
StringBuilder builder = new StringBuilder(); |
|
1158 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1159 |
builder.append(getMessage("main.opt.mode")).append("\n "); |
36511 | 1160 |
builder.append(getMessage("main.opt.mode.create")).append("\n "); |
1161 |
builder.append(getMessage("main.opt.mode.list")).append("\n "); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1162 |
builder.append(getMessage("main.opt.mode.describe")).append("\n "); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1163 |
builder.append(getMessage("main.opt.mode.hash")).append("\n\n"); |
36511 | 1164 |
|
1165 |
String cmdfile = null; |
|
1166 |
String[] lines = content.split("\n"); |
|
1167 |
for (String line : lines) { |
|
1168 |
if (line.startsWith("--@")) { |
|
1169 |
cmdfile = line.replace("--" + CMD_FILENAME, CMD_FILENAME + " "); |
|
1170 |
} else if (line.startsWith("Option") || line.startsWith("------")) { |
|
1171 |
builder.append(" ").append(line).append("\n"); |
|
1172 |
} else if (!line.matches("Non-option arguments")){ |
|
1173 |
builder.append(" ").append(line).append("\n"); |
|
1174 |
} |
|
1175 |
} |
|
1176 |
if (cmdfile != null) { |
|
1177 |
builder.append(" ").append(cmdfile).append("\n"); |
|
1178 |
} |
|
1179 |
return builder.toString(); |
|
1180 |
} |
|
1181 |
} |
|
1182 |
||
40261
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1183 |
private final OptionParser parser = new OptionParser("hp"); |
36511 | 1184 |
|
1185 |
private void handleOptions(String[] args) { |
|
1186 |
parser.formatHelpWith(new JmodHelpFormatter()); |
|
1187 |
||
1188 |
OptionSpec<Path> classPath |
|
1189 |
= parser.accepts("class-path", getMessage("main.opt.class-path")) |
|
1190 |
.withRequiredArg() |
|
1191 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
|
1192 |
.withValuesConvertedBy(ClassPathConverter.INSTANCE); |
|
1193 |
||
1194 |
OptionSpec<Path> cmds |
|
1195 |
= parser.accepts("cmds", getMessage("main.opt.cmds")) |
|
1196 |
.withRequiredArg() |
|
1197 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
|
1198 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1199 |
||
1200 |
OptionSpec<Path> config |
|
1201 |
= parser.accepts("config", getMessage("main.opt.config")) |
|
1202 |
.withRequiredArg() |
|
1203 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
|
1204 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1205 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1206 |
OptionSpec<Void> dryrun |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1207 |
= parser.accepts("dry-run", getMessage("main.opt.dry-run")); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1208 |
|
36511 | 1209 |
OptionSpec<PathMatcher> excludes |
1210 |
= parser.accepts("exclude", getMessage("main.opt.exclude")) |
|
1211 |
.withRequiredArg() |
|
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1212 |
.withValuesConvertedBy(new PathMatcherConverter()); |
36511 | 1213 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1214 |
OptionSpec<Pattern> hashModules |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1215 |
= parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) |
36511 | 1216 |
.withRequiredArg() |
1217 |
.withValuesConvertedBy(new PatternConverter()); |
|
1218 |
||
1219 |
OptionSpec<Void> help |
|
40261
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1220 |
= parser.acceptsAll(Set.of("h", "help"), getMessage("main.opt.help")) |
36511 | 1221 |
.forHelp(); |
1222 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1223 |
OptionSpec<Path> headerFiles |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1224 |
= parser.accepts("header-files", getMessage("main.opt.header-files")) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1225 |
.withRequiredArg() |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1226 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1227 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1228 |
|
36511 | 1229 |
OptionSpec<Path> libs |
1230 |
= parser.accepts("libs", getMessage("main.opt.libs")) |
|
1231 |
.withRequiredArg() |
|
1232 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
|
1233 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1234 |
||
1235 |
OptionSpec<String> mainClass |
|
1236 |
= parser.accepts("main-class", getMessage("main.opt.main-class")) |
|
1237 |
.withRequiredArg() |
|
1238 |
.describedAs(getMessage("main.opt.main-class.arg")); |
|
1239 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1240 |
OptionSpec<Path> manPages |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1241 |
= parser.accepts("man-pages", getMessage("main.opt.man-pages")) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1242 |
.withRequiredArg() |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1243 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1244 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1245 |
|
40261
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1246 |
OptionSpec<Path> modulePath |
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1247 |
= parser.acceptsAll(Set.of("p", "module-path"), |
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1248 |
getMessage("main.opt.module-path")) |
36511 | 1249 |
.withRequiredArg() |
1250 |
.withValuesSeparatedBy(File.pathSeparatorChar) |
|
1251 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1252 |
||
1253 |
OptionSpec<Version> moduleVersion |
|
1254 |
= parser.accepts("module-version", getMessage("main.opt.module-version")) |
|
1255 |
.withRequiredArg() |
|
1256 |
.withValuesConvertedBy(new ModuleVersionConverter()); |
|
1257 |
||
1258 |
OptionSpec<String> osName |
|
1259 |
= parser.accepts("os-name", getMessage("main.opt.os-name")) |
|
1260 |
.withRequiredArg() |
|
1261 |
.describedAs(getMessage("main.opt.os-name.arg")); |
|
1262 |
||
1263 |
OptionSpec<String> osArch |
|
1264 |
= parser.accepts("os-arch", getMessage("main.opt.os-arch")) |
|
1265 |
.withRequiredArg() |
|
1266 |
.describedAs(getMessage("main.opt.os-arch.arg")); |
|
1267 |
||
1268 |
OptionSpec<String> osVersion |
|
1269 |
= parser.accepts("os-version", getMessage("main.opt.os-version")) |
|
1270 |
.withRequiredArg() |
|
1271 |
.describedAs(getMessage("main.opt.os-version.arg")); |
|
1272 |
||
1273 |
OptionSpec<Void> version |
|
1274 |
= parser.accepts("version", getMessage("main.opt.version")); |
|
1275 |
||
1276 |
NonOptionArgumentSpec<String> nonOptions |
|
1277 |
= parser.nonOptions(); |
|
1278 |
||
1279 |
try { |
|
1280 |
OptionSet opts = parser.parse(args); |
|
1281 |
||
1282 |
if (opts.has(help) || opts.has(version)) { |
|
1283 |
options = new Options(); |
|
1284 |
options.help = opts.has(help); |
|
1285 |
options.version = opts.has(version); |
|
1286 |
return; // informational message will be shown |
|
1287 |
} |
|
1288 |
||
1289 |
List<String> words = opts.valuesOf(nonOptions); |
|
1290 |
if (words.isEmpty()) |
|
1291 |
throw new CommandException("err.missing.mode").showUsage(true); |
|
1292 |
String verb = words.get(0); |
|
1293 |
options = new Options(); |
|
1294 |
try { |
|
1295 |
options.mode = Enum.valueOf(Mode.class, verb.toUpperCase()); |
|
1296 |
} catch (IllegalArgumentException e) { |
|
1297 |
throw new CommandException("err.invalid.mode", verb).showUsage(true); |
|
1298 |
} |
|
1299 |
||
1300 |
if (opts.has(classPath)) |
|
1301 |
options.classpath = opts.valuesOf(classPath); |
|
1302 |
if (opts.has(cmds)) |
|
1303 |
options.cmds = opts.valuesOf(cmds); |
|
1304 |
if (opts.has(config)) |
|
1305 |
options.configs = opts.valuesOf(config); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1306 |
if (opts.has(dryrun)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1307 |
options.dryrun = true; |
36511 | 1308 |
if (opts.has(excludes)) |
1309 |
options.excludes = opts.valuesOf(excludes); |
|
1310 |
if (opts.has(libs)) |
|
1311 |
options.libs = opts.valuesOf(libs); |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1312 |
if (opts.has(headerFiles)) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1313 |
options.headerFiles = opts.valuesOf(headerFiles); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1314 |
if (opts.has(manPages)) |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1315 |
options.manPages = opts.valuesOf(manPages); |
36511 | 1316 |
if (opts.has(modulePath)) { |
1317 |
Path[] dirs = opts.valuesOf(modulePath).toArray(new Path[0]); |
|
41817
b90ad1de93ea
8168789: ModuleReader.list and ModuleFinder.of update
alanb
parents:
41561
diff
changeset
|
1318 |
options.moduleFinder = JLMA.newModulePath(Runtime.version(), true, dirs); |
36511 | 1319 |
} |
1320 |
if (opts.has(moduleVersion)) |
|
1321 |
options.moduleVersion = opts.valueOf(moduleVersion); |
|
1322 |
if (opts.has(mainClass)) |
|
1323 |
options.mainClass = opts.valueOf(mainClass); |
|
1324 |
if (opts.has(osName)) |
|
1325 |
options.osName = opts.valueOf(osName); |
|
1326 |
if (opts.has(osArch)) |
|
1327 |
options.osArch = opts.valueOf(osArch); |
|
1328 |
if (opts.has(osVersion)) |
|
1329 |
options.osVersion = opts.valueOf(osVersion); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1330 |
if (opts.has(hashModules)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1331 |
options.modulesToHash = opts.valueOf(hashModules); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1332 |
// if storing hashes then the module path is required |
36511 | 1333 |
if (options.moduleFinder == null) |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1334 |
throw new CommandException("err.modulepath.must.be.specified") |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1335 |
.showUsage(true); |
36511 | 1336 |
} |
1337 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1338 |
if (options.mode.equals(Mode.HASH)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1339 |
if (options.moduleFinder == null || options.modulesToHash == null) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1340 |
throw new CommandException("err.modulepath.must.be.specified") |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1341 |
.showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1342 |
} else { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1343 |
if (words.size() <= 1) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1344 |
throw new CommandException("err.jmod.must.be.specified").showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1345 |
Path path = Paths.get(words.get(1)); |
36511 | 1346 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1347 |
if (options.mode.equals(Mode.CREATE) && Files.exists(path)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1348 |
throw new CommandException("err.file.already.exists", path); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1349 |
else if ((options.mode.equals(Mode.LIST) || |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1350 |
options.mode.equals(Mode.DESCRIBE)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1351 |
&& Files.notExists(path)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1352 |
throw new CommandException("err.jmod.not.found", path); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1353 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1354 |
if (options.dryrun) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1355 |
throw new CommandException("err.invalid.dryrun.option"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1356 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1357 |
options.jmodFile = path; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1358 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1359 |
if (words.size() > 2) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1360 |
throw new CommandException("err.unknown.option", |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1361 |
words.subList(2, words.size())).showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1362 |
} |
36511 | 1363 |
|
1364 |
if (options.mode.equals(Mode.CREATE) && options.classpath == null) |
|
1365 |
throw new CommandException("err.classpath.must.be.specified").showUsage(true); |
|
1366 |
if (options.mainClass != null && !isValidJavaIdentifier(options.mainClass)) |
|
1367 |
throw new CommandException("err.invalid.main-class", options.mainClass); |
|
1368 |
} catch (OptionException e) { |
|
1369 |
throw new CommandException(e.getMessage()); |
|
1370 |
} |
|
1371 |
} |
|
1372 |
||
1373 |
/** |
|
1374 |
* Returns true if, and only if, the given main class is a legal. |
|
1375 |
*/ |
|
1376 |
static boolean isValidJavaIdentifier(String mainClass) { |
|
1377 |
if (mainClass.length() == 0) |
|
1378 |
return false; |
|
1379 |
||
1380 |
if (!Character.isJavaIdentifierStart(mainClass.charAt(0))) |
|
1381 |
return false; |
|
1382 |
||
1383 |
int n = mainClass.length(); |
|
1384 |
for (int i=1; i < n; i++) { |
|
1385 |
char c = mainClass.charAt(i); |
|
1386 |
if (!Character.isJavaIdentifierPart(c) && c != '.') |
|
1387 |
return false; |
|
1388 |
} |
|
1389 |
if (mainClass.charAt(n-1) == '.') |
|
1390 |
return false; |
|
1391 |
||
1392 |
return true; |
|
1393 |
} |
|
1394 |
||
1395 |
private void reportError(String message) { |
|
1396 |
out.println(getMessage("error.prefix") + " " + message); |
|
1397 |
} |
|
1398 |
||
1399 |
private void warning(String key, Object... args) { |
|
1400 |
out.println(getMessage("warn.prefix") + " " + getMessage(key, args)); |
|
1401 |
} |
|
1402 |
||
1403 |
private void showUsageSummary() { |
|
1404 |
out.println(getMessage("main.usage.summary", PROGNAME)); |
|
1405 |
} |
|
1406 |
||
1407 |
private void showHelp() { |
|
1408 |
out.println(getMessage("main.usage", PROGNAME)); |
|
1409 |
try { |
|
1410 |
parser.printHelpOn(out); |
|
1411 |
} catch (IOException x) { |
|
1412 |
throw new AssertionError(x); |
|
1413 |
} |
|
1414 |
} |
|
1415 |
||
1416 |
private void showVersion() { |
|
1417 |
out.println(version()); |
|
1418 |
} |
|
1419 |
||
1420 |
private String version() { |
|
1421 |
return System.getProperty("java.version"); |
|
1422 |
} |
|
1423 |
||
1424 |
private static String getMessage(String key, Object... args) { |
|
1425 |
try { |
|
1426 |
return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args); |
|
1427 |
} catch (MissingResourceException e) { |
|
1428 |
throw new InternalError("Missing message: " + key); |
|
1429 |
} |
|
1430 |
} |
|
1431 |
||
1432 |
private static class ResourceBundleHelper { |
|
1433 |
static final ResourceBundle bundle; |
|
1434 |
||
1435 |
static { |
|
1436 |
Locale locale = Locale.getDefault(); |
|
1437 |
try { |
|
1438 |
bundle = ResourceBundle.getBundle("jdk.tools.jmod.resources.jmod", locale); |
|
1439 |
} catch (MissingResourceException e) { |
|
1440 |
throw new InternalError("Cannot find jmod resource bundle for locale " + locale); |
|
1441 |
} |
|
1442 |
} |
|
1443 |
} |
|
1444 |
} |