136
137 /**
138 * Defines the storage options that SimpleLibrary supports.
139 */
140 public static enum StorageOption {
141 DEFLATED,
142 }
143
144 private static final class Header
145 extends MetaData
146 {
147 private static final String FILE
148 = FileConstants.META_PREFIX + "jigsaw-library";
149
150 private static final int MAJOR_VERSION = 0;
151 private static final int MINOR_VERSION = 1;
152
153 private static final int DEFLATED = 1 << 0;
154
155 private File parent;
156 private Set<StorageOption> opts;
157
158 public File parent() { return parent; }
159 public boolean isDeflated() {
160 return opts.contains(StorageOption.DEFLATED);
161 }
162
163 private Header(File root, File p, Set<StorageOption> opts) {
164 super(MAJOR_VERSION, MINOR_VERSION,
165 FileConstants.Type.LIBRARY_HEADER,
166 new File(root, FILE));
167 this.parent = p;
168 this.opts = new HashSet<>(opts);
169 }
170
171 private Header(File root) {
172 this(root, null, Collections.<StorageOption>emptySet());
173 }
174
175 protected void storeRest(DataOutputStream out)
176 throws IOException
177 {
178 int flags = 0;
179 if (isDeflated())
180 flags |= DEFLATED;
181 out.writeShort(flags);
182 out.writeByte((parent != null) ? 1 : 0);
183 if (parent != null)
184 out.writeUTF(parent.toString());
185 }
186
187 protected void loadRest(DataInputStream in)
188 throws IOException
189 {
190 opts = new HashSet<StorageOption>();
191 int flags = in.readShort();
192 if ((flags & DEFLATED) == DEFLATED)
193 opts.add(StorageOption.DEFLATED);
194 int b = in.readByte();
195 if (b != 0)
196 parent = new File(in.readUTF());
197 }
198
199 private static Header load(File f)
200 throws IOException
201 {
202 Header h = new Header(f);
203 h.load();
204 return h;
205 }
206
207 }
208
209 private final File root;
210 private final File canonicalRoot;
211 private File parentPath = null;
212 private SimpleLibrary parent = null;
213 private final Header hd;
214
215 public String name() { return root.toString(); }
216 public File root() { return canonicalRoot; }
217 public int majorVersion() { return hd.majorVersion; }
218 public int minorVersion() { return hd.minorVersion; }
219 public SimpleLibrary parent() { return parent; }
220 public boolean isDeflated() { return hd.isDeflated(); }
221
222 private URI location = null;
223 public URI location() {
224 if (location == null)
225 location = root().toURI();
226 return location;
227 }
228
229 @Override
230 public String toString() {
231 return (this.getClass().getName()
232 + "[" + canonicalRoot
233 + ", v" + hd.majorVersion + "." + hd.minorVersion + "]");
234 }
235
236 private SimpleLibrary(File path, boolean create, File parentPath, Set<StorageOption> opts)
237 throws IOException
238 {
239 root = path;
240 canonicalRoot = root.getCanonicalFile();
241 if (root.exists()) {
242 if (!root.isDirectory())
243 throw new IOException(root + ": Exists but is not a directory");
244 hd = Header.load(root);
245 if (hd.parent() != null) {
246 parent = open(hd.parent());
247 parentPath = hd.parent();
248 }
249 return;
250 }
251 if (!create)
252 throw new FileNotFoundException(root.toString());
253 if (parentPath != null) {
254 this.parent = open(parentPath);
255 this.parentPath = this.parent.root();
256 }
257 if (!root.mkdirs())
258 throw new IOException(root + ": Cannot create library directory");
259 hd = new Header(canonicalRoot, this.parentPath, opts);
260 hd.store();
261 }
262
263 public static SimpleLibrary create(File path, File parent, Set<StorageOption> opts)
264 throws IOException
265 {
266 return new SimpleLibrary(path, true, parent, opts);
267 }
268
269 public static SimpleLibrary create(File path, File parent)
270 throws IOException
271 {
272 return new SimpleLibrary(path, true, parent, Collections.<StorageOption>emptySet());
273 }
274
275 public static SimpleLibrary create(File path, Set<StorageOption> opts)
276 throws IOException
277 {
278 // ## Should default parent to $JAVA_HOME/lib/modules
279 return new SimpleLibrary(path, true, null, opts);
280 }
281
282 public static SimpleLibrary open(File path)
283 throws IOException
284 {
285 return new SimpleLibrary(path, false, null, Collections.<StorageOption>emptySet());
286 }
287
288 private static final JigsawModuleSystem jms
289 = JigsawModuleSystem.instance();
290
291 private static final class Index
292 extends MetaData
293 {
294
295 private static String FILE = "index";
296
297 private static int MAJOR_VERSION = 0;
298 private static int MINOR_VERSION = 1;
299
300 private Set<String> publicClasses;
301 public Set<String> publicClasses() { return publicClasses; }
302
303 private Set<String> otherClasses;
304 public Set<String> otherClasses() { return otherClasses; }
305
952 {
953 install(mfs, root, strip);
954 configure(null);
955 }
956
957 @Override
958 public void installFromManifests(Collection<Manifest> mfs)
959 throws ConfigurationException, IOException
960 {
961 installFromManifests(mfs, false);
962 }
963
964 private ModuleFileVerifier.Parameters mfvParams;
965
966 private ModuleId install(InputStream is, boolean verifySignature, boolean strip)
967 throws ConfigurationException, IOException, SignatureException
968 {
969 BufferedInputStream bin = new BufferedInputStream(is);
970 DataInputStream in = new DataInputStream(bin);
971 File md = null;
972 try (ModuleFile.Reader mr = new ModuleFile.Reader(in)) {
973 byte[] mib = mr.readStart();
974 ModuleInfo mi = jms.parseModuleInfo(mib);
975 md = moduleDir(mi.id());
976 ModuleId mid = mi.id();
977 if (md.exists())
978 throw new ConfigurationException(mid + ": Already installed");
979 if (!md.mkdirs())
980 throw new IOException(md + ": Cannot create");
981
982 if (verifySignature && mr.hasSignature()) {
983 ModuleFileVerifier mfv = new SignedModule.PKCS7Verifier(mr);
984 if (mfvParams == null) {
985 mfvParams = new SignedModule.VerifierParameters();
986 }
987 // Verify the module signature and validate the signer's
988 // certificate chain
989 Set<CodeSigner> signers = mfv.verifySignature(mfvParams);
990
991 // Verify the module header hash and the module info hash
992 mfv.verifyHashesStart(mfvParams);
1321 throws ConfigurationException, IOException
1322 {
1323 // ## mids not used yet
1324 for (ModuleInfo mi : listLocalRootModuleInfos()) {
1325 // ## We could be a lot more clever about this!
1326 Configuration<Context> cf
1327 = Configurator.configure(this, mi.id().toQuery());
1328 new StoredConfiguration(moduleDir(mi.id()), cf).store();
1329 }
1330 }
1331
1332 public URI findLocalResource(ModuleId mid, String name)
1333 throws IOException
1334 {
1335 return locateContent(mid, name);
1336 }
1337
1338 public File findLocalNativeLibrary(ModuleId mid, String name)
1339 throws IOException
1340 {
1341 File md = findModuleDir(mid);
1342 if (md == null)
1343 return null;
1344 File f = new File(new File(md, "lib"), name);
1345 if (!f.exists())
1346 return null;
1347 return f;
1348 }
1349
1350 public File classPath(ModuleId mid)
1351 throws IOException
1352 {
1353 File md = findModuleDir(mid);
1354 if (md == null) {
1355 if (parent != null)
1356 return parent.classPath(mid);
1357 return null;
1358 }
1359 // ## Check for other formats here
1360 return new File(md, "classes");
1361 }
1362
1363 /**
1364 * <p> Re-index the classes of the named previously-installed modules, and
|
136
137 /**
138 * Defines the storage options that SimpleLibrary supports.
139 */
140 public static enum StorageOption {
141 DEFLATED,
142 }
143
144 private static final class Header
145 extends MetaData
146 {
147 private static final String FILE
148 = FileConstants.META_PREFIX + "jigsaw-library";
149
150 private static final int MAJOR_VERSION = 0;
151 private static final int MINOR_VERSION = 1;
152
153 private static final int DEFLATED = 1 << 0;
154
155 private File parent;
156 // location of native libs for this library (may be outside the library)
157 private File natlibs;
158 // location of native cmds for this library (may be outside the library)
159 private File natcmds;
160
161 private Set<StorageOption> opts;
162
163 public File parent() { return parent; }
164 public File natlibs() { return natlibs; }
165 public File natcmds() { return natcmds; }
166 public boolean isDeflated() {
167 return opts.contains(StorageOption.DEFLATED);
168 }
169
170 private Header(File root, File p, File natlibs, File natcmds,
171 Set<StorageOption> opts) {
172 super(MAJOR_VERSION, MINOR_VERSION,
173 FileConstants.Type.LIBRARY_HEADER,
174 new File(root, FILE));
175 this.parent = p;
176 this.natlibs = natlibs;
177 this.natcmds = natcmds;
178 this.opts = new HashSet<>(opts);
179 }
180
181 private Header(File root) {
182 this(root, null, null, null, Collections.<StorageOption>emptySet());
183 }
184
185 protected void storeRest(DataOutputStream out)
186 throws IOException
187 {
188 int flags = 0;
189 if (isDeflated())
190 flags |= DEFLATED;
191 out.writeShort(flags);
192 out.writeByte((parent != null) ? 1 : 0);
193 if (parent != null)
194 out.writeUTF(parent.toString());
195 out.writeByte((natlibs != null) ? 1 : 0);
196 if (natlibs != null)
197 out.writeUTF(natlibs.toString());
198 out.writeByte((natcmds != null) ? 1 : 0);
199 if (natcmds != null)
200 out.writeUTF(natcmds.toString());
201 }
202
203 protected void loadRest(DataInputStream in)
204 throws IOException
205 {
206 opts = new HashSet<StorageOption>();
207 int flags = in.readShort();
208 if ((flags & DEFLATED) == DEFLATED)
209 opts.add(StorageOption.DEFLATED);
210 int b = in.readByte();
211 if (b != 0)
212 parent = new File(in.readUTF());
213 b = in.readByte();
214 if (b != 0)
215 natlibs = new File(in.readUTF());
216 b = in.readByte();
217 if (b != 0)
218 natcmds = new File(in.readUTF());
219 }
220
221 private static Header load(File f)
222 throws IOException
223 {
224 Header h = new Header(f);
225 h.load();
226 return h;
227 }
228
229 }
230
231 private final File root;
232 private final File canonicalRoot;
233 private File parentPath;
234 private File natlibs;
235 private File natcmds;
236 private SimpleLibrary parent;
237 private final Header hd;
238
239 public String name() { return root.toString(); }
240 public File root() { return canonicalRoot; }
241 public int majorVersion() { return hd.majorVersion; }
242 public int minorVersion() { return hd.minorVersion; }
243 public SimpleLibrary parent() { return parent; }
244 public File natlibs() { return natlibs; }
245 public File natcmds() { return natcmds; }
246 public boolean isDeflated() { return hd.isDeflated(); }
247
248 private URI location = null;
249 public URI location() {
250 if (location == null)
251 location = root().toURI();
252 return location;
253 }
254
255 @Override
256 public String toString() {
257 return (this.getClass().getName()
258 + "[" + canonicalRoot
259 + ", v" + hd.majorVersion + "." + hd.minorVersion + "]");
260 }
261
262 private SimpleLibrary(File path, boolean create, File parentPath,
263 File natlibs, File natcmds, Set<StorageOption> opts)
264 throws IOException
265 {
266 root = path;
267 canonicalRoot = root.getCanonicalFile();
268 if (root.exists()) {
269 //TODO: root exists, but we are creating????
270 if (!root.isDirectory())
271 throw new IOException(root + ": Exists but is not a directory");
272 hd = Header.load(root);
273 if (hd.parent() != null) {
274 parent = open(hd.parent());
275 this.parentPath = hd.parent();
276 }
277 if (hd.natlibs() != null)
278 this.natlibs = hd.natlibs();
279 if (hd.natcmds() != null)
280 this.natcmds = hd.natcmds();
281 return;
282 }
283 if (!create)
284 throw new FileNotFoundException(root.toString());
285 if (parentPath != null) {
286 this.parent = open(parentPath);
287 this.parentPath = this.parent.root();
288 }
289 if (!root.mkdirs())
290 throw new IOException(root + ": Cannot create library directory");
291 if (natlibs != null)
292 // resolve against the working dir, and store the absolute path
293 this.natlibs = natlibs.getCanonicalFile();
294 if (natcmds != null)
295 this.natcmds = natcmds.getCanonicalFile();
296 hd = new Header(canonicalRoot, this.parentPath, this.natlibs,
297 this.natcmds, opts);
298 hd.store();
299 }
300
301 public static SimpleLibrary create(File path, File parent, File natlibs,
302 File natcmds, Set<StorageOption> opts)
303 throws IOException
304 {
305 return new SimpleLibrary(path, true, parent, natlibs, natcmds, opts);
306 }
307
308 public static SimpleLibrary create(File path, File parent,
309 Set<StorageOption> opts)
310 throws IOException
311 {
312 return new SimpleLibrary(path, true, parent, null, null, opts);
313 }
314
315 public static SimpleLibrary create(File path, File parent)
316 throws IOException
317 {
318 return new SimpleLibrary(path, true, parent, null, null,
319 Collections.<StorageOption>emptySet());
320 }
321
322 public static SimpleLibrary create(File path, Set<StorageOption> opts)
323 throws IOException
324 {
325 // ## Should default parent to $JAVA_HOME/lib/modules
326 return new SimpleLibrary(path, true, null, null, null, opts);
327 }
328
329 public static SimpleLibrary open(File path)
330 throws IOException
331 {
332 return new SimpleLibrary(path, false, null, null, null,
333 Collections.<StorageOption>emptySet());
334 }
335
336 private static final JigsawModuleSystem jms
337 = JigsawModuleSystem.instance();
338
339 private static final class Index
340 extends MetaData
341 {
342
343 private static String FILE = "index";
344
345 private static int MAJOR_VERSION = 0;
346 private static int MINOR_VERSION = 1;
347
348 private Set<String> publicClasses;
349 public Set<String> publicClasses() { return publicClasses; }
350
351 private Set<String> otherClasses;
352 public Set<String> otherClasses() { return otherClasses; }
353
1000 {
1001 install(mfs, root, strip);
1002 configure(null);
1003 }
1004
1005 @Override
1006 public void installFromManifests(Collection<Manifest> mfs)
1007 throws ConfigurationException, IOException
1008 {
1009 installFromManifests(mfs, false);
1010 }
1011
1012 private ModuleFileVerifier.Parameters mfvParams;
1013
1014 private ModuleId install(InputStream is, boolean verifySignature, boolean strip)
1015 throws ConfigurationException, IOException, SignatureException
1016 {
1017 BufferedInputStream bin = new BufferedInputStream(is);
1018 DataInputStream in = new DataInputStream(bin);
1019 File md = null;
1020 try (ModuleFile.Reader mr = new ModuleFile.Reader(in, this)) {
1021 byte[] mib = mr.readStart();
1022 ModuleInfo mi = jms.parseModuleInfo(mib);
1023 md = moduleDir(mi.id());
1024 ModuleId mid = mi.id();
1025 if (md.exists())
1026 throw new ConfigurationException(mid + ": Already installed");
1027 if (!md.mkdirs())
1028 throw new IOException(md + ": Cannot create");
1029
1030 if (verifySignature && mr.hasSignature()) {
1031 ModuleFileVerifier mfv = new SignedModule.PKCS7Verifier(mr);
1032 if (mfvParams == null) {
1033 mfvParams = new SignedModule.VerifierParameters();
1034 }
1035 // Verify the module signature and validate the signer's
1036 // certificate chain
1037 Set<CodeSigner> signers = mfv.verifySignature(mfvParams);
1038
1039 // Verify the module header hash and the module info hash
1040 mfv.verifyHashesStart(mfvParams);
1369 throws ConfigurationException, IOException
1370 {
1371 // ## mids not used yet
1372 for (ModuleInfo mi : listLocalRootModuleInfos()) {
1373 // ## We could be a lot more clever about this!
1374 Configuration<Context> cf
1375 = Configurator.configure(this, mi.id().toQuery());
1376 new StoredConfiguration(moduleDir(mi.id()), cf).store();
1377 }
1378 }
1379
1380 public URI findLocalResource(ModuleId mid, String name)
1381 throws IOException
1382 {
1383 return locateContent(mid, name);
1384 }
1385
1386 public File findLocalNativeLibrary(ModuleId mid, String name)
1387 throws IOException
1388 {
1389 File f = natlibs();
1390 if (f == null) {
1391 f = findModuleDir(mid);
1392 if (f == null)
1393 return null;
1394 f = new File(f, "lib");
1395 }
1396 f = new File(f, name);
1397 if (!f.exists())
1398 return null;
1399 return f;
1400 }
1401
1402 public File classPath(ModuleId mid)
1403 throws IOException
1404 {
1405 File md = findModuleDir(mid);
1406 if (md == null) {
1407 if (parent != null)
1408 return parent.classPath(mid);
1409 return null;
1410 }
1411 // ## Check for other formats here
1412 return new File(md, "classes");
1413 }
1414
1415 /**
1416 * <p> Re-index the classes of the named previously-installed modules, and
|