--- old/src/share/classes/org/openjdk/jigsaw/ModuleFile.java Mon Dec 12 16:27:56 2011 +++ new/src/share/classes/org/openjdk/jigsaw/ModuleFile.java Mon Dec 12 16:27:56 2011 @@ -58,6 +58,9 @@ public final static class Reader implements Closeable { + // The library where this module is to be installed, or null if + // simply extracting ( jmod Extract, or jsign ) + private SimpleLibrary lib; private DataInputStream stream; private File destination; private boolean deflate; @@ -123,6 +126,11 @@ } } + public Reader(DataInputStream stream, SimpleLibrary lib) { + this(stream); + this.lib = lib; + } + private void checkHashMatch(byte[] expected, byte[] computed) throws IOException { @@ -469,6 +477,19 @@ return readModuleInfo(in, csize); // signature has the same format } + // Returns the path for the section type, if the library + // has one configured. + private File librarySectionPath(SectionType type) { + if (lib != null && type == SectionType.NATIVE_LIBS + && lib.natlibs() != null) + return lib.natlibs(); + if (lib != null && type == SectionType.NATIVE_CMDS + && lib.natcmds() != null) + return lib.natcmds(); + + return null; + } + private File computeRealPath(String storedpath) throws IOException { String convertedpath = storedpath.replace('/', File.separatorChar); @@ -489,6 +510,16 @@ String storedpath) throws IOException { + File lsp = librarySectionPath(type); + if (lsp != null) { + // The library has a configured path for this section + File realpath = new File(lsp, storedpath); + // Create the parent directories if necessary + File parent = realpath.getParentFile(); + if (!parent.exists()) + Files.mkdirs(parent, realpath.getName()); + return realpath; + } String dir = getSubdirOfSection(type); return computeRealPath(dir + File.separatorChar + storedpath); } --- old/src/share/classes/org/openjdk/jigsaw/SimpleLibrary.java Mon Dec 12 16:27:57 2011 +++ new/src/share/classes/org/openjdk/jigsaw/SimpleLibrary.java Mon Dec 12 16:27:57 2011 @@ -153,23 +153,33 @@ private static final int DEFLATED = 1 << 0; private File parent; + // location of native libs for this library (may be outside the library) + private File natlibs; + // location of native cmds for this library (may be outside the library) + private File natcmds; + private Set opts; public File parent() { return parent; } + public File natlibs() { return natlibs; } + public File natcmds() { return natcmds; } public boolean isDeflated() { return opts.contains(StorageOption.DEFLATED); } - private Header(File root, File p, Set opts) { + private Header(File root, File p, File natlibs, File natcmds, + Set opts) { super(MAJOR_VERSION, MINOR_VERSION, FileConstants.Type.LIBRARY_HEADER, new File(root, FILE)); this.parent = p; + this.natlibs = natlibs; + this.natcmds = natcmds; this.opts = new HashSet<>(opts); } private Header(File root) { - this(root, null, Collections.emptySet()); + this(root, null, null, null, Collections.emptySet()); } protected void storeRest(DataOutputStream out) @@ -182,6 +192,12 @@ out.writeByte((parent != null) ? 1 : 0); if (parent != null) out.writeUTF(parent.toString()); + out.writeByte((natlibs != null) ? 1 : 0); + if (natlibs != null) + out.writeUTF(natlibs.toString()); + out.writeByte((natcmds != null) ? 1 : 0); + if (natcmds != null) + out.writeUTF(natcmds.toString()); } protected void loadRest(DataInputStream in) @@ -194,6 +210,12 @@ int b = in.readByte(); if (b != 0) parent = new File(in.readUTF()); + b = in.readByte(); + if (b != 0) + natlibs = new File(in.readUTF()); + b = in.readByte(); + if (b != 0) + natcmds = new File(in.readUTF()); } private static Header load(File f) @@ -208,8 +230,10 @@ 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 SimpleLibrary parent; private final Header hd; public String name() { return root.toString(); } @@ -217,6 +241,8 @@ 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 boolean isDeflated() { return hd.isDeflated(); } private URI location = null; @@ -233,19 +259,25 @@ + ", v" + hd.majorVersion + "." + hd.minorVersion + "]"); } - private SimpleLibrary(File path, boolean create, File parentPath, Set opts) + private SimpleLibrary(File path, boolean create, File parentPath, + File natlibs, File natcmds, Set opts) throws IOException { root = path; canonicalRoot = root.getCanonicalFile(); if (root.exists()) { + //TODO: root exists, but we are creating???? if (!root.isDirectory()) throw new IOException(root + ": Exists but is not a directory"); hd = Header.load(root); if (hd.parent() != null) { parent = open(hd.parent()); - parentPath = hd.parent(); + this.parentPath = hd.parent(); } + if (hd.natlibs() != null) + this.natlibs = hd.natlibs(); + if (hd.natcmds() != null) + this.natcmds = hd.natcmds(); return; } if (!create) @@ -256,20 +288,35 @@ } if (!root.mkdirs()) throw new IOException(root + ": Cannot create library directory"); - hd = new Header(canonicalRoot, this.parentPath, opts); + if (natlibs != null) + // resolve against the working dir, and store the absolute path + this.natlibs = natlibs.getCanonicalFile(); + if (natcmds != null) + this.natcmds = natcmds.getCanonicalFile(); + hd = new Header(canonicalRoot, this.parentPath, this.natlibs, + this.natcmds, opts); hd.store(); } - public static SimpleLibrary create(File path, File parent, Set opts) + public static SimpleLibrary create(File path, File parent, File natlibs, + File natcmds, Set opts) throws IOException { - return new SimpleLibrary(path, true, parent, opts); + return new SimpleLibrary(path, true, parent, natlibs, natcmds, opts); } + public static SimpleLibrary create(File path, File parent, + Set opts) + throws IOException + { + return new SimpleLibrary(path, true, parent, null, null, opts); + } + public static SimpleLibrary create(File path, File parent) - throws IOException + throws IOException { - return new SimpleLibrary(path, true, parent, Collections.emptySet()); + return new SimpleLibrary(path, true, parent, null, null, + Collections.emptySet()); } public static SimpleLibrary create(File path, Set opts) @@ -276,13 +323,14 @@ throws IOException { // ## Should default parent to $JAVA_HOME/lib/modules - return new SimpleLibrary(path, true, null, opts); + return new SimpleLibrary(path, true, null, null, null, opts); } public static SimpleLibrary open(File path) throws IOException { - return new SimpleLibrary(path, false, null, Collections.emptySet()); + return new SimpleLibrary(path, false, null, null, null, + Collections.emptySet()); } private static final JigsawModuleSystem jms @@ -829,11 +877,11 @@ * directory. */ private void strip(File md) throws IOException { - File classes = new File(md, "classes"); + File classes = new File(md, "classes"); if (classes.isFile()) { File pf = new File(md, "classes.pack"); try (JarFile jf = new JarFile(classes); - FileOutputStream out = new FileOutputStream(pf)) + FileOutputStream out = new FileOutputStream(pf)) { Pack200.Packer packer = Pack200.newPacker(); Map p = packer.properties(); @@ -969,7 +1017,7 @@ BufferedInputStream bin = new BufferedInputStream(is); DataInputStream in = new DataInputStream(bin); File md = null; - try (ModuleFile.Reader mr = new ModuleFile.Reader(in)) { + try (ModuleFile.Reader mr = new ModuleFile.Reader(in, this)) { byte[] mib = mr.readStart(); ModuleInfo mi = jms.parseModuleInfo(mib); md = moduleDir(mi.id()); @@ -1003,8 +1051,8 @@ } else { mr.readRest(md, isDeflated()); } - - if (strip) + + if (strip) strip(md); reIndex(mid); // ## Could do this while reading module file return mid; @@ -1338,10 +1386,14 @@ public File findLocalNativeLibrary(ModuleId mid, String name) throws IOException { - File md = findModuleDir(mid); - if (md == null) - return null; - File f = new File(new File(md, "lib"), name); + File f = natlibs(); + if (f == null) { + f = findModuleDir(mid); + if (f == null) + return null; + f = new File(f, "lib"); + } + f = new File(f, name); if (!f.exists()) return null; return f; --- old/src/share/classes/org/openjdk/jigsaw/cli/Librarian.java Mon Dec 12 16:27:58 2011 +++ new/src/share/classes/org/openjdk/jigsaw/cli/Librarian.java Mon Dec 12 16:27:58 2011 @@ -47,12 +47,41 @@ private static JigsawModuleSystem jms = JigsawModuleSystem.instance(); + private static final File homeLibrary + = new File(System.getProperty("java.home"), "lib/modules"); + static class Create extends Command { protected void go(SimpleLibrary lib) throws Command.Exception { + //assert lib == null; noDry(); + File lp = libPath(opts); + File pp = null; + if (opts.has(parentPath)) { + pp = opts.valueOf(parentPath); + } else if (!opts.has("N")) { + pp = homeLibrary; + } + File natlibs = null; + if (opts.has(nativeLibs)) { + natlibs = opts.valueOf(nativeLibs); + } + File natcmds = null; + if (opts.has(nativeCmds)) { + natcmds = opts.valueOf(nativeCmds); + } finishArgs(); + + Set createOpts = new HashSet<>(); + if (opts.has("z")) + createOpts.add(StorageOption.DEFLATED); + + try { + lib = SimpleLibrary.create(lp, pp, natlibs, natcmds, createOpts); + } catch (IOException x) { + throw new Command.Exception(x); + } } } @@ -121,8 +150,8 @@ File module = new File(takeArg()); File classes = null; try (FileInputStream fis = new FileInputStream(module); - DataInputStream dis = new DataInputStream(fis); - ModuleFile.Reader reader = new ModuleFile.Reader(dis)) { + DataInputStream dis = new DataInputStream(fis); + ModuleFile.Reader reader = new ModuleFile.Reader(dis)) { ModuleInfo mi = jms.parseModuleInfo(reader.readStart()); classes = new File(mi.id().name()); @@ -447,7 +476,7 @@ } } } - + private static Map>> commands = new HashMap<>(); @@ -473,6 +502,10 @@ private OptionParser parser; private static OptionSpec repoIndex; // ## + private static OptionSpec libPath; + private static OptionSpec parentPath; + private static OptionSpec nativeLibs; + private static OptionSpec nativeCmds; private void usage() { out.format("%n"); @@ -479,7 +512,7 @@ out.format("usage: jmod add-repo [-i ] URL%n"); out.format(" jmod extract ...%n"); out.format(" jmod config [ ...]%n"); - out.format(" jmod create [-L ] [-P ]%n"); + out.format(" jmod create [-L ] [-P ] [-natlibs ] [-natcmds ]%n"); out.format(" jmod del-repo URL%n"); out.format(" jmod dump-class %n"); out.format(" jmod dump-config %n"); @@ -510,7 +543,7 @@ parser = new OptionParser(); // ## Need subcommand-specific option parsing - OptionSpec libPath + libPath = (parser.acceptsAll(Arrays.asList("L", "library"), "Module-library location" + " (default $JAVA_MODULES)") @@ -517,12 +550,23 @@ .withRequiredArg() .describedAs("path") .ofType(File.class)); - OptionSpec parentPath + parentPath = (parser.acceptsAll(Arrays.asList("P", "parent-path"), "Parent module-library location") .withRequiredArg() .describedAs("path") .ofType(File.class)); + nativeLibs + = (parser.accepts("natlibs", "Directory with native libs") + .withRequiredArg() + .describedAs("dir") + .ofType(File.class)); + + nativeCmds + = (parser.accepts("natcmds", "Directory with native launchers") + .withRequiredArg() + .describedAs("dir") + .ofType(File.class)); parser.acceptsAll(Arrays.asList("N", "no-parent"), "Use no parent library when creating"); parser.acceptsAll(Arrays.asList("v", "verbose"), @@ -550,13 +594,10 @@ + "Treat as unsigned."); parser.acceptsAll(Arrays.asList("G", "strip-debug"), "Strip debug attributes during installation"); - + if (args.length == 0) usage(); - File homeLibrary = new File(System.getProperty("java.home"), - "lib/modules"); - OptionSet opts = parser.parse(args); if (opts.has("h")) usage(); @@ -567,47 +608,29 @@ Class> cmd = commands.get(verb); if (cmd == null) throw new Command.Exception("%s: unknown command", verb); - File lp = null; - if (opts.has(libPath)) { - lp = opts.valueOf(libPath); - } else { - String jm = System.getenv("JAVA_MODULES"); - if (jm != null) - lp = new File(jm); - else - lp = homeLibrary; - } - File pp = null; - if (opts.has(parentPath)) { - pp = opts.valueOf(parentPath); - } else if (!opts.has("N")) { - pp = homeLibrary; - } + + // every command, except create, needs to be passed a reference to the library SimpleLibrary lib = null; - try { - if (verb.equals("create")) { - Set createOpts = new HashSet<>(); - if (opts.has("z")) - createOpts.add(StorageOption.DEFLATED); - lib = SimpleLibrary.create(lp, pp, createOpts); - } else { + if (!verb.equals("create")) { + File lp = libPath(opts); + try { lib = SimpleLibrary.open(lp); + } catch (FileNotFoundException x) { + String msg = null; + File f = new File(x.getMessage()); + try { + f = f.getCanonicalFile(); + if (lp.getCanonicalFile().equals(f)) + msg = "No such library"; + else + msg = "Cannot open parent library " + f; + } catch (IOException y) { + throw new Command.Exception(y); + } + throw new Command.Exception("%s: %s", lp, msg); + } catch (IOException x) { + throw new Command.Exception(x); } - } catch (FileNotFoundException x) { - String msg = null; - File f = new File(x.getMessage()); - try { - f = f.getCanonicalFile(); - if (lp.getCanonicalFile().equals(f)) - msg = "No such library"; - else - msg = "Cannot open parent library " + f; - } catch (IOException y) { - throw new Command.Exception(y); - } - throw new Command.Exception("%s: %s", lp, msg); - } catch (IOException x) { - throw new Command.Exception(x); } try { cmd.newInstance().run(lib, opts); @@ -617,6 +640,18 @@ throw new AssertionError(x); } } + + private static File libPath(OptionSet opts) { + if (opts.has(libPath)) { + return opts.valueOf(libPath); + } else { + String jm = System.getenv("JAVA_MODULES"); + if (jm != null) + return new File(jm); + else + return homeLibrary; + } + } private Librarian() { } --- old/test/org/openjdk/jigsaw/hello-native.sh Mon Dec 12 16:27:59 2011 +++ new/test/org/openjdk/jigsaw/hello-native.sh Mon Dec 12 16:27:59 2011 @@ -89,6 +89,9 @@ $BIN/jmod -L z.lib create $BIN/jmod -L z.lib install z.test/module-files/* $BIN/java -L z.lib -m com.greetings +$BIN/jmod -L z.libSpecifyLib create -natlibs z.libSpecifyLib_libs +$BIN/jmod -L z.libSpecifyLib install z.test/module-files/* +$BIN/java -L z.libSpecifyLib -m com.greetings exit 0