author | chegar |
Sat, 03 Mar 2018 20:21:35 +0000 | |
branch | http-client-branch |
changeset 56235 | 6218673d7fa0 |
parent 48543 | 7067fe4e054e |
child 50130 | aefd3c7f5373 |
permissions | -rw-r--r-- |
36511 | 1 |
/* |
48543
7067fe4e054e
8189102: All tools should support -?, -h and --help
goetz
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. |
36511 | 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; |
|
41484
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
34 |
import java.io.PrintWriter; |
36511 | 35 |
import java.io.UncheckedIOException; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
36 |
import java.lang.module.Configuration; |
43712
5dfd0950317c
8173393: Module system implementation refresh (2/2017)
alanb
parents:
43242
diff
changeset
|
37 |
import java.lang.module.FindException; |
37779
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; |
|
62 |
import java.util.ArrayList; |
|
63 |
import java.util.Collection; |
|
64 |
import java.util.Collections; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
65 |
import java.util.Comparator; |
36511 | 66 |
import java.util.HashSet; |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
67 |
import java.util.LinkedHashMap; |
36511 | 68 |
import java.util.List; |
69 |
import java.util.Locale; |
|
70 |
import java.util.Map; |
|
71 |
import java.util.MissingResourceException; |
|
72 |
import java.util.Optional; |
|
73 |
import java.util.ResourceBundle; |
|
74 |
import java.util.Set; |
|
42922
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
75 |
import java.util.TreeSet; |
36511 | 76 |
import java.util.function.Consumer; |
77 |
import java.util.function.Predicate; |
|
78 |
import java.util.function.Supplier; |
|
79 |
import java.util.jar.JarEntry; |
|
80 |
import java.util.jar.JarFile; |
|
41352 | 81 |
import java.util.jar.JarOutputStream; |
36511 | 82 |
import java.util.stream.Collectors; |
83 |
import java.util.regex.Pattern; |
|
84 |
import java.util.regex.PatternSyntaxException; |
|
85 |
import java.util.zip.ZipEntry; |
|
86 |
import java.util.zip.ZipException; |
|
87 |
import java.util.zip.ZipFile; |
|
88 |
||
41352 | 89 |
import jdk.internal.jmod.JmodFile; |
90 |
import jdk.internal.jmod.JmodFile.Section; |
|
36511 | 91 |
import jdk.internal.joptsimple.BuiltinHelpFormatter; |
92 |
import jdk.internal.joptsimple.NonOptionArgumentSpec; |
|
93 |
import jdk.internal.joptsimple.OptionDescriptor; |
|
94 |
import jdk.internal.joptsimple.OptionException; |
|
95 |
import jdk.internal.joptsimple.OptionParser; |
|
96 |
import jdk.internal.joptsimple.OptionSet; |
|
97 |
import jdk.internal.joptsimple.OptionSpec; |
|
98 |
import jdk.internal.joptsimple.ValueConverter; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
99 |
import jdk.internal.module.ModuleHashes; |
43109 | 100 |
import jdk.internal.module.ModuleHashesBuilder; |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
101 |
import jdk.internal.module.ModuleInfo; |
36511 | 102 |
import jdk.internal.module.ModuleInfoExtender; |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
103 |
import jdk.internal.module.ModulePath; |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
104 |
import jdk.internal.module.ModuleResolution; |
44359
c6761862ca0b
8174823: Module system implementation refresh (3/2017)
alanb
parents:
43712
diff
changeset
|
105 |
import jdk.internal.module.ModuleTarget; |
c6761862ca0b
8174823: Module system implementation refresh (3/2017)
alanb
parents:
43712
diff
changeset
|
106 |
import jdk.internal.module.Resources; |
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 |
||
42468 | 141 |
private static final Path CWD = Paths.get(""); |
142 |
||
36511 | 143 |
private Options options; |
41484
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
144 |
private PrintWriter out = new PrintWriter(System.out, true); |
834b7539ada3
8164689: Retrofit jar, jlink, jmod as a ToolProvider
mchung
parents:
41352
diff
changeset
|
145 |
void setLog(PrintWriter out, PrintWriter err) { |
36511 | 146 |
this.out = out; |
147 |
} |
|
148 |
||
149 |
/* Result codes. */ |
|
150 |
static final int EXIT_OK = 0, // Completed with no errors. |
|
151 |
EXIT_ERROR = 1, // Completed but reported errors. |
|
152 |
EXIT_CMDERR = 2, // Bad command-line arguments |
|
153 |
EXIT_SYSERR = 3, // System error or resource exhaustion. |
|
154 |
EXIT_ABNORMAL = 4;// terminated abnormally |
|
155 |
||
156 |
enum Mode { |
|
157 |
CREATE, |
|
42468 | 158 |
EXTRACT, |
36511 | 159 |
LIST, |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
160 |
DESCRIBE, |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
161 |
HASH |
36511 | 162 |
}; |
163 |
||
164 |
static class Options { |
|
165 |
Mode mode; |
|
166 |
Path jmodFile; |
|
167 |
boolean help; |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
168 |
boolean helpExtra; |
36511 | 169 |
boolean version; |
170 |
List<Path> classpath; |
|
171 |
List<Path> cmds; |
|
172 |
List<Path> configs; |
|
173 |
List<Path> libs; |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
174 |
List<Path> headerFiles; |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
175 |
List<Path> manPages; |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
176 |
List<Path> legalNotices;; |
36511 | 177 |
ModuleFinder moduleFinder; |
178 |
Version moduleVersion; |
|
179 |
String mainClass; |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
180 |
String targetPlatform; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
181 |
Pattern modulesToHash; |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
182 |
ModuleResolution moduleResolution; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
183 |
boolean dryrun; |
36511 | 184 |
List<PathMatcher> excludes; |
42468 | 185 |
Path extractDir; |
36511 | 186 |
} |
187 |
||
188 |
public int run(String[] args) { |
|
189 |
||
190 |
try { |
|
191 |
handleOptions(args); |
|
192 |
if (options == null) { |
|
193 |
showUsageSummary(); |
|
194 |
return EXIT_CMDERR; |
|
195 |
} |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
196 |
if (options.help || options.helpExtra) { |
36511 | 197 |
showHelp(); |
198 |
return EXIT_OK; |
|
199 |
} |
|
200 |
if (options.version) { |
|
201 |
showVersion(); |
|
202 |
return EXIT_OK; |
|
203 |
} |
|
204 |
||
205 |
boolean ok; |
|
206 |
switch (options.mode) { |
|
207 |
case CREATE: |
|
208 |
ok = create(); |
|
209 |
break; |
|
42468 | 210 |
case EXTRACT: |
211 |
ok = extract(); |
|
212 |
break; |
|
36511 | 213 |
case LIST: |
214 |
ok = list(); |
|
215 |
break; |
|
216 |
case DESCRIBE: |
|
217 |
ok = describe(); |
|
218 |
break; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
219 |
case HASH: |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
220 |
ok = hashModules(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
221 |
break; |
36511 | 222 |
default: |
223 |
throw new AssertionError("Unknown mode: " + options.mode.name()); |
|
224 |
} |
|
225 |
||
226 |
return ok ? EXIT_OK : EXIT_ERROR; |
|
227 |
} catch (CommandException e) { |
|
228 |
reportError(e.getMessage()); |
|
229 |
if (e.showUsage) |
|
230 |
showUsageSummary(); |
|
231 |
return EXIT_CMDERR; |
|
232 |
} catch (Exception x) { |
|
233 |
reportError(x.getMessage()); |
|
234 |
x.printStackTrace(); |
|
235 |
return EXIT_ABNORMAL; |
|
236 |
} finally { |
|
237 |
out.flush(); |
|
238 |
} |
|
239 |
} |
|
240 |
||
241 |
private boolean list() throws IOException { |
|
242 |
ZipFile zip = null; |
|
243 |
try { |
|
244 |
try { |
|
245 |
zip = new ZipFile(options.jmodFile.toFile()); |
|
246 |
} catch (IOException x) { |
|
247 |
throw new IOException("error opening jmod file", x); |
|
248 |
} |
|
249 |
||
250 |
// Trivially print the archive entries for now, pending a more complete implementation |
|
251 |
zip.stream().forEach(e -> out.println(e.getName())); |
|
252 |
return true; |
|
253 |
} finally { |
|
254 |
if (zip != null) |
|
255 |
zip.close(); |
|
256 |
} |
|
257 |
} |
|
258 |
||
42468 | 259 |
private boolean extract() throws IOException { |
260 |
Path dir = options.extractDir != null ? options.extractDir : CWD; |
|
261 |
try (JmodFile jf = new JmodFile(options.jmodFile)) { |
|
262 |
jf.stream().forEach(e -> { |
|
263 |
try { |
|
264 |
ZipEntry entry = e.zipEntry(); |
|
265 |
String name = entry.getName(); |
|
266 |
int index = name.lastIndexOf("/"); |
|
267 |
if (index != -1) { |
|
268 |
Path p = dir.resolve(name.substring(0, index)); |
|
269 |
if (Files.notExists(p)) |
|
270 |
Files.createDirectories(p); |
|
271 |
} |
|
272 |
||
273 |
try (OutputStream os = Files.newOutputStream(dir.resolve(name))) { |
|
274 |
jf.getInputStream(e).transferTo(os); |
|
275 |
} |
|
276 |
} catch (IOException x) { |
|
277 |
throw new UncheckedIOException(x); |
|
278 |
} |
|
279 |
}); |
|
280 |
||
281 |
return true; |
|
282 |
} |
|
283 |
} |
|
284 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
285 |
private boolean hashModules() { |
43109 | 286 |
if (options.dryrun) { |
287 |
out.println("Dry run:"); |
|
288 |
} |
|
289 |
||
290 |
Hasher hasher = new Hasher(options.moduleFinder); |
|
291 |
hasher.computeHashes().forEach((mn, hashes) -> { |
|
292 |
if (options.dryrun) { |
|
293 |
out.format("%s%n", mn); |
|
294 |
hashes.names().stream() |
|
295 |
.sorted() |
|
296 |
.forEach(name -> out.format(" hashes %s %s %s%n", |
|
297 |
name, hashes.algorithm(), toHex(hashes.hashFor(name)))); |
|
298 |
} else { |
|
299 |
try { |
|
300 |
hasher.updateModuleInfo(mn, hashes); |
|
301 |
} catch (IOException ex) { |
|
302 |
throw new UncheckedIOException(ex); |
|
303 |
} |
|
304 |
} |
|
305 |
}); |
|
306 |
return true; |
|
36511 | 307 |
} |
308 |
||
309 |
private boolean describe() throws IOException { |
|
41352 | 310 |
try (JmodFile jf = new JmodFile(options.jmodFile)) { |
311 |
try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) { |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
312 |
ModuleInfo.Attributes attrs = ModuleInfo.read(in, null); |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
313 |
describeModule(attrs.descriptor(), |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
314 |
attrs.target(), |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
315 |
attrs.recordedHashes()); |
41352 | 316 |
return true; |
317 |
} catch (IOException e) { |
|
318 |
throw new CommandException("err.module.descriptor.not.found"); |
|
36511 | 319 |
} |
320 |
} |
|
321 |
} |
|
322 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
323 |
static <T> String toString(Collection<T> c) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
324 |
if (c.isEmpty()) { return ""; } |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
325 |
return " " + c.stream().map(e -> e.toString().toLowerCase(Locale.ROOT)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
326 |
.sorted().collect(joining(" ")); |
36511 | 327 |
} |
328 |
||
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
329 |
private void describeModule(ModuleDescriptor md, |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
330 |
ModuleTarget target, |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
331 |
ModuleHashes hashes) |
36511 | 332 |
throws IOException |
333 |
{ |
|
41352 | 334 |
StringBuilder sb = new StringBuilder(); |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
335 |
|
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
336 |
sb.append(md.toNameAndVersion()); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
337 |
|
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
338 |
if (md.isOpen()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
339 |
sb.append(" open"); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
340 |
if (md.isAutomatic()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
341 |
sb.append(" automatic"); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
342 |
sb.append("\n"); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
343 |
|
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
344 |
// unqualified exports (sorted by package) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
345 |
md.exports().stream() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
346 |
.sorted(Comparator.comparing(Exports::source)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
347 |
.filter(e -> !e.isQualified()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
348 |
.forEach(e -> sb.append("exports ").append(e.source()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
349 |
.append(toString(e.modifiers())).append("\n")); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
350 |
|
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
351 |
// dependences |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
352 |
md.requires().stream().sorted() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
353 |
.forEach(r -> sb.append("requires ").append(r.name()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
354 |
.append(toString(r.modifiers())).append("\n")); |
36511 | 355 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
356 |
// service use and provides |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
357 |
md.uses().stream().sorted() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
358 |
.forEach(s -> sb.append("uses ").append(s).append("\n")); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
359 |
|
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
360 |
md.provides().stream() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
361 |
.sorted(Comparator.comparing(Provides::service)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
362 |
.forEach(p -> sb.append("provides ").append(p.service()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
363 |
.append(" with") |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
364 |
.append(toString(p.providers())) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
365 |
.append("\n")); |
36511 | 366 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
367 |
// qualified exports |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
368 |
md.exports().stream() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
369 |
.sorted(Comparator.comparing(Exports::source)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
370 |
.filter(Exports::isQualified) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
371 |
.forEach(e -> sb.append("qualified exports ").append(e.source()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
372 |
.append(" to").append(toString(e.targets())) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
373 |
.append("\n")); |
36511 | 374 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
375 |
// open packages |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
376 |
md.opens().stream() |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
377 |
.sorted(Comparator.comparing(Opens::source)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
378 |
.filter(o -> !o.isQualified()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
379 |
.forEach(o -> sb.append("opens ").append(o.source()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
380 |
.append(toString(o.modifiers())) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
381 |
.append("\n")); |
41352 | 382 |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
383 |
md.opens().stream() |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
384 |
.sorted(Comparator.comparing(Opens::source)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
385 |
.filter(Opens::isQualified) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
386 |
.forEach(o -> sb.append("qualified opens ").append(o.source()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
387 |
.append(toString(o.modifiers())) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
388 |
.append(" to").append(toString(o.targets())) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
389 |
.append("\n")); |
36511 | 390 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
391 |
// non-exported/non-open packages |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
392 |
Set<String> concealed = new TreeSet<>(md.packages()); |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
393 |
md.exports().stream().map(Exports::source).forEach(concealed::remove); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
394 |
md.opens().stream().map(Opens::source).forEach(concealed::remove); |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
395 |
concealed.forEach(p -> sb.append("contains ").append(p).append("\n")); |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
396 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
397 |
md.mainClass().ifPresent(v -> sb.append("main-class ").append(v).append("\n")); |
36511 | 398 |
|
44359
c6761862ca0b
8174823: Module system implementation refresh (3/2017)
alanb
parents:
43712
diff
changeset
|
399 |
if (target != null) { |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
400 |
String targetPlatform = target.targetPlatform(); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
401 |
if (!targetPlatform.isEmpty()) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
402 |
sb.append("platform ").append(targetPlatform).append("\n"); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
403 |
} |
36511 | 404 |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
405 |
if (hashes != null) { |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
406 |
hashes.names().stream().sorted().forEach( |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
407 |
mod -> sb.append("hashes ").append(mod).append(" ") |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
408 |
.append(hashes.algorithm()).append(" ") |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
409 |
.append(toHex(hashes.hashFor(mod))) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
410 |
.append("\n")); |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
411 |
} |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
412 |
|
41352 | 413 |
out.println(sb.toString()); |
36511 | 414 |
} |
415 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
416 |
private String toHex(byte[] ba) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
417 |
StringBuilder sb = new StringBuilder(ba.length); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
418 |
for (byte b: ba) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
419 |
sb.append(String.format("%02x", b & 0xff)); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
420 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
421 |
return sb.toString(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
422 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
423 |
|
36511 | 424 |
private boolean create() throws IOException { |
425 |
JmodFileWriter jmod = new JmodFileWriter(); |
|
426 |
||
427 |
// create jmod with temporary name to avoid it being examined |
|
428 |
// when scanning the module path |
|
429 |
Path target = options.jmodFile; |
|
43242 | 430 |
Path tempTarget = jmodTempFilePath(target); |
36511 | 431 |
try { |
41352 | 432 |
try (JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) { |
433 |
jmod.write(jos); |
|
36511 | 434 |
} |
435 |
Files.move(tempTarget, target); |
|
436 |
} catch (Exception e) { |
|
43242 | 437 |
try { |
438 |
Files.deleteIfExists(tempTarget); |
|
439 |
} catch (IOException ioe) { |
|
440 |
e.addSuppressed(ioe); |
|
36511 | 441 |
} |
442 |
throw e; |
|
443 |
} |
|
444 |
return true; |
|
445 |
} |
|
446 |
||
43242 | 447 |
/* |
448 |
* Create a JMOD .tmp file for the given target JMOD file |
|
449 |
*/ |
|
450 |
private static Path jmodTempFilePath(Path target) throws IOException { |
|
451 |
return target.resolveSibling("." + target.getFileName() + ".tmp"); |
|
452 |
} |
|
453 |
||
36511 | 454 |
private class JmodFileWriter { |
455 |
final List<Path> cmds = options.cmds; |
|
456 |
final List<Path> libs = options.libs; |
|
457 |
final List<Path> configs = options.configs; |
|
458 |
final List<Path> classpath = options.classpath; |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
459 |
final List<Path> headerFiles = options.headerFiles; |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
460 |
final List<Path> manPages = options.manPages; |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
461 |
final List<Path> legalNotices = options.legalNotices; |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
462 |
|
36511 | 463 |
final Version moduleVersion = options.moduleVersion; |
464 |
final String mainClass = options.mainClass; |
|
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
465 |
final String targetPlatform = options.targetPlatform; |
36511 | 466 |
final List<PathMatcher> excludes = options.excludes; |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
467 |
final ModuleResolution moduleResolution = options.moduleResolution; |
36511 | 468 |
|
469 |
JmodFileWriter() { } |
|
470 |
||
471 |
/** |
|
472 |
* Writes the jmod to the given output stream. |
|
473 |
*/ |
|
41352 | 474 |
void write(JmodOutputStream out) throws IOException { |
475 |
// module-info.class |
|
476 |
writeModuleInfo(out, findPackages(classpath)); |
|
36511 | 477 |
|
41352 | 478 |
// classes |
479 |
processClasses(out, classpath); |
|
36511 | 480 |
|
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
481 |
processSection(out, Section.CONFIG, configs); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
482 |
processSection(out, Section.HEADER_FILES, headerFiles); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
483 |
processSection(out, Section.LEGAL_NOTICES, legalNotices); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
484 |
processSection(out, Section.MAN_PAGES, manPages); |
41352 | 485 |
processSection(out, Section.NATIVE_CMDS, cmds); |
486 |
processSection(out, Section.NATIVE_LIBS, libs); |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
487 |
|
36511 | 488 |
} |
489 |
||
490 |
/** |
|
491 |
* Returns a supplier of an input stream to the module-info.class |
|
492 |
* on the class path of directories and JAR files. |
|
493 |
*/ |
|
494 |
Supplier<InputStream> newModuleInfoSupplier() throws IOException { |
|
495 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
|
496 |
for (Path e: classpath) { |
|
497 |
if (Files.isDirectory(e)) { |
|
498 |
Path mi = e.resolve(MODULE_INFO); |
|
499 |
if (Files.isRegularFile(mi)) { |
|
500 |
Files.copy(mi, baos); |
|
501 |
break; |
|
502 |
} |
|
503 |
} else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) { |
|
504 |
try (JarFile jf = new JarFile(e.toFile())) { |
|
505 |
ZipEntry entry = jf.getEntry(MODULE_INFO); |
|
506 |
if (entry != null) { |
|
507 |
jf.getInputStream(entry).transferTo(baos); |
|
508 |
break; |
|
509 |
} |
|
510 |
} catch (ZipException x) { |
|
511 |
// Skip. Do nothing. No packages will be added. |
|
512 |
} |
|
513 |
} |
|
514 |
} |
|
515 |
if (baos.size() == 0) { |
|
516 |
return null; |
|
517 |
} else { |
|
518 |
byte[] bytes = baos.toByteArray(); |
|
519 |
return () -> new ByteArrayInputStream(bytes); |
|
520 |
} |
|
521 |
} |
|
522 |
||
523 |
/** |
|
524 |
* Writes the updated module-info.class to the ZIP output stream. |
|
525 |
* |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
526 |
* The updated module-info.class will have a Packages attribute |
36511 | 527 |
* with the set of module-private/non-exported packages. |
528 |
* |
|
529 |
* If --module-version, --main-class, or other options were provided |
|
530 |
* then the corresponding class file attributes are added to the |
|
531 |
* module-info here. |
|
532 |
*/ |
|
41352 | 533 |
void writeModuleInfo(JmodOutputStream out, Set<String> packages) |
36511 | 534 |
throws IOException |
535 |
{ |
|
536 |
Supplier<InputStream> miSupplier = newModuleInfoSupplier(); |
|
537 |
if (miSupplier == null) { |
|
538 |
throw new IOException(MODULE_INFO + " not found"); |
|
539 |
} |
|
540 |
||
541 |
ModuleDescriptor descriptor; |
|
542 |
try (InputStream in = miSupplier.get()) { |
|
543 |
descriptor = ModuleDescriptor.read(in); |
|
544 |
} |
|
545 |
||
546 |
// copy the module-info.class into the jmod with the additional |
|
547 |
// attributes for the version, main class and other meta data |
|
548 |
try (InputStream in = miSupplier.get()) { |
|
549 |
ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in); |
|
550 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
551 |
// Add (or replace) the Packages attribute |
36511 | 552 |
if (packages != null) { |
42922
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
553 |
validatePackages(descriptor, packages); |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
554 |
extender.packages(packages); |
36511 | 555 |
} |
556 |
||
557 |
// --main-class |
|
558 |
if (mainClass != null) |
|
559 |
extender.mainClass(mainClass); |
|
560 |
||
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
561 |
// --target-platform |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
562 |
if (targetPlatform != null) { |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
563 |
extender.targetPlatform(targetPlatform); |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
564 |
} |
36511 | 565 |
|
566 |
// --module-version |
|
567 |
if (moduleVersion != null) |
|
568 |
extender.version(moduleVersion); |
|
569 |
||
43109 | 570 |
// --hash-modules |
571 |
if (options.modulesToHash != null) { |
|
572 |
// To compute hashes, it creates a Configuration to resolve |
|
573 |
// a module graph. The post-resolution check requires |
|
574 |
// the packages in ModuleDescriptor be available for validation. |
|
575 |
ModuleDescriptor md; |
|
576 |
try (InputStream is = miSupplier.get()) { |
|
577 |
md = ModuleDescriptor.read(is, () -> packages); |
|
578 |
} |
|
579 |
||
580 |
ModuleHashes moduleHashes = computeHashes(md); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
581 |
if (moduleHashes != null) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
582 |
extender.hashes(moduleHashes); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
583 |
} else { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
584 |
warning("warn.no.module.hashes", descriptor.name()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
585 |
} |
36511 | 586 |
} |
587 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
588 |
if (moduleResolution != null && moduleResolution.value() != 0) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
589 |
extender.moduleResolution(moduleResolution); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
590 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
591 |
|
36511 | 592 |
// write the (possibly extended or modified) module-info.class |
41352 | 593 |
out.writeEntry(extender.toByteArray(), Section.CLASSES, MODULE_INFO); |
36511 | 594 |
} |
595 |
} |
|
596 |
||
42922
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
597 |
private void validatePackages(ModuleDescriptor descriptor, Set<String> packages) { |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
598 |
Set<String> nonExistPackages = new TreeSet<>(); |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
599 |
descriptor.exports().stream() |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
600 |
.map(Exports::source) |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
601 |
.filter(pn -> !packages.contains(pn)) |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
602 |
.forEach(nonExistPackages::add); |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
603 |
|
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
604 |
descriptor.opens().stream() |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
605 |
.map(Opens::source) |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
606 |
.filter(pn -> !packages.contains(pn)) |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
607 |
.forEach(nonExistPackages::add); |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
608 |
|
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
609 |
if (!nonExistPackages.isEmpty()) { |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
610 |
throw new CommandException("err.missing.export.or.open.packages", |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
611 |
descriptor.name(), nonExistPackages); |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
612 |
} |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
613 |
} |
9111fb672357
8170618: jmod should validate if any exported or open package is missing
sundar
parents:
42704
diff
changeset
|
614 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
615 |
/* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
616 |
* Hasher resolves a module graph using the --hash-modules PATTERN |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
617 |
* as the roots. |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
618 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
619 |
* 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
|
620 |
* given modulepath. |
36511 | 621 |
*/ |
43109 | 622 |
private ModuleHashes computeHashes(ModuleDescriptor descriptor) { |
623 |
String mn = descriptor.name(); |
|
624 |
URI uri = options.jmodFile.toUri(); |
|
625 |
ModuleReference mref = new ModuleReference(descriptor, uri) { |
|
626 |
@Override |
|
627 |
public ModuleReader open() { |
|
628 |
throw new UnsupportedOperationException("opening " + mn); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
629 |
} |
43109 | 630 |
}; |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
631 |
|
43109 | 632 |
// compose a module finder with the module path and also |
633 |
// a module finder that can find the jmod file being created |
|
634 |
ModuleFinder finder = ModuleFinder.compose(options.moduleFinder, |
|
635 |
new ModuleFinder() { |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
636 |
@Override |
43109 | 637 |
public Optional<ModuleReference> find(String name) { |
638 |
if (descriptor.name().equals(name)) |
|
639 |
return Optional.of(mref); |
|
640 |
else return Optional.empty(); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
641 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
642 |
|
43109 | 643 |
@Override |
644 |
public Set<ModuleReference> findAll() { |
|
645 |
return Collections.singleton(mref); |
|
646 |
} |
|
647 |
}); |
|
36511 | 648 |
|
43109 | 649 |
return new Hasher(mn, finder).computeHashes().get(mn); |
36511 | 650 |
} |
651 |
||
652 |
/** |
|
653 |
* Returns the set of all packages on the given class path. |
|
654 |
*/ |
|
655 |
Set<String> findPackages(List<Path> classpath) { |
|
656 |
Set<String> packages = new HashSet<>(); |
|
657 |
for (Path path : classpath) { |
|
658 |
if (Files.isDirectory(path)) { |
|
659 |
packages.addAll(findPackages(path)); |
|
660 |
} else if (Files.isRegularFile(path) && path.toString().endsWith(".jar")) { |
|
661 |
try (JarFile jf = new JarFile(path.toString())) { |
|
662 |
packages.addAll(findPackages(jf)); |
|
663 |
} catch (ZipException x) { |
|
664 |
// Skip. Do nothing. No packages will be added. |
|
665 |
} catch (IOException ioe) { |
|
666 |
throw new UncheckedIOException(ioe); |
|
667 |
} |
|
668 |
} |
|
669 |
} |
|
670 |
return packages; |
|
671 |
} |
|
672 |
||
673 |
/** |
|
674 |
* Returns the set of packages in the given directory tree. |
|
675 |
*/ |
|
676 |
Set<String> findPackages(Path dir) { |
|
677 |
try { |
|
678 |
return Files.find(dir, Integer.MAX_VALUE, |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
679 |
((path, attrs) -> attrs.isRegularFile())) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
680 |
.map(dir::relativize) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
681 |
.filter(path -> isResource(path.toString())) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
682 |
.map(path -> toPackageName(path)) |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
683 |
.filter(pkg -> pkg.length() > 0) |
36511 | 684 |
.distinct() |
685 |
.collect(Collectors.toSet()); |
|
686 |
} catch (IOException ioe) { |
|
687 |
throw new UncheckedIOException(ioe); |
|
688 |
} |
|
689 |
} |
|
690 |
||
691 |
/** |
|
692 |
* Returns the set of packages in the given JAR file. |
|
693 |
*/ |
|
694 |
Set<String> findPackages(JarFile jf) { |
|
695 |
return jf.stream() |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
696 |
.filter(e -> !e.isDirectory() && isResource(e.getName())) |
36511 | 697 |
.map(e -> toPackageName(e)) |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
698 |
.filter(pkg -> pkg.length() > 0) |
36511 | 699 |
.distinct() |
700 |
.collect(Collectors.toSet()); |
|
701 |
} |
|
702 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
703 |
/** |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
704 |
* 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
|
705 |
* package name. |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
706 |
*/ |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
707 |
boolean isResource(String name) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
708 |
name = name.replace(File.separatorChar, '/'); |
44359
c6761862ca0b
8174823: Module system implementation refresh (3/2017)
alanb
parents:
43712
diff
changeset
|
709 |
return name.endsWith(".class") || Resources.canEncapsulate(name); |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
710 |
} |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
711 |
|
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
712 |
|
36511 | 713 |
String toPackageName(Path path) { |
714 |
String name = path.toString(); |
|
715 |
int index = name.lastIndexOf(File.separatorChar); |
|
716 |
if (index != -1) |
|
717 |
return name.substring(0, index).replace(File.separatorChar, '.'); |
|
718 |
||
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
719 |
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { |
36511 | 720 |
IOException e = new IOException(name + " in the unnamed package"); |
721 |
throw new UncheckedIOException(e); |
|
722 |
} |
|
723 |
return ""; |
|
724 |
} |
|
725 |
||
726 |
String toPackageName(ZipEntry entry) { |
|
727 |
String name = entry.getName(); |
|
728 |
int index = name.lastIndexOf("/"); |
|
729 |
if (index != -1) |
|
730 |
return name.substring(0, index).replace('/', '.'); |
|
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
731 |
|
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
732 |
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) { |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
733 |
IOException e = new IOException(name + " in the unnamed package"); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
734 |
throw new UncheckedIOException(e); |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
735 |
} |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
41916
diff
changeset
|
736 |
return ""; |
36511 | 737 |
} |
738 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
739 |
void processClasses(JmodOutputStream out, List<Path> classpaths) |
36511 | 740 |
throws IOException |
741 |
{ |
|
742 |
if (classpaths == null) |
|
743 |
return; |
|
744 |
||
745 |
for (Path p : classpaths) { |
|
746 |
if (Files.isDirectory(p)) { |
|
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
747 |
processSection(out, Section.CLASSES, p); |
36511 | 748 |
} else if (Files.isRegularFile(p) && p.toString().endsWith(".jar")) { |
749 |
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
|
750 |
JarEntryConsumer jec = new JarEntryConsumer(out, jf); |
36511 | 751 |
jf.stream().filter(jec).forEach(jec); |
752 |
} |
|
753 |
} |
|
754 |
} |
|
755 |
} |
|
756 |
||
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
757 |
void processSection(JmodOutputStream out, Section section, List<Path> paths) |
36511 | 758 |
throws IOException |
759 |
{ |
|
760 |
if (paths == null) |
|
761 |
return; |
|
762 |
||
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
763 |
for (Path p : paths) { |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
764 |
processSection(out, section, p); |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
765 |
} |
36511 | 766 |
} |
767 |
||
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
768 |
void processSection(JmodOutputStream out, Section section, Path path) |
36511 | 769 |
throws IOException |
770 |
{ |
|
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
771 |
Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS), |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
772 |
Integer.MAX_VALUE, new SimpleFileVisitor<Path>() { |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
773 |
@Override |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
774 |
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
775 |
throws IOException |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
776 |
{ |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
777 |
Path relPath = path.relativize(file); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
778 |
if (relPath.toString().equals(MODULE_INFO) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
779 |
&& !Section.CLASSES.equals(section)) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
780 |
warning("warn.ignore.entry", MODULE_INFO, section); |
39882
2a5433a2eca5
8134779: (jmod) ZipException is thrown if there are duplicate resources
chegar
parents:
39150
diff
changeset
|
781 |
|
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
782 |
if (!relPath.toString().equals(MODULE_INFO) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
783 |
&& !matches(relPath, excludes)) { |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
784 |
try (InputStream in = Files.newInputStream(file)) { |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
785 |
out.writeEntry(in, section, relPath.toString()); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
786 |
} catch (IOException x) { |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
787 |
if (x.getMessage().contains("duplicate entry")) { |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
788 |
warning("warn.ignore.duplicate.entry", |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
789 |
relPath.toString(), section); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
790 |
return FileVisitResult.CONTINUE; |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
791 |
} |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
792 |
throw x; |
41352 | 793 |
} |
36511 | 794 |
} |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
795 |
return FileVisitResult.CONTINUE; |
36511 | 796 |
} |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
797 |
}); |
36511 | 798 |
} |
799 |
||
800 |
boolean matches(Path path, List<PathMatcher> matchers) { |
|
801 |
if (matchers != null) { |
|
802 |
for (PathMatcher pm : matchers) { |
|
803 |
if (pm.matches(path)) |
|
804 |
return true; |
|
805 |
} |
|
806 |
} |
|
807 |
return false; |
|
808 |
} |
|
809 |
||
810 |
class JarEntryConsumer implements Consumer<JarEntry>, Predicate<JarEntry> { |
|
41352 | 811 |
final JmodOutputStream out; |
36511 | 812 |
final JarFile jarfile; |
41352 | 813 |
JarEntryConsumer(JmodOutputStream out, JarFile jarfile) { |
814 |
this.out = out; |
|
36511 | 815 |
this.jarfile = jarfile; |
816 |
} |
|
817 |
@Override |
|
818 |
public void accept(JarEntry je) { |
|
819 |
try (InputStream in = jarfile.getInputStream(je)) { |
|
41352 | 820 |
out.writeEntry(in, Section.CLASSES, je.getName()); |
36511 | 821 |
} catch (IOException e) { |
822 |
throw new UncheckedIOException(e); |
|
823 |
} |
|
824 |
} |
|
825 |
@Override |
|
826 |
public boolean test(JarEntry je) { |
|
827 |
String name = je.getName(); |
|
828 |
// ## no support for excludes. Is it really needed? |
|
829 |
return !name.endsWith(MODULE_INFO) && !je.isDirectory(); |
|
830 |
} |
|
831 |
} |
|
832 |
} |
|
833 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
834 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
835 |
* Compute and record hashes |
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 |
private class Hasher { |
43109 | 838 |
final Configuration configuration; |
839 |
final ModuleHashesBuilder hashesBuilder; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
840 |
final Set<String> modules; |
43109 | 841 |
final String moduleName; // a specific module to record hashes, if set |
842 |
||
843 |
/** |
|
844 |
* This constructor is for jmod hash command. |
|
845 |
* |
|
846 |
* This Hasher will determine which modules to record hashes, i.e. |
|
847 |
* the module in a subgraph of modules to be hashed and that |
|
848 |
* has no outgoing edges. It will record in each of these modules, |
|
849 |
* say `M`, with the the hashes of modules that depend upon M |
|
850 |
* directly or indirectly matching the specified --hash-modules pattern. |
|
851 |
*/ |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
852 |
Hasher(ModuleFinder finder) { |
43109 | 853 |
this(null, finder); |
854 |
} |
|
855 |
||
856 |
/** |
|
857 |
* Constructs a Hasher to compute hashes. |
|
858 |
* |
|
859 |
* If a module name `M` is specified, it will compute the hashes of |
|
860 |
* modules that depend upon M directly or indirectly matching the |
|
861 |
* specified --hash-modules pattern and record in the ModuleHashes |
|
862 |
* attribute in M's module-info.class. |
|
863 |
* |
|
864 |
* @param name name of the module to record hashes |
|
865 |
* @param finder module finder for the specified --module-path |
|
866 |
*/ |
|
867 |
Hasher(String name, ModuleFinder finder) { |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
868 |
// Determine the modules that matches the pattern {@code modulesToHash} |
43109 | 869 |
Set<String> roots = finder.findAll().stream() |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
870 |
.map(mref -> mref.descriptor().name()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
871 |
.filter(mn -> options.modulesToHash.matcher(mn).find()) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
872 |
.collect(Collectors.toSet()); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
873 |
|
43109 | 874 |
// use system module path unless it creates a JMOD file for |
875 |
// a module that is present in the system image e.g. upgradeable |
|
876 |
// module |
|
877 |
ModuleFinder system; |
|
878 |
if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) { |
|
879 |
system = ModuleFinder.of(); |
|
880 |
} else { |
|
881 |
system = ModuleFinder.ofSystem(); |
|
882 |
} |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
883 |
// get a resolved module graph |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
884 |
Configuration config = null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
885 |
try { |
43712
5dfd0950317c
8173393: Module system implementation refresh (2/2017)
alanb
parents:
43242
diff
changeset
|
886 |
config = Configuration.empty().resolve(system, finder, roots); |
5dfd0950317c
8173393: Module system implementation refresh (2/2017)
alanb
parents:
43242
diff
changeset
|
887 |
} catch (FindException | ResolutionException e) { |
43109 | 888 |
throw new CommandException("err.module.resolution.fail", e.getMessage()); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
889 |
} |
43109 | 890 |
|
891 |
this.moduleName = name; |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
892 |
this.configuration = config; |
43109 | 893 |
|
894 |
// filter modules resolved from the system module finder |
|
895 |
this.modules = config.modules().stream() |
|
896 |
.map(ResolvedModule::name) |
|
897 |
.filter(mn -> roots.contains(mn) && !system.find(mn).isPresent()) |
|
898 |
.collect(Collectors.toSet()); |
|
899 |
||
900 |
this.hashesBuilder = new ModuleHashesBuilder(config, modules); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
901 |
} |
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 |
/** |
43109 | 904 |
* Returns a map of a module M to record hashes of the modules |
905 |
* that depend upon M directly or indirectly. |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
906 |
* |
43109 | 907 |
* For jmod hash command, the returned map contains one entry |
908 |
* for each module M that has no outgoing edges to any of the |
|
909 |
* modules matching the specified --hash-modules pattern. |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
910 |
* |
43109 | 911 |
* Each entry represents a leaf node in a connected subgraph containing |
912 |
* M and other candidate modules from the module graph where M's outgoing |
|
913 |
* edges to any module other than the ones matching the specified |
|
914 |
* --hash-modules pattern are excluded. |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
915 |
*/ |
43109 | 916 |
Map<String, ModuleHashes> computeHashes() { |
917 |
if (hashesBuilder == null) |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
918 |
return null; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
919 |
|
43109 | 920 |
if (moduleName != null) { |
921 |
return hashesBuilder.computeHashes(Set.of(moduleName)); |
|
922 |
} else { |
|
923 |
return hashesBuilder.computeHashes(modules); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
924 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
925 |
} |
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 |
/** |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
928 |
* Reads the given input stream of module-info.class and write |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
929 |
* the extended module-info.class with the given ModuleHashes |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
930 |
* |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
931 |
* @param in InputStream of module-info.class |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
932 |
* @param out OutputStream to write the extended module-info.class |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
933 |
* @param hashes ModuleHashes |
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 |
private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
936 |
throws IOException |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
937 |
{ |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
938 |
ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
939 |
extender.hashes(hashes); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
940 |
extender.write(out); |
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 |
|
43109 | 943 |
void updateModuleInfo(String name, ModuleHashes moduleHashes) |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
944 |
throws IOException |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
945 |
{ |
43109 | 946 |
Path target = moduleToPath(name); |
43242 | 947 |
Path tempTarget = jmodTempFilePath(target); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
948 |
try { |
41352 | 949 |
if (target.getFileName().toString().endsWith(".jmod")) { |
950 |
updateJmodFile(target, tempTarget, moduleHashes); |
|
951 |
} else { |
|
952 |
updateModularJar(target, tempTarget, moduleHashes); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
953 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
954 |
} catch (IOException|RuntimeException e) { |
43242 | 955 |
try { |
956 |
Files.deleteIfExists(tempTarget); |
|
957 |
} catch (IOException ioe) { |
|
958 |
e.addSuppressed(ioe); |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
959 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
960 |
throw e; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
961 |
} |
41352 | 962 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
963 |
out.println(getMessage("module.hashes.recorded", name)); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
964 |
Files.move(tempTarget, target, StandardCopyOption.REPLACE_EXISTING); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
965 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
966 |
|
41352 | 967 |
private void updateModularJar(Path target, Path tempTarget, |
968 |
ModuleHashes moduleHashes) |
|
969 |
throws IOException |
|
970 |
{ |
|
971 |
try (JarFile jf = new JarFile(target.toFile()); |
|
972 |
OutputStream out = Files.newOutputStream(tempTarget); |
|
973 |
JarOutputStream jos = new JarOutputStream(out)) |
|
974 |
{ |
|
975 |
jf.stream().forEach(e -> { |
|
976 |
try (InputStream in = jf.getInputStream(e)) { |
|
977 |
if (e.getName().equals(MODULE_INFO)) { |
|
978 |
// what about module-info.class in versioned entries? |
|
979 |
ZipEntry ze = new ZipEntry(e.getName()); |
|
980 |
ze.setTime(System.currentTimeMillis()); |
|
981 |
jos.putNextEntry(ze); |
|
982 |
recordHashes(in, jos, moduleHashes); |
|
983 |
jos.closeEntry(); |
|
984 |
} else { |
|
985 |
jos.putNextEntry(e); |
|
986 |
jos.write(in.readAllBytes()); |
|
987 |
jos.closeEntry(); |
|
988 |
} |
|
989 |
} catch (IOException x) { |
|
990 |
throw new UncheckedIOException(x); |
|
991 |
} |
|
992 |
}); |
|
993 |
} |
|
994 |
} |
|
995 |
||
996 |
private void updateJmodFile(Path target, Path tempTarget, |
|
997 |
ModuleHashes moduleHashes) |
|
998 |
throws IOException |
|
999 |
{ |
|
1000 |
||
1001 |
try (JmodFile jf = new JmodFile(target); |
|
1002 |
JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget)) |
|
1003 |
{ |
|
1004 |
jf.stream().forEach(e -> { |
|
1005 |
try (InputStream in = jf.getInputStream(e.section(), e.name())) { |
|
1006 |
if (e.name().equals(MODULE_INFO)) { |
|
1007 |
// replace module-info.class |
|
1008 |
ModuleInfoExtender extender = |
|
1009 |
ModuleInfoExtender.newExtender(in); |
|
1010 |
extender.hashes(moduleHashes); |
|
1011 |
jos.writeEntry(extender.toByteArray(), e.section(), e.name()); |
|
1012 |
} else { |
|
1013 |
jos.writeEntry(in, e); |
|
1014 |
} |
|
1015 |
} catch (IOException x) { |
|
1016 |
throw new UncheckedIOException(x); |
|
1017 |
} |
|
1018 |
}); |
|
1019 |
} |
|
1020 |
} |
|
1021 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1022 |
private Path moduleToPath(String name) { |
43109 | 1023 |
ResolvedModule rm = configuration.findModule(name).orElseThrow( |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1024 |
() -> new InternalError("Selected module " + name + " not on module path")); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1025 |
|
43109 | 1026 |
URI uri = rm.reference().location().get(); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1027 |
Path path = Paths.get(uri); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1028 |
String fn = path.getFileName().toString(); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1029 |
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1030 |
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
|
1031 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1032 |
return path; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1033 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1034 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1035 |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1036 |
/** |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1037 |
* An abstract converter that given a string representing a list of paths, |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1038 |
* separated by the File.pathSeparator, returns a List of java.nio.Path's. |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1039 |
* Specific subclasses should do whatever validation is required on the |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1040 |
* individual path elements, if any. |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1041 |
*/ |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1042 |
static abstract class AbstractPathConverter implements ValueConverter<List<Path>> { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1043 |
@Override |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1044 |
public List<Path> convert(String value) { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1045 |
List<Path> paths = new ArrayList<>(); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1046 |
String[] pathElements = value.split(File.pathSeparator); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1047 |
for (String pathElement : pathElements) { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1048 |
paths.add(toPath(pathElement)); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1049 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1050 |
return paths; |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1051 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1052 |
|
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1053 |
@SuppressWarnings("unchecked") |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1054 |
@Override |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1055 |
public Class<List<Path>> valueType() { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1056 |
return (Class<List<Path>>)(Object)List.class; |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1057 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1058 |
|
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1059 |
@Override public String valuePattern() { return "path"; } |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1060 |
|
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1061 |
abstract Path toPath(String path); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1062 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1063 |
|
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1064 |
static class ClassPathConverter extends AbstractPathConverter { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1065 |
static final ValueConverter<List<Path>> INSTANCE = new ClassPathConverter(); |
36511 | 1066 |
|
1067 |
@Override |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1068 |
public Path toPath(String value) { |
36511 | 1069 |
try { |
1070 |
Path path = CWD.resolve(value); |
|
1071 |
if (Files.notExists(path)) |
|
1072 |
throw new CommandException("err.path.not.found", path); |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1073 |
if (!(Files.isDirectory(path) || |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1074 |
(Files.isRegularFile(path) && path.toString().endsWith(".jar")))) |
36511 | 1075 |
throw new CommandException("err.invalid.class.path.entry", path); |
1076 |
return path; |
|
1077 |
} catch (InvalidPathException x) { |
|
1078 |
throw new CommandException("err.path.not.valid", value); |
|
1079 |
} |
|
1080 |
} |
|
1081 |
} |
|
1082 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1083 |
static class DirPathConverter extends AbstractPathConverter { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1084 |
static final ValueConverter<List<Path>> INSTANCE = new DirPathConverter(); |
36511 | 1085 |
|
1086 |
@Override |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1087 |
public Path toPath(String value) { |
36511 | 1088 |
try { |
1089 |
Path path = CWD.resolve(value); |
|
1090 |
if (Files.notExists(path)) |
|
1091 |
throw new CommandException("err.path.not.found", path); |
|
1092 |
if (!Files.isDirectory(path)) |
|
1093 |
throw new CommandException("err.path.not.a.dir", path); |
|
1094 |
return path; |
|
1095 |
} catch (InvalidPathException x) { |
|
1096 |
throw new CommandException("err.path.not.valid", value); |
|
1097 |
} |
|
1098 |
} |
|
1099 |
} |
|
1100 |
||
42468 | 1101 |
static class ExtractDirPathConverter implements ValueConverter<Path> { |
1102 |
||
1103 |
@Override |
|
1104 |
public Path convert(String value) { |
|
1105 |
try { |
|
1106 |
Path path = CWD.resolve(value); |
|
1107 |
if (Files.exists(path)) { |
|
1108 |
if (!Files.isDirectory(path)) |
|
1109 |
throw new CommandException("err.cannot.create.dir", path); |
|
1110 |
} |
|
1111 |
return path; |
|
1112 |
} catch (InvalidPathException x) { |
|
1113 |
throw new CommandException("err.path.not.valid", value); |
|
1114 |
} |
|
1115 |
} |
|
1116 |
||
1117 |
@Override public Class<Path> valueType() { return Path.class; } |
|
1118 |
||
1119 |
@Override public String valuePattern() { return "path"; } |
|
1120 |
} |
|
1121 |
||
36511 | 1122 |
static class ModuleVersionConverter implements ValueConverter<Version> { |
1123 |
@Override |
|
1124 |
public Version convert(String value) { |
|
1125 |
try { |
|
1126 |
return Version.parse(value); |
|
1127 |
} catch (IllegalArgumentException x) { |
|
1128 |
throw new CommandException("err.invalid.version", x.getMessage()); |
|
1129 |
} |
|
1130 |
} |
|
1131 |
||
1132 |
@Override public Class<Version> valueType() { return Version.class; } |
|
1133 |
||
1134 |
@Override public String valuePattern() { return "module-version"; } |
|
1135 |
} |
|
1136 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1137 |
static class WarnIfResolvedReasonConverter |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1138 |
implements ValueConverter<ModuleResolution> |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1139 |
{ |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1140 |
@Override |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1141 |
public ModuleResolution convert(String value) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1142 |
if (value.equals("deprecated")) |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1143 |
return ModuleResolution.empty().withDeprecated(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1144 |
else if (value.equals("deprecated-for-removal")) |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1145 |
return ModuleResolution.empty().withDeprecatedForRemoval(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1146 |
else if (value.equals("incubating")) |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1147 |
return ModuleResolution.empty().withIncubating(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1148 |
else |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1149 |
throw new CommandException("err.bad.WarnIfResolvedReason", value); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1150 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1151 |
|
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1152 |
@Override public Class<ModuleResolution> valueType() { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1153 |
return ModuleResolution.class; |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1154 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1155 |
|
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1156 |
@Override public String valuePattern() { return "reason"; } |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1157 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1158 |
|
36511 | 1159 |
static class PatternConverter implements ValueConverter<Pattern> { |
1160 |
@Override |
|
1161 |
public Pattern convert(String value) { |
|
1162 |
try { |
|
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1163 |
if (value.startsWith("regex:")) { |
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1164 |
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
|
1165 |
} |
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1166 |
|
36511 | 1167 |
return Pattern.compile(value); |
1168 |
} catch (PatternSyntaxException e) { |
|
1169 |
throw new CommandException("err.bad.pattern", value); |
|
1170 |
} |
|
1171 |
} |
|
1172 |
||
1173 |
@Override public Class<Pattern> valueType() { return Pattern.class; } |
|
1174 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1175 |
@Override public String valuePattern() { return "regex-pattern"; } |
36511 | 1176 |
} |
1177 |
||
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1178 |
static class PathMatcherConverter implements ValueConverter<PathMatcher> { |
36511 | 1179 |
@Override |
1180 |
public PathMatcher convert(String pattern) { |
|
1181 |
try { |
|
39042 | 1182 |
return Utils.getPathMatcher(FileSystems.getDefault(), pattern); |
36511 | 1183 |
} catch (PatternSyntaxException e) { |
1184 |
throw new CommandException("err.bad.pattern", pattern); |
|
1185 |
} |
|
1186 |
} |
|
1187 |
||
1188 |
@Override public Class<PathMatcher> valueType() { return PathMatcher.class; } |
|
1189 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1190 |
@Override public String valuePattern() { return "pattern-list"; } |
36511 | 1191 |
} |
1192 |
||
1193 |
/* Support for @<file> in jmod help */ |
|
1194 |
private static final String CMD_FILENAME = "@<filename>"; |
|
1195 |
||
1196 |
/** |
|
1197 |
* This formatter is adding the @filename option and does the required |
|
1198 |
* formatting. |
|
1199 |
*/ |
|
1200 |
private static final class JmodHelpFormatter extends BuiltinHelpFormatter { |
|
1201 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1202 |
private final Options opts; |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1203 |
|
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1204 |
private JmodHelpFormatter(Options opts) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1205 |
super(80, 2); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1206 |
this.opts = opts; |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1207 |
} |
36511 | 1208 |
|
1209 |
@Override |
|
1210 |
public String format(Map<String, ? extends OptionDescriptor> options) { |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1211 |
Map<String, OptionDescriptor> all = new LinkedHashMap<>(); |
36511 | 1212 |
all.putAll(options); |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1213 |
|
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1214 |
// extra options |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1215 |
if (!opts.helpExtra) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1216 |
all.remove("do-not-resolve-by-default"); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1217 |
all.remove("warn-if-resolved"); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1218 |
} |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1219 |
|
36511 | 1220 |
all.put(CMD_FILENAME, new OptionDescriptor() { |
1221 |
@Override |
|
1222 |
public Collection<String> options() { |
|
1223 |
List<String> ret = new ArrayList<>(); |
|
1224 |
ret.add(CMD_FILENAME); |
|
1225 |
return ret; |
|
1226 |
} |
|
1227 |
@Override |
|
1228 |
public String description() { return getMessage("main.opt.cmdfile"); } |
|
1229 |
@Override |
|
1230 |
public List<?> defaultValues() { return Collections.emptyList(); } |
|
1231 |
@Override |
|
1232 |
public boolean isRequired() { return false; } |
|
1233 |
@Override |
|
1234 |
public boolean acceptsArguments() { return false; } |
|
1235 |
@Override |
|
1236 |
public boolean requiresArgument() { return false; } |
|
1237 |
@Override |
|
1238 |
public String argumentDescription() { return null; } |
|
1239 |
@Override |
|
1240 |
public String argumentTypeIndicator() { return null; } |
|
1241 |
@Override |
|
1242 |
public boolean representsNonOptions() { return false; } |
|
1243 |
}); |
|
1244 |
String content = super.format(all); |
|
1245 |
StringBuilder builder = new StringBuilder(); |
|
1246 |
||
39150
cb99396625b4
8159172: Update usage of jlink/jimage/jmod to show option patterns
jlaskey
parents:
39042
diff
changeset
|
1247 |
builder.append(getMessage("main.opt.mode")).append("\n "); |
36511 | 1248 |
builder.append(getMessage("main.opt.mode.create")).append("\n "); |
42468 | 1249 |
builder.append(getMessage("main.opt.mode.extract")).append("\n "); |
36511 | 1250 |
builder.append(getMessage("main.opt.mode.list")).append("\n "); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1251 |
builder.append(getMessage("main.opt.mode.describe")).append("\n "); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1252 |
builder.append(getMessage("main.opt.mode.hash")).append("\n\n"); |
36511 | 1253 |
|
1254 |
String cmdfile = null; |
|
1255 |
String[] lines = content.split("\n"); |
|
1256 |
for (String line : lines) { |
|
1257 |
if (line.startsWith("--@")) { |
|
1258 |
cmdfile = line.replace("--" + CMD_FILENAME, CMD_FILENAME + " "); |
|
1259 |
} else if (line.startsWith("Option") || line.startsWith("------")) { |
|
1260 |
builder.append(" ").append(line).append("\n"); |
|
1261 |
} else if (!line.matches("Non-option arguments")){ |
|
1262 |
builder.append(" ").append(line).append("\n"); |
|
1263 |
} |
|
1264 |
} |
|
1265 |
if (cmdfile != null) { |
|
1266 |
builder.append(" ").append(cmdfile).append("\n"); |
|
1267 |
} |
|
1268 |
return builder.toString(); |
|
1269 |
} |
|
1270 |
} |
|
1271 |
||
40261
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1272 |
private final OptionParser parser = new OptionParser("hp"); |
36511 | 1273 |
|
1274 |
private void handleOptions(String[] args) { |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1275 |
options = new Options(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1276 |
parser.formatHelpWith(new JmodHelpFormatter(options)); |
36511 | 1277 |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1278 |
OptionSpec<List<Path>> classPath |
36511 | 1279 |
= parser.accepts("class-path", getMessage("main.opt.class-path")) |
1280 |
.withRequiredArg() |
|
1281 |
.withValuesConvertedBy(ClassPathConverter.INSTANCE); |
|
1282 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1283 |
OptionSpec<List<Path>> cmds |
36511 | 1284 |
= parser.accepts("cmds", getMessage("main.opt.cmds")) |
1285 |
.withRequiredArg() |
|
1286 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1287 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1288 |
OptionSpec<List<Path>> config |
36511 | 1289 |
= parser.accepts("config", getMessage("main.opt.config")) |
1290 |
.withRequiredArg() |
|
1291 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1292 |
||
42468 | 1293 |
OptionSpec<Path> dir |
1294 |
= parser.accepts("dir", getMessage("main.opt.extractDir")) |
|
1295 |
.withRequiredArg() |
|
1296 |
.withValuesConvertedBy(new ExtractDirPathConverter()); |
|
1297 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1298 |
OptionSpec<Void> dryrun |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1299 |
= parser.accepts("dry-run", getMessage("main.opt.dry-run")); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1300 |
|
36511 | 1301 |
OptionSpec<PathMatcher> excludes |
1302 |
= parser.accepts("exclude", getMessage("main.opt.exclude")) |
|
1303 |
.withRequiredArg() |
|
38871
ec08bf1979d4
8158402: jlink: should use regex for all pattern operations (--order-resources or --exclude-resources)
jlaskey
parents:
37779
diff
changeset
|
1304 |
.withValuesConvertedBy(new PathMatcherConverter()); |
36511 | 1305 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1306 |
OptionSpec<Pattern> hashModules |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1307 |
= parser.accepts("hash-modules", getMessage("main.opt.hash-modules")) |
36511 | 1308 |
.withRequiredArg() |
1309 |
.withValuesConvertedBy(new PatternConverter()); |
|
1310 |
||
1311 |
OptionSpec<Void> help |
|
48543
7067fe4e054e
8189102: All tools should support -?, -h and --help
goetz
parents:
47216
diff
changeset
|
1312 |
= parser.acceptsAll(Set.of("h", "help", "?"), getMessage("main.opt.help")) |
36511 | 1313 |
.forHelp(); |
1314 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1315 |
OptionSpec<Void> helpExtra |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1316 |
= parser.accepts("help-extra", getMessage("main.opt.help-extra")); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1317 |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1318 |
OptionSpec<List<Path>> headerFiles |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1319 |
= parser.accepts("header-files", getMessage("main.opt.header-files")) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1320 |
.withRequiredArg() |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1321 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1322 |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1323 |
OptionSpec<List<Path>> libs |
36511 | 1324 |
= parser.accepts("libs", getMessage("main.opt.libs")) |
1325 |
.withRequiredArg() |
|
1326 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1327 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1328 |
OptionSpec<List<Path>> legalNotices |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1329 |
= parser.accepts("legal-notices", getMessage("main.opt.legal-notices")) |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1330 |
.withRequiredArg() |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1331 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1332 |
|
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1333 |
|
36511 | 1334 |
OptionSpec<String> mainClass |
1335 |
= parser.accepts("main-class", getMessage("main.opt.main-class")) |
|
1336 |
.withRequiredArg() |
|
1337 |
.describedAs(getMessage("main.opt.main-class.arg")); |
|
1338 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1339 |
OptionSpec<List<Path>> manPages |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1340 |
= parser.accepts("man-pages", getMessage("main.opt.man-pages")) |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1341 |
.withRequiredArg() |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1342 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1343 |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1344 |
OptionSpec<List<Path>> modulePath |
40261
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1345 |
= parser.acceptsAll(Set.of("p", "module-path"), |
86a49ba76f52
8136930: Simplify use of module-system options by custom launchers
mchung
parents:
39882
diff
changeset
|
1346 |
getMessage("main.opt.module-path")) |
36511 | 1347 |
.withRequiredArg() |
1348 |
.withValuesConvertedBy(DirPathConverter.INSTANCE); |
|
1349 |
||
1350 |
OptionSpec<Version> moduleVersion |
|
1351 |
= parser.accepts("module-version", getMessage("main.opt.module-version")) |
|
1352 |
.withRequiredArg() |
|
1353 |
.withValuesConvertedBy(new ModuleVersionConverter()); |
|
1354 |
||
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
1355 |
OptionSpec<String> targetPlatform |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
1356 |
= parser.accepts("target-platform", getMessage("main.opt.target-platform")) |
36511 | 1357 |
.withRequiredArg() |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
1358 |
.describedAs(getMessage("main.opt.target-platform.arg")); |
36511 | 1359 |
|
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1360 |
OptionSpec<Void> doNotResolveByDefault |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1361 |
= parser.accepts("do-not-resolve-by-default", |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1362 |
getMessage("main.opt.do-not-resolve-by-default")); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1363 |
|
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1364 |
OptionSpec<ModuleResolution> warnIfResolved |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1365 |
= parser.accepts("warn-if-resolved", getMessage("main.opt.warn-if-resolved")) |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1366 |
.withRequiredArg() |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1367 |
.withValuesConvertedBy(new WarnIfResolvedReasonConverter()); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1368 |
|
36511 | 1369 |
OptionSpec<Void> version |
1370 |
= parser.accepts("version", getMessage("main.opt.version")); |
|
1371 |
||
1372 |
NonOptionArgumentSpec<String> nonOptions |
|
1373 |
= parser.nonOptions(); |
|
1374 |
||
1375 |
try { |
|
1376 |
OptionSet opts = parser.parse(args); |
|
1377 |
||
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1378 |
if (opts.has(help) || opts.has(helpExtra) || opts.has(version)) { |
36511 | 1379 |
options.help = opts.has(help); |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1380 |
options.helpExtra = opts.has(helpExtra); |
36511 | 1381 |
options.version = opts.has(version); |
1382 |
return; // informational message will be shown |
|
1383 |
} |
|
1384 |
||
1385 |
List<String> words = opts.valuesOf(nonOptions); |
|
1386 |
if (words.isEmpty()) |
|
1387 |
throw new CommandException("err.missing.mode").showUsage(true); |
|
1388 |
String verb = words.get(0); |
|
1389 |
try { |
|
1390 |
options.mode = Enum.valueOf(Mode.class, verb.toUpperCase()); |
|
1391 |
} catch (IllegalArgumentException e) { |
|
1392 |
throw new CommandException("err.invalid.mode", verb).showUsage(true); |
|
1393 |
} |
|
1394 |
||
1395 |
if (opts.has(classPath)) |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1396 |
options.classpath = getLastElement(opts.valuesOf(classPath)); |
36511 | 1397 |
if (opts.has(cmds)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1398 |
options.cmds = getLastElement(opts.valuesOf(cmds)); |
36511 | 1399 |
if (opts.has(config)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1400 |
options.configs = getLastElement(opts.valuesOf(config)); |
42468 | 1401 |
if (opts.has(dir)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1402 |
options.extractDir = getLastElement(opts.valuesOf(dir)); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1403 |
if (opts.has(dryrun)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1404 |
options.dryrun = true; |
36511 | 1405 |
if (opts.has(excludes)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1406 |
options.excludes = opts.valuesOf(excludes); // excludes is repeatable |
36511 | 1407 |
if (opts.has(libs)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1408 |
options.libs = getLastElement(opts.valuesOf(libs)); |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1409 |
if (opts.has(headerFiles)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1410 |
options.headerFiles = getLastElement(opts.valuesOf(headerFiles)); |
41561
0c6942d13f2e
8167558: Add new JMOD section for header files and man pages
mchung
parents:
41484
diff
changeset
|
1411 |
if (opts.has(manPages)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1412 |
options.manPages = getLastElement(opts.valuesOf(manPages)); |
42670
d833113eb7d7
8169925: Organize licenses by module in source, JMOD file, and run-time image
mchung
parents:
42468
diff
changeset
|
1413 |
if (opts.has(legalNotices)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1414 |
options.legalNotices = getLastElement(opts.valuesOf(legalNotices)); |
36511 | 1415 |
if (opts.has(modulePath)) { |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1416 |
Path[] dirs = getLastElement(opts.valuesOf(modulePath)).toArray(new Path[0]); |
43712
5dfd0950317c
8173393: Module system implementation refresh (2/2017)
alanb
parents:
43242
diff
changeset
|
1417 |
options.moduleFinder = ModulePath.of(Runtime.version(), true, dirs); |
36511 | 1418 |
} |
1419 |
if (opts.has(moduleVersion)) |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1420 |
options.moduleVersion = getLastElement(opts.valuesOf(moduleVersion)); |
36511 | 1421 |
if (opts.has(mainClass)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1422 |
options.mainClass = getLastElement(opts.valuesOf(mainClass)); |
45004
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
1423 |
if (opts.has(targetPlatform)) |
ea3137042a61
8178380: Module system implementation refresh (5/2017)
alanb
parents:
44359
diff
changeset
|
1424 |
options.targetPlatform = getLastElement(opts.valuesOf(targetPlatform)); |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1425 |
if (opts.has(warnIfResolved)) |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1426 |
options.moduleResolution = getLastElement(opts.valuesOf(warnIfResolved)); |
42703
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1427 |
if (opts.has(doNotResolveByDefault)) { |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1428 |
if (options.moduleResolution == null) |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1429 |
options.moduleResolution = ModuleResolution.empty(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1430 |
options.moduleResolution = options.moduleResolution.withDoNotResolveByDefault(); |
20c39ea4a507
8170987: Module system implementation refresh (12/2016)
alanb
parents:
42468
diff
changeset
|
1431 |
} |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1432 |
if (opts.has(hashModules)) { |
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1433 |
options.modulesToHash = getLastElement(opts.valuesOf(hashModules)); |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1434 |
// if storing hashes then the module path is required |
36511 | 1435 |
if (options.moduleFinder == null) |
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1436 |
throw new CommandException("err.modulepath.must.be.specified") |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1437 |
.showUsage(true); |
36511 | 1438 |
} |
1439 |
||
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1440 |
if (options.mode.equals(Mode.HASH)) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1441 |
if (options.moduleFinder == null || options.modulesToHash == null) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1442 |
throw new CommandException("err.modulepath.must.be.specified") |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1443 |
.showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1444 |
} else { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1445 |
if (words.size() <= 1) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1446 |
throw new CommandException("err.jmod.must.be.specified").showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1447 |
Path path = Paths.get(words.get(1)); |
36511 | 1448 |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1449 |
if (options.mode.equals(Mode.CREATE) && Files.exists(path)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1450 |
throw new CommandException("err.file.already.exists", path); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1451 |
else if ((options.mode.equals(Mode.LIST) || |
42468 | 1452 |
options.mode.equals(Mode.DESCRIBE) || |
1453 |
options.mode.equals((Mode.EXTRACT))) |
|
37779
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1454 |
&& Files.notExists(path)) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1455 |
throw new CommandException("err.jmod.not.found", path); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1456 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1457 |
if (options.dryrun) { |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1458 |
throw new CommandException("err.invalid.dryrun.option"); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1459 |
} |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1460 |
options.jmodFile = path; |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1461 |
|
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1462 |
if (words.size() > 2) |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1463 |
throw new CommandException("err.unknown.option", |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1464 |
words.subList(2, words.size())).showUsage(true); |
7c84df693837
8154956: Module system implementation refresh (4/2016)
alanb
parents:
36511
diff
changeset
|
1465 |
} |
36511 | 1466 |
|
1467 |
if (options.mode.equals(Mode.CREATE) && options.classpath == null) |
|
1468 |
throw new CommandException("err.classpath.must.be.specified").showUsage(true); |
|
1469 |
if (options.mainClass != null && !isValidJavaIdentifier(options.mainClass)) |
|
1470 |
throw new CommandException("err.invalid.main-class", options.mainClass); |
|
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1471 |
if (options.mode.equals(Mode.EXTRACT) && options.extractDir != null) { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1472 |
try { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1473 |
Files.createDirectories(options.extractDir); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1474 |
} catch (IOException ioe) { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1475 |
throw new CommandException("err.cannot.create.dir", options.extractDir); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1476 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1477 |
} |
36511 | 1478 |
} catch (OptionException e) { |
1479 |
throw new CommandException(e.getMessage()); |
|
1480 |
} |
|
1481 |
} |
|
1482 |
||
1483 |
/** |
|
1484 |
* Returns true if, and only if, the given main class is a legal. |
|
1485 |
*/ |
|
1486 |
static boolean isValidJavaIdentifier(String mainClass) { |
|
1487 |
if (mainClass.length() == 0) |
|
1488 |
return false; |
|
1489 |
||
1490 |
if (!Character.isJavaIdentifierStart(mainClass.charAt(0))) |
|
1491 |
return false; |
|
1492 |
||
1493 |
int n = mainClass.length(); |
|
1494 |
for (int i=1; i < n; i++) { |
|
1495 |
char c = mainClass.charAt(i); |
|
1496 |
if (!Character.isJavaIdentifierPart(c) && c != '.') |
|
1497 |
return false; |
|
1498 |
} |
|
1499 |
if (mainClass.charAt(n-1) == '.') |
|
1500 |
return false; |
|
1501 |
||
1502 |
return true; |
|
1503 |
} |
|
1504 |
||
43067
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1505 |
static <E> E getLastElement(List<E> list) { |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1506 |
if (list.size() == 0) |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1507 |
throw new InternalError("Unexpected 0 list size"); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1508 |
return list.get(list.size() - 1); |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1509 |
} |
3f011a470ce2
8168149: Examine the behavior of jmod command-line options - repeating vs last one wins
chegar
parents:
42922
diff
changeset
|
1510 |
|
36511 | 1511 |
private void reportError(String message) { |
1512 |
out.println(getMessage("error.prefix") + " " + message); |
|
1513 |
} |
|
1514 |
||
1515 |
private void warning(String key, Object... args) { |
|
1516 |
out.println(getMessage("warn.prefix") + " " + getMessage(key, args)); |
|
1517 |
} |
|
1518 |
||
1519 |
private void showUsageSummary() { |
|
1520 |
out.println(getMessage("main.usage.summary", PROGNAME)); |
|
1521 |
} |
|
1522 |
||
1523 |
private void showHelp() { |
|
1524 |
out.println(getMessage("main.usage", PROGNAME)); |
|
1525 |
try { |
|
1526 |
parser.printHelpOn(out); |
|
1527 |
} catch (IOException x) { |
|
1528 |
throw new AssertionError(x); |
|
1529 |
} |
|
1530 |
} |
|
1531 |
||
1532 |
private void showVersion() { |
|
1533 |
out.println(version()); |
|
1534 |
} |
|
1535 |
||
1536 |
private String version() { |
|
1537 |
return System.getProperty("java.version"); |
|
1538 |
} |
|
1539 |
||
1540 |
private static String getMessage(String key, Object... args) { |
|
1541 |
try { |
|
1542 |
return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args); |
|
1543 |
} catch (MissingResourceException e) { |
|
1544 |
throw new InternalError("Missing message: " + key); |
|
1545 |
} |
|
1546 |
} |
|
1547 |
||
1548 |
private static class ResourceBundleHelper { |
|
1549 |
static final ResourceBundle bundle; |
|
1550 |
||
1551 |
static { |
|
1552 |
Locale locale = Locale.getDefault(); |
|
1553 |
try { |
|
1554 |
bundle = ResourceBundle.getBundle("jdk.tools.jmod.resources.jmod", locale); |
|
1555 |
} catch (MissingResourceException e) { |
|
1556 |
throw new InternalError("Cannot find jmod resource bundle for locale " + locale); |
|
1557 |
} |
|
1558 |
} |
|
1559 |
} |
|
1560 |
} |