src/share/classes/org/openjdk/jigsaw/SimpleLibrary.java
Print this page
@@ -26,10 +26,11 @@
package org.openjdk.jigsaw;
import java.lang.module.*;
import java.io.*;
import java.net.URI;
+import java.nio.file.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
@@ -68,12 +69,12 @@
protected final int maxMajorVersion;
protected final int maxMinorVersion;
protected int majorVersion;
protected int minorVersion;
- private FileConstants.Type type;
- private File file;
+ private final FileConstants.Type type;
+ private final File file;
protected MetaData(int maxMajor, int maxMinor,
FileConstants.Type t, File f)
{
maxMajorVersion = majorVersion = maxMajor;
@@ -84,37 +85,31 @@
protected abstract void storeRest(DataOutputStream out)
throws IOException;
void store() throws IOException {
- OutputStream fo = new FileOutputStream(file);
- DataOutputStream out
- = new DataOutputStream(new BufferedOutputStream(fo));
- try {
+ try (OutputStream fos = new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ DataOutputStream out = new DataOutputStream(bos)) {
out.writeInt(FileConstants.MAGIC);
out.writeShort(type.value());
out.writeShort(majorVersion);
out.writeShort(minorVersion);
storeRest(out);
- } finally {
- out.close();
}
}
protected abstract void loadRest(DataInputStream in)
throws IOException;
protected void load() throws IOException {
- InputStream fi = new FileInputStream(file);
- try {
- DataInputStream in
- = new DataInputStream(new BufferedInputStream(fi));
- int m = in.readInt();
- if (m != FileConstants.MAGIC)
+ try (InputStream fis = new FileInputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ DataInputStream in = new DataInputStream(fis)) {
+ if (in.readInt() != FileConstants.MAGIC)
throw new IOException(file + ": Invalid magic number");
- int typ = in.readShort();
- if (typ != type.value())
+ if (in.readShort() != type.value())
throw new IOException(file + ": Invalid file type");
int maj = in.readShort();
int min = in.readShort();
if ( maj > maxMajorVersion
|| (maj == maxMajorVersion && min > maxMinorVersion)) {
@@ -123,17 +118,13 @@
}
majorVersion = maj;
minorVersion = min;
loadRest(in);
} catch (EOFException x) {
- throw new IOException(file + ": Invalid library metadata",
- x);
- } finally {
- fi.close();
+ throw new IOException(file + ": Invalid library metadata", x);
}
}
-
}
/**
* Defines the storage options that SimpleLibrary supports.
*/
@@ -151,74 +142,106 @@
private static final int MINOR_VERSION = 1;
private static final int DEFLATED = 1 << 0;
private File parent;
+ // location of native libs for this library (may be outside the library)
+ // null:default, to use a per-module 'lib' directory
+ private File natlibs;
+ // location of native cmds for this library (may be outside the library)
+ // null:default, to use a per-module 'bin' directory
+ private File natcmds;
+ // location of config files for this library (may be outside the library)
+ // null:default, to use a per-module 'etc' directory
+ private File configs;
private Set<StorageOption> opts;
public File parent() { return parent; }
+ public File natlibs() { return natlibs; }
+ public File natcmds() { return natcmds; }
+ public File configs() { return configs; }
public boolean isDeflated() {
return opts.contains(StorageOption.DEFLATED);
}
- private Header(File root, File p, Set<StorageOption> opts) {
+ private Header(File root) {
super(MAJOR_VERSION, MINOR_VERSION,
FileConstants.Type.LIBRARY_HEADER,
new File(root, FILE));
- this.parent = p;
+ }
+
+ private Header(File root, File parent, File natlibs, File natcmds,
+ File configs, Set<StorageOption> opts) {
+ this(root);
+ this.parent = parent;
+ this.natlibs = natlibs;
+ this.natcmds = natcmds;
+ this.configs = configs;
this.opts = new HashSet<>(opts);
}
- private Header(File root) {
- this(root, null, Collections.<StorageOption>emptySet());
+ private void storePath(File p, DataOutputStream out) throws IOException {
+ if (p != null) {
+ out.writeByte(1);
+ out.writeUTF(Files.convertSeparator(p.toString()));
+ } else
+ out.write(0);
}
- protected void storeRest(DataOutputStream out)
- throws IOException
- {
+ protected void storeRest(DataOutputStream out) throws IOException {
int flags = 0;
if (isDeflated())
flags |= DEFLATED;
out.writeShort(flags);
- out.writeByte((parent != null) ? 1 : 0);
- if (parent != null)
- out.writeUTF(parent.toString());
+
+ storePath(parent, out);
+ storePath(natlibs, out);
+ storePath(natcmds, out);
+ storePath(configs, out);
}
- protected void loadRest(DataInputStream in)
- throws IOException
- {
+ private File loadPath(DataInputStream in) throws IOException {
+ if (in.readByte() != 0)
+ return new File(Files.platformSeparator(in.readUTF()));
+ return null;
+ }
+
+ protected void loadRest(DataInputStream in) throws IOException {
opts = new HashSet<StorageOption>();
int flags = in.readShort();
if ((flags & DEFLATED) == DEFLATED)
opts.add(StorageOption.DEFLATED);
- int b = in.readByte();
- if (b != 0)
- parent = new File(in.readUTF());
+ parent = loadPath(in);
+ natlibs = loadPath(in);
+ natcmds = loadPath(in);
+ configs = loadPath(in);
}
- private static Header load(File f)
- throws IOException
- {
+ private static Header load(File f) throws IOException {
Header h = new Header(f);
h.load();
return h;
}
-
}
private final File root;
private final File canonicalRoot;
- private File parentPath = null;
- private SimpleLibrary parent = null;
+ private File parentPath;
+ private File natlibs;
+ private File natcmds;
+ private File configs;
+ private SimpleLibrary parent;
private final Header hd;
public String name() { return root.toString(); }
public File root() { return canonicalRoot; }
public int majorVersion() { return hd.majorVersion; }
public int minorVersion() { return hd.minorVersion; }
public SimpleLibrary parent() { return parent; }
+ public File natlibs() { return natlibs; }
+ public File natcmds() { return natcmds; }
+ public File configs() { return configs; }
public boolean isDeflated() { return hd.isDeflated(); }
private URI location = null;
public URI location() {
if (location == null)
@@ -231,60 +254,109 @@
return (this.getClass().getName()
+ "[" + canonicalRoot
+ ", v" + hd.majorVersion + "." + hd.minorVersion + "]");
}
- private SimpleLibrary(File path, boolean create, File parentPath, Set<StorageOption> opts)
- throws IOException
- {
+
+ private static File resolveAndEnsurePath(File path) throws IOException {
+ if (path == null) { return null; }
+
+ File p = path.getCanonicalFile();
+ if (!p.exists())
+ Files.mkdirs(p, p.toString());
+ else {
+ Files.ensureIsDirectory(p);
+ Files.ensureWriteable(p);
+ }
+ return p;
+ }
+
+ private File relativize(File path) throws IOException {
+ if (path == null) { return null; }
+ // Return the path relative to the canonical root
+ return (canonicalRoot.toPath().relativize(path.toPath().toRealPath())).toFile();
+ }
+
+ // Opens an existing library
+ private SimpleLibrary(File path) throws IOException {
root = path;
canonicalRoot = root.getCanonicalFile();
- if (root.exists()) {
- if (!root.isDirectory())
- throw new IOException(root + ": Exists but is not a directory");
+ Files.ensureIsDirectory(root);
hd = Header.load(root);
if (hd.parent() != null) {
parent = open(hd.parent());
parentPath = hd.parent();
}
- return;
+
+ if (hd.natlibs() != null)
+ natlibs = new File(canonicalRoot, hd.natlibs().toString()).getCanonicalFile();
+ if (hd.natcmds() != null)
+ natcmds = new File(canonicalRoot, hd.natcmds().toString()).getCanonicalFile();
+ if (hd.configs() != null)
+ configs = new File(canonicalRoot, hd.configs().toString()).getCanonicalFile();
}
- if (!create)
- throw new FileNotFoundException(root.toString());
+
+ // Creates a new library
+ private SimpleLibrary(File path, File parentPath, File natlibs, File natcmds,
+ File configs, Set<StorageOption> opts)
+ throws IOException
+ {
+ root = path;
+ canonicalRoot = root.getCanonicalFile();
+ if (root.exists()) {
+ Files.ensureIsDirectory(root);
+ if (root.list().length != 0)
+ throw new IOException(root + ": Already Exists");
+ Files.ensureWriteable(root);
+ } else
+ Files.mkdirs(root, root.toString());
+
if (parentPath != null) {
this.parent = open(parentPath);
this.parentPath = this.parent.root();
}
- if (!root.mkdirs())
- throw new IOException(root + ": Cannot create library directory");
- hd = new Header(canonicalRoot, this.parentPath, opts);
+
+ this.natlibs = resolveAndEnsurePath(natlibs);
+ this.natcmds = resolveAndEnsurePath(natcmds);
+ this.configs = resolveAndEnsurePath(configs);
+
+ hd = new Header(canonicalRoot, this.parentPath, relativize(this.natlibs),
+ relativize(this.natcmds), relativize(this.configs), opts);
hd.store();
}
+ public static SimpleLibrary create(File path, File parent, File natlibs,
+ File natcmds, File configs,
+ Set<StorageOption> opts)
+ throws IOException
+ {
+ return new SimpleLibrary(path, parent, natlibs, natcmds, configs, opts);
+ }
+
public static SimpleLibrary create(File path, File parent, Set<StorageOption> opts)
throws IOException
{
- return new SimpleLibrary(path, true, parent, opts);
+ return new SimpleLibrary(path, parent, null, null, null, opts);
}
public static SimpleLibrary create(File path, File parent)
throws IOException
{
- return new SimpleLibrary(path, true, parent, Collections.<StorageOption>emptySet());
+ return SimpleLibrary.create(path, parent, Collections.<StorageOption>emptySet());
}
public static SimpleLibrary create(File path, Set<StorageOption> opts)
throws IOException
{
// ## Should default parent to $JAVA_HOME/lib/modules
- return new SimpleLibrary(path, true, null, opts);
+ return SimpleLibrary.create(path, null, opts);
}
public static SimpleLibrary open(File path)
throws IOException
{
- return new SimpleLibrary(path, false, null, Collections.<StorageOption>emptySet());
+ return new SimpleLibrary(path);
}
private static final JigsawModuleSystem jms
= JigsawModuleSystem.instance();
@@ -996,14 +1068,14 @@
// Store signer info
new Signers(md, signers).store();
// Read and verify the rest of the hashes
- mr.readRest(md, isDeflated());
+ mr.readRest(md, isDeflated(), natlibs(), natcmds(), configs());
mfv.verifyHashesRest(mfvParams);
} else {
- mr.readRest(md, isDeflated());
+ mr.readRest(md, isDeflated(), natlibs(), natcmds(), configs());
}
if (strip)
strip(md);
reIndex(mid); // ## Could do this while reading module file
@@ -1010,11 +1082,11 @@
return mid;
} catch (IOException | SignatureException x) {
if (md != null && md.exists()) {
try {
- Files.deleteTree(md);
+ ModuleFile.Reader.remove(md);
} catch (IOException y) {
y.initCause(x);
throw y;
}
}
@@ -1184,10 +1256,11 @@
{
ModuleId mid;
if (mf.getName().endsWith(".jar"))
mid = installFromJarFile(mf, verifySignature, strip);
else {
+ // Assume jmod file
try (FileInputStream in = new FileInputStream(mf)) {
mid = install(in, verifySignature, strip);
}
}
return mid;
@@ -1336,14 +1409,18 @@
}
public File findLocalNativeLibrary(ModuleId mid, String name)
throws IOException
{
- File md = findModuleDir(mid);
- if (md == null)
+ File f = natlibs();
+ if (f == null) {
+ f = findModuleDir(mid);
+ if (f == null)
return null;
- File f = new File(new File(md, "lib"), name);
+ f = new File(f, "lib");
+ }
+ f = new File(f, name);
if (!f.exists())
return null;
return f;
}