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