22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package org.openjdk.jigsaw;
27
28 import java.lang.module.*;
29 import java.io.*;
30 import java.net.URI;
31 import java.nio.channels.FileChannel;
32 import java.nio.file.*;
33 import java.nio.file.attribute.BasicFileAttributes;
34 import java.security.*;
35 import java.security.cert.*;
36 import java.util.*;
37 import java.util.jar.*;
38 import java.util.zip.*;
39
40 import static java.nio.file.StandardCopyOption.*;
41 import static java.nio.file.StandardOpenOption.*;
42 import org.openjdk.jigsaw.Repository.ModuleType;
43
44 /**
45 * A simple module library which stores data directly in the filesystem
46 *
47 * @see Library
48 */
49
50 // ## TODO: Move remaining parent-searching logic upward into Library class
51
52 // On-disk library layout
53 //
54 // $LIB/%jigsaw-library
55 // com.foo.bar/1.2.3/info (= module-info.class)
56 // index (list of defined classes)
57 // config (resolved configuration, if a root)
58 // classes/com/foo/bar/...
59 // resources/com/foo/bar/...
60 // lib/libbar.so
61 // bin/bar
62 // signer (signer's certchain & timestamp)
141 {
142 private static final String FILE
143 = FileConstants.META_PREFIX + "jigsaw-library";
144
145 private static final int MAJOR_VERSION = 0;
146 private static final int MINOR_VERSION = 1;
147
148 private static final int DEFLATED = 1 << 0;
149
150 private File parent;
151 // location of native libs for this library (may be outside the library)
152 // null:default, to use a per-module 'lib' directory
153 private File natlibs;
154 // location of native cmds for this library (may be outside the library)
155 // null:default, to use a per-module 'bin' directory
156 private File natcmds;
157 // location of config files for this library (may be outside the library)
158 // null:default, to use a per-module 'etc' directory
159 private File configs;
160 private Set<StorageOption> opts;
161
162 public File parent() { return parent; }
163 public File natlibs() { return natlibs; }
164 public File natcmds() { return natcmds; }
165 public File configs() { return configs; }
166 public boolean isDeflated() {
167 return opts.contains(StorageOption.DEFLATED);
168 }
169
170 private Header(File root) {
171 super(MAJOR_VERSION, MINOR_VERSION,
172 FileConstants.Type.LIBRARY_HEADER,
173 new File(root, FILE));
174 }
175
176 private Header(File root, File parent, File natlibs, File natcmds,
177 File configs, Set<StorageOption> opts) {
178 this(root);
179 this.parent = parent;
180 this.natlibs = natlibs;
181 this.natcmds = natcmds;
182 this.configs = configs;
183 this.opts = new HashSet<>(opts);
184 }
185
186 private void storePath(File p, DataOutputStream out) throws IOException {
187 if (p != null) {
188 out.writeByte(1);
189 out.writeUTF(Files.convertSeparator(p.toString()));
190 } else {
191 out.write(0);
192 }
193 }
194
195 protected void storeRest(DataOutputStream out) throws IOException {
196 int flags = 0;
197 if (isDeflated())
198 flags |= DEFLATED;
199 out.writeShort(flags);
200
201 storePath(parent, out);
202 storePath(natlibs, out);
203 storePath(natcmds, out);
204 storePath(configs, out);
205 }
206
207 private File loadPath(DataInputStream in) throws IOException {
208 if (in.readByte() != 0)
209 return new File(Files.platformSeparator(in.readUTF()));
210 return null;
211 }
212
213 protected void loadRest(DataInputStream in) throws IOException {
214 opts = new HashSet<StorageOption>();
215 int flags = in.readShort();
216 if ((flags & DEFLATED) == DEFLATED)
217 opts.add(StorageOption.DEFLATED);
218 parent = loadPath(in);
219 natlibs = loadPath(in);
220 natcmds = loadPath(in);
221 configs = loadPath(in);
222 }
223
224 private static Header load(File f) throws IOException {
225 Header h = new Header(f);
226 h.load();
227 return h;
228 }
229 }
230
231 private final File root;
232 private final File canonicalRoot;
233 private final File parentPath;
234 private final File natlibs;
235 private final File natcmds;
236 private final File configs;
237 private final SimpleLibrary parent;
238 private final Header hd;
239 private final ModuleDictionary moduleDictionary;
240 private final File lockf;
241 private final File trash;
242
243 public String name() { return root.toString(); }
244 public File root() { return canonicalRoot; }
245 public int majorVersion() { return hd.majorVersion; }
246 public int minorVersion() { return hd.minorVersion; }
247 public SimpleLibrary parent() { return parent; }
248 public File natlibs() { return natlibs; }
249 public File natcmds() { return natcmds; }
250 public File configs() { return configs; }
251 public boolean isDeflated() { return hd.isDeflated(); }
252
253 private URI location = null;
254 public URI location() {
255 if (location == null)
256 location = root().toURI();
257 return location;
258 }
259
260 @Override
261 public String toString() {
262 return (this.getClass().getName()
263 + "[" + canonicalRoot
264 + ", v" + hd.majorVersion + "." + hd.minorVersion + "]");
265 }
266
267 private static File resolveAndEnsurePath(File path) throws IOException {
268 if (path == null) { return null; }
269
270 File p = path.getCanonicalFile();
282 // Return the path relative to the canonical root
283 return (canonicalRoot.toPath().relativize(path.toPath().toRealPath())).toFile();
284 }
285
286 // Opens an existing library
287 private SimpleLibrary(File path) throws IOException {
288 root = path;
289 canonicalRoot = root.getCanonicalFile();
290 Files.ensureIsDirectory(root);
291 hd = Header.load(root);
292
293 parentPath = hd.parent();
294 parent = parentPath != null ? open(parentPath) : null;
295
296 natlibs = hd.natlibs() == null ? null :
297 new File(canonicalRoot, hd.natlibs().toString()).getCanonicalFile();
298 natcmds = hd.natcmds() == null ? null :
299 new File(canonicalRoot, hd.natcmds().toString()).getCanonicalFile();
300 configs = hd.configs() == null ? null :
301 new File(canonicalRoot, hd.configs().toString()).getCanonicalFile();
302
303 lockf = new File(root, FileConstants.META_PREFIX + "lock");
304 trash = new File(root, TRASH);
305 moduleDictionary = new ModuleDictionary(root);
306 }
307
308 // Creates a new library
309 private SimpleLibrary(File path, File parentPath, File natlibs, File natcmds,
310 File configs, Set<StorageOption> opts)
311 throws IOException
312 {
313 root = path;
314 canonicalRoot = root.getCanonicalFile();
315 if (root.exists()) {
316 Files.ensureIsDirectory(root);
317 if (root.list().length != 0)
318 throw new IOException(root + ": Already Exists");
319 Files.ensureWriteable(root);
320 } else
321 Files.mkdirs(root, root.toString());
322
323 this.parent = parentPath != null ? open(parentPath) : null;
324 this.parentPath = parentPath != null ? this.parent.root() : null;
325
326 this.natlibs = resolveAndEnsurePath(natlibs);
327 this.natcmds = resolveAndEnsurePath(natcmds);
328 this.configs = resolveAndEnsurePath(configs);
329
330 hd = new Header(canonicalRoot, this.parentPath, relativize(this.natlibs),
331 relativize(this.natcmds), relativize(this.configs), opts);
332 hd.store();
333
334 lockf = new File(root, FileConstants.META_PREFIX + "lock");
335 lockf.createNewFile();
336 trash = new File(root, TRASH);
337 Files.mkdirs(trash, "module library trash");
338 moduleDictionary = new ModuleDictionary(canonicalRoot);
339 moduleDictionary.store();
340 }
341
342 public static SimpleLibrary create(File path, File parent, File natlibs,
343 File natcmds, File configs,
344 Set<StorageOption> opts)
345 throws IOException
346 {
347 return new SimpleLibrary(path, parent, natlibs, natcmds, configs, opts);
348 }
349
350 public static SimpleLibrary create(File path, File parent, Set<StorageOption> opts)
351 throws IOException
352 {
353 return new SimpleLibrary(path, parent, null, null, null, opts);
354 }
355
356 public static SimpleLibrary create(File path, File parent)
357 throws IOException
358 {
359 return SimpleLibrary.create(path, parent, Collections.<StorageOption>emptySet());
360 }
361
362 public static SimpleLibrary create(File path, Set<StorageOption> opts)
363 throws IOException
364 {
365 // ## Should default parent to $JAVA_HOME/lib/modules
366 return SimpleLibrary.create(path, null, opts);
367 }
368
369 public static SimpleLibrary open(File path)
370 throws IOException
371 {
372 return new SimpleLibrary(path);
373 }
1170 }
1171 } catch (IOException y) {
1172 x.addSuppressed(y);
1173 }
1174 throw x;
1175 } finally {
1176 if (complete) {
1177 moduleDictionary.store();
1178 }
1179 fc.close();
1180 }
1181 }
1182
1183 @Override
1184 public void installFromManifests(Collection<Manifest> mfs)
1185 throws ConfigurationException, IOException
1186 {
1187 installFromManifests(mfs, false);
1188 }
1189
1190 private ModuleId installWhileLocked(ModuleType type, InputStream is, boolean verifySignature,
1191 boolean strip)
1192 throws ConfigurationException, IOException, SignatureException
1193 {
1194 switch (type) {
1195 case JAR:
1196 Path jf = java.nio.file.Files.createTempFile(null, null);
1197 try {
1198 java.nio.file.Files.copy(is, jf, StandardCopyOption.REPLACE_EXISTING);
1199 return installFromJarFile(jf.toFile(), verifySignature, strip);
1200 } finally {
1201 java.nio.file.Files.delete(jf);
1202 }
1203 case JMOD:
1204 default:
1205 return installWhileLocked(is, verifySignature, strip);
1206 }
1207 }
1208
1209 private ModuleId installWhileLocked(InputStream is, boolean verifySignature,
1210 boolean strip)
1211 throws ConfigurationException, IOException, SignatureException
1212 {
1213 BufferedInputStream bin = new BufferedInputStream(is);
1214 DataInputStream in = new DataInputStream(bin);
1215 ModuleInfo mi = null;
1216 try (ModuleFile.Reader mr = new ModuleFile.Reader(in)) {
1217 ModuleInfo moduleInfo = jms.parseModuleInfo(mr.getModuleInfoBytes());
1218 File md = moduleDictionary.add(moduleInfo);
1219 mi = moduleInfo;
1220 if (verifySignature && mr.hasSignature()) {
1221 // Verify the module signature
1222 SignedModule sm = new SignedModule(mr);
1223 Set<CodeSigner> signers = sm.verifySignature();
1224
1225 // Validate the signers
1226 try {
1227 SignedModule.validateSigners(signers);
1228 } catch (CertificateException x) {
1229 throw new SignatureException(x);
1230 }
1231
1232 // ## TODO: Check policy and determine if signer is trusted
1233 // ## and what permissions should be granted.
1234 // ## If there is no policy entry, show signers and prompt
1235 // ## user to accept before proceeding.
1236
1237 // Verify the module header hash and the module info hash
1498 // ## Handle case of installing multiple root modules
1499 assert res.rootQueries.size() == 1;
1500 ModuleIdQuery midq = res.rootQueries.iterator().next();
1501 ModuleInfo root = null;
1502 for (String mn : res.moduleViewForName.keySet()) {
1503 ModuleView mv = res.moduleViewForName.get(mn);
1504 if (midq.matches(mv.id())) {
1505 root = mv.moduleInfo();
1506 break;
1507 }
1508 }
1509 assert root != null;
1510
1511 // Download
1512 //
1513 for (ModuleId mid : res.modulesNeeded()) {
1514 URI u = res.locationForName.get(mid.name());
1515 assert u != null;
1516 RemoteRepository rr = repositoryList().firstRepository();
1517 assert rr != null;
1518 installWhileLocked(rr.fetchMetaData(mid).getType(),
1519 rr.fetch(mid),
1520 verifySignature,
1521 strip);
1522 res.locationForName.put(mid.name(), location());
1523 // ## If something goes wrong, delete all our modules
1524 }
1525
1526 // Configure
1527 //
1528 configureWhileModuleDirectoryLocked(res.modulesNeeded());
1529 complete = true;
1530 } catch (ConfigurationException | IOException | SignatureException |
1531 ModuleFileParserException x) { // ## catch throwable??
1532 try {
1533 for (ModuleId mid : res.modulesNeeded()) {
1534 ModuleInfo mi = readLocalModuleInfo(mid);
1535 if (mi != null) {
1536 moduleDictionary.remove(mi);
1537 }
1538 }
|
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package org.openjdk.jigsaw;
27
28 import java.lang.module.*;
29 import java.io.*;
30 import java.net.URI;
31 import java.nio.channels.FileChannel;
32 import java.nio.file.*;
33 import java.nio.file.attribute.BasicFileAttributes;
34 import java.security.*;
35 import java.security.cert.*;
36 import java.util.*;
37 import java.util.jar.*;
38 import java.util.zip.*;
39
40 import static java.nio.file.StandardCopyOption.*;
41 import static java.nio.file.StandardOpenOption.*;
42 import org.openjdk.jigsaw.Repository.ModuleFileType;
43
44 /**
45 * A simple module library which stores data directly in the filesystem
46 *
47 * @see Library
48 */
49
50 // ## TODO: Move remaining parent-searching logic upward into Library class
51
52 // On-disk library layout
53 //
54 // $LIB/%jigsaw-library
55 // com.foo.bar/1.2.3/info (= module-info.class)
56 // index (list of defined classes)
57 // config (resolved configuration, if a root)
58 // classes/com/foo/bar/...
59 // resources/com/foo/bar/...
60 // lib/libbar.so
61 // bin/bar
62 // signer (signer's certchain & timestamp)
141 {
142 private static final String FILE
143 = FileConstants.META_PREFIX + "jigsaw-library";
144
145 private static final int MAJOR_VERSION = 0;
146 private static final int MINOR_VERSION = 1;
147
148 private static final int DEFLATED = 1 << 0;
149
150 private File parent;
151 // location of native libs for this library (may be outside the library)
152 // null:default, to use a per-module 'lib' directory
153 private File natlibs;
154 // location of native cmds for this library (may be outside the library)
155 // null:default, to use a per-module 'bin' directory
156 private File natcmds;
157 // location of config files for this library (may be outside the library)
158 // null:default, to use a per-module 'etc' directory
159 private File configs;
160 private Set<StorageOption> opts;
161 // target Operating System of this library
162 private String os;
163 // target Architecture of this library
164 private String arch;
165
166 public File parent() { return parent; }
167 public File natlibs() { return natlibs; }
168 public File natcmds() { return natcmds; }
169 public File configs() { return configs; }
170 public String os() { return os; }
171 public String arch() { return arch; }
172 public boolean isDeflated() {
173 return opts.contains(StorageOption.DEFLATED);
174 }
175
176 private Header(File root) {
177 super(MAJOR_VERSION, MINOR_VERSION,
178 FileConstants.Type.LIBRARY_HEADER,
179 new File(root, FILE));
180 }
181
182 private Header(File root, File parent, File natlibs, File natcmds,
183 File configs, Set<StorageOption> opts, String os,
184 String arch) {
185 this(root);
186 this.parent = parent;
187 this.natlibs = natlibs;
188 this.natcmds = natcmds;
189 this.configs = configs;
190 this.os = os;
191 this.arch = arch;
192 this.opts = new HashSet<>(opts);
193 }
194
195 private void storePath(File p, DataOutputStream out) throws IOException {
196 if (p != null) {
197 out.writeByte(1);
198 out.writeUTF(Files.convertSeparator(p.toString()));
199 } else {
200 out.write(0);
201 }
202 }
203
204 private void storeUTF(String s, DataOutputStream out) throws IOException {
205 if (s != null) {
206 out.writeByte(1);
207 out.writeUTF(s);
208 } else {
209 out.write(0);
210 }
211 }
212
213 @Override
214 protected void storeRest(DataOutputStream out) throws IOException {
215 int flags = 0;
216 if (isDeflated())
217 flags |= DEFLATED;
218 out.writeShort(flags);
219
220 storePath(parent, out);
221 storePath(natlibs, out);
222 storePath(natcmds, out);
223 storePath(configs, out);
224 storeUTF(os, out);
225 storeUTF(arch, out);
226 }
227
228 private File loadPath(DataInputStream in) throws IOException {
229 if (in.readByte() != 0)
230 return new File(Files.platformSeparator(in.readUTF()));
231 return null;
232 }
233
234 private String loadUTF(DataInputStream in) throws IOException {
235 if (in.readByte() != 0)
236 return in.readUTF();
237 return null;
238 }
239
240 @Override
241 protected void loadRest(DataInputStream in) throws IOException {
242 opts = new HashSet<StorageOption>();
243 int flags = in.readShort();
244 if ((flags & DEFLATED) == DEFLATED)
245 opts.add(StorageOption.DEFLATED);
246 parent = loadPath(in);
247 natlibs = loadPath(in);
248 natcmds = loadPath(in);
249 configs = loadPath(in);
250 os = loadUTF(in);
251 arch = loadUTF(in);
252 }
253
254 private static Header load(File f) throws IOException {
255 Header h = new Header(f);
256 h.load();
257 return h;
258 }
259 }
260
261 private final File root;
262 private final File canonicalRoot;
263 private final File parentPath;
264 private final File natlibs;
265 private final File natcmds;
266 private final File configs;
267 private final ModuleArchitecture modArch;
268 private final SimpleLibrary parent;
269 private final Header hd;
270 private final ModuleDictionary moduleDictionary;
271 private final File lockf;
272 private final File trash;
273
274 public String name() { return root.toString(); }
275 public File root() { return canonicalRoot; }
276 public int majorVersion() { return hd.majorVersion; }
277 public int minorVersion() { return hd.minorVersion; }
278 public SimpleLibrary parent() { return parent; }
279 public File natlibs() { return natlibs; }
280 public File natcmds() { return natcmds; }
281 public File configs() { return configs; }
282 public ModuleArchitecture architecture() { return modArch; }
283 public boolean isDeflated() { return hd.isDeflated(); }
284
285 private URI location = null;
286 public URI location() {
287 if (location == null)
288 location = root().toURI();
289 return location;
290 }
291
292 @Override
293 public String toString() {
294 return (this.getClass().getName()
295 + "[" + canonicalRoot
296 + ", v" + hd.majorVersion + "." + hd.minorVersion + "]");
297 }
298
299 private static File resolveAndEnsurePath(File path) throws IOException {
300 if (path == null) { return null; }
301
302 File p = path.getCanonicalFile();
314 // Return the path relative to the canonical root
315 return (canonicalRoot.toPath().relativize(path.toPath().toRealPath())).toFile();
316 }
317
318 // Opens an existing library
319 private SimpleLibrary(File path) throws IOException {
320 root = path;
321 canonicalRoot = root.getCanonicalFile();
322 Files.ensureIsDirectory(root);
323 hd = Header.load(root);
324
325 parentPath = hd.parent();
326 parent = parentPath != null ? open(parentPath) : null;
327
328 natlibs = hd.natlibs() == null ? null :
329 new File(canonicalRoot, hd.natlibs().toString()).getCanonicalFile();
330 natcmds = hd.natcmds() == null ? null :
331 new File(canonicalRoot, hd.natcmds().toString()).getCanonicalFile();
332 configs = hd.configs() == null ? null :
333 new File(canonicalRoot, hd.configs().toString()).getCanonicalFile();
334 modArch = ModuleArchitecture.create(hd.os(), hd.arch());
335
336 lockf = new File(root, FileConstants.META_PREFIX + "lock");
337 trash = new File(root, TRASH);
338 moduleDictionary = new ModuleDictionary(root);
339 }
340
341 // Creates a new library
342 private SimpleLibrary(File path, File parentPath, File natlibs, File natcmds,
343 File configs, Set<StorageOption> opts,
344 ModuleArchitecture modArch)
345 throws IOException
346 {
347 root = path;
348 canonicalRoot = root.getCanonicalFile();
349 if (root.exists()) {
350 Files.ensureIsDirectory(root);
351 if (root.list().length != 0)
352 throw new IOException(root + ": Already Exists");
353 Files.ensureWriteable(root);
354 } else
355 Files.mkdirs(root, root.toString());
356
357 this.parent = parentPath != null ? open(parentPath) : null;
358 this.parentPath = parentPath != null ? this.parent.root() : null;
359
360 this.natlibs = resolveAndEnsurePath(natlibs);
361 this.natcmds = resolveAndEnsurePath(natcmds);
362 this.configs = resolveAndEnsurePath(configs);
363 this.modArch = modArch;
364
365 hd = new Header(canonicalRoot, this.parentPath, relativize(this.natlibs),
366 relativize(this.natcmds), relativize(this.configs),
367 opts, modArch.os(), modArch.arch());
368 hd.store();
369
370 lockf = new File(root, FileConstants.META_PREFIX + "lock");
371 lockf.createNewFile();
372 trash = new File(root, TRASH);
373 Files.mkdirs(trash, "module library trash");
374 moduleDictionary = new ModuleDictionary(canonicalRoot);
375 moduleDictionary.store();
376 }
377
378 public static SimpleLibrary create(File path, File parent, File natlibs,
379 File natcmds, File configs,
380 Set<StorageOption> opts,
381 ModuleArchitecture modArch)
382 throws IOException
383 {
384 return new SimpleLibrary(path, parent, natlibs, natcmds, configs,
385 opts, modArch);
386 }
387
388 public static SimpleLibrary create(File path, File parent, Set<StorageOption> opts)
389 throws IOException
390 {
391 return new SimpleLibrary(path, parent, null, null, null, opts,
392 ModuleArchitecture.ANY);
393 }
394
395 public static SimpleLibrary create(File path, File parent)
396 throws IOException
397 {
398 return SimpleLibrary.create(path, parent, Collections.<StorageOption>emptySet());
399 }
400
401 public static SimpleLibrary create(File path, Set<StorageOption> opts)
402 throws IOException
403 {
404 // ## Should default parent to $JAVA_HOME/lib/modules
405 return SimpleLibrary.create(path, null, opts);
406 }
407
408 public static SimpleLibrary open(File path)
409 throws IOException
410 {
411 return new SimpleLibrary(path);
412 }
1209 }
1210 } catch (IOException y) {
1211 x.addSuppressed(y);
1212 }
1213 throw x;
1214 } finally {
1215 if (complete) {
1216 moduleDictionary.store();
1217 }
1218 fc.close();
1219 }
1220 }
1221
1222 @Override
1223 public void installFromManifests(Collection<Manifest> mfs)
1224 throws ConfigurationException, IOException
1225 {
1226 installFromManifests(mfs, false);
1227 }
1228
1229 private ModuleId installWhileLocked(ModuleFileType type, InputStream is,
1230 boolean verifySignature, boolean strip)
1231 throws ConfigurationException, IOException, SignatureException
1232 {
1233 switch (type) {
1234 case JAR:
1235 Path jf = java.nio.file.Files.createTempFile(null, null);
1236 try {
1237 java.nio.file.Files.copy(is, jf, StandardCopyOption.REPLACE_EXISTING);
1238 return installFromJarFile(jf.toFile(), verifySignature, strip);
1239 } finally {
1240 java.nio.file.Files.delete(jf);
1241 }
1242 case JMOD:
1243 default:
1244 return installWhileLocked(is, verifySignature, strip);
1245 }
1246 }
1247
1248 private ModuleId installWhileLocked(InputStream is, boolean verifySignature,
1249 boolean strip)
1250 throws ConfigurationException, IOException, SignatureException
1251 {
1252 BufferedInputStream bin = new BufferedInputStream(is);
1253 DataInputStream in = new DataInputStream(bin);
1254 ModuleInfo mi = null;
1255 try (ModuleFile.Reader mr = new ModuleFile.Reader(in)) {
1256 ModuleInfo moduleInfo = jms.parseModuleInfo(mr.getModuleInfoBytes());
1257
1258 // Installee must have the same architecture as the library
1259 if (!mr.getArchitecture().matches(architecture()))
1260 throw new IOException("Module architecture [" + mr.getArchitecture()
1261 + "] does not match library ["
1262 + architecture() + "]"); // ## exception type??
1263
1264 File md = moduleDictionary.add(moduleInfo);
1265 mi = moduleInfo;
1266 if (verifySignature && mr.hasSignature()) {
1267 // Verify the module signature
1268 SignedModule sm = new SignedModule(mr);
1269 Set<CodeSigner> signers = sm.verifySignature();
1270
1271 // Validate the signers
1272 try {
1273 SignedModule.validateSigners(signers);
1274 } catch (CertificateException x) {
1275 throw new SignatureException(x);
1276 }
1277
1278 // ## TODO: Check policy and determine if signer is trusted
1279 // ## and what permissions should be granted.
1280 // ## If there is no policy entry, show signers and prompt
1281 // ## user to accept before proceeding.
1282
1283 // Verify the module header hash and the module info hash
1544 // ## Handle case of installing multiple root modules
1545 assert res.rootQueries.size() == 1;
1546 ModuleIdQuery midq = res.rootQueries.iterator().next();
1547 ModuleInfo root = null;
1548 for (String mn : res.moduleViewForName.keySet()) {
1549 ModuleView mv = res.moduleViewForName.get(mn);
1550 if (midq.matches(mv.id())) {
1551 root = mv.moduleInfo();
1552 break;
1553 }
1554 }
1555 assert root != null;
1556
1557 // Download
1558 //
1559 for (ModuleId mid : res.modulesNeeded()) {
1560 URI u = res.locationForName.get(mid.name());
1561 assert u != null;
1562 RemoteRepository rr = repositoryList().firstRepository();
1563 assert rr != null;
1564 Repository.ModuleFileMetaData mfmd = rr.fetchMetaData(mid);
1565 // Installee must have the same architecture as the library
1566 if (!mfmd.architecture().matches(architecture()))
1567 throw new IOException("Module architecture [" + mfmd.architecture()
1568 + "] does not match library ["
1569 + architecture() + "]"); // ## exception type??
1570 installWhileLocked(mfmd.getType(),
1571 rr.fetch(mid),
1572 verifySignature,
1573 strip);
1574 res.locationForName.put(mid.name(), location());
1575 // ## If something goes wrong, delete all our modules
1576 }
1577
1578 // Configure
1579 //
1580 configureWhileModuleDirectoryLocked(res.modulesNeeded());
1581 complete = true;
1582 } catch (ConfigurationException | IOException | SignatureException |
1583 ModuleFileParserException x) { // ## catch throwable??
1584 try {
1585 for (ModuleId mid : res.modulesNeeded()) {
1586 ModuleInfo mi = readLocalModuleInfo(mid);
1587 if (mi != null) {
1588 moduleDictionary.remove(mi);
1589 }
1590 }
|