src/share/classes/sun/module/tools/JRepo.java

Print this page

        

*** 28,55 **** import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URISyntaxException; import java.module.*; import java.security.AccessController; import java.text.DateFormat; import java.util.Arrays; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; ! import sun.module.JamUtils; import sun.module.repository.RepositoryConfig; import sun.security.action.GetPropertyAction; import sun.tools.jar.CommandLine; /** --- 28,60 ---- import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; + import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URISyntaxException; import java.module.*; + import java.module.annotation.ImportPolicyClass; import java.security.AccessController; + import java.security.PrivilegedAction; import java.text.DateFormat; import java.util.Arrays; import java.util.ArrayList; + import java.util.Collections; import java.util.Date; import java.util.HashMap; + import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; ! import java.util.Set; import sun.module.repository.RepositoryConfig; import sun.security.action.GetPropertyAction; import sun.tools.jar.CommandLine; /**
*** 77,92 **** private static final Map<String, Command> commands = new LinkedHashMap<String, Command>(); /** Usage message created from each command's usage. */ private static String usage = null; ! /** Format for module name & version. */ private static final String MAIFormat = "%-20s %-20s"; ! /** Format for additional/verbose module information. */ private static final String MAIFormatVerbose = " %-9s %-7s %-17s %s"; /** String containing column headings for name & version. */ private static final String maiHeading; /** String containing column headings for additional/verbose module information. */ private static final String maiHeadingVerbose; --- 82,103 ---- private static final Map<String, Command> commands = new LinkedHashMap<String, Command>(); /** Usage message created from each command's usage. */ private static String usage = null; ! /** Format for ModuleArchiveInfo name & version. */ private static final String MAIFormat = "%-20s %-20s"; ! /** Format for additional/verbose ModuleArchiveInfo details. */ private static final String MAIFormatVerbose = " %-9s %-7s %-17s %s"; + /** Format for ModuleDefinition name & version. */ + private static final String MDFormat = "%s-%s"; + + /** Format for additional/verbose ModuleDefinition details. */ + private static final String MDFormatVerbose = " %s"; + /** String containing column headings for name & version. */ private static final String maiHeading; /** String containing column headings for additional/verbose module information. */ private static final String maiHeadingVerbose;
*** 98,107 **** --- 109,124 ---- private static final Flag verboseFlag = new Flag('v'); /** Location of repository; if not given uses system repository. */ private static final RepositoryFlag repositoryFlag = new RepositoryFlag(); + /** Indicates dependencies command should display info on core modules. */ + private static final Flag javaseFlag = new Flag('j'); + + /** Provides way to specify platform binding fo dependencies command. */ + private static final BindingFlag bindingFlag = new BindingFlag(); + /** Contains the flags that are common to all commands. */ private static final HashMap<Character, Flag> commonFlags = new HashMap<Character, Flag>(); static { repositoryFlag.register(commonFlags);
*** 117,133 **** --- 134,155 ---- pw.printf(MAIFormat, "Name", "Version"); // XXX i18n pw.printf(MAIFormatVerbose, "Platform", "Arch", "Modified", "Filename"); // XXX i18n maiHeadingVerbose = sw.toString(); } + public JRepo(OutputStream out, OutputStream err, BufferedReader reader) { + this(new PrintStream(out), new PrintStream(err), reader); + } + public JRepo(PrintStream out, PrintStream err, BufferedReader reader) { msg = new Messenger("jrepo", out, err, reader); synchronized(commands) { if (commands.isEmpty()) { new ListCommand().register(commands); new InstallCommand().register(commands); new UninstallCommand().register(commands); + new DependenciesCommand().register(commands); } } reset(); }
*** 187,197 **** rc = Modules.newLocalRepository( "jrepo", f.getCanonicalFile(), null, RepositoryConfig.getSystemRepository()); } else { ! throw new IOException("Cannot access repository at " + repositoryLocation); } } } return rc; } --- 209,220 ---- rc = Modules.newLocalRepository( "jrepo", f.getCanonicalFile(), null, RepositoryConfig.getSystemRepository()); } else { ! throw new IOException("Cannot access repository at " // XXX i18n ! + repositoryLocation); } } } return rc; }
*** 260,270 **** return cmd; } /** Returns a user-grokkable description of the repository. */ ! private String getRepositoryText(Repository repo) { String rc; URI u = repo.getSourceLocation(); if (u == null) { rc = "Bootstrap repository"; } else { --- 283,293 ---- return cmd; } /** Returns a user-grokkable description of the repository. */ ! private static String getRepositoryText(Repository repo) { String rc; URI u = repo.getSourceLocation(); if (u == null) { rc = "Bootstrap repository"; } else {
*** 275,285 **** } } return rc; } ! private String getMAIText(ModuleArchiveInfo mai) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.printf(MAIFormat, mai.getName(), mai.getVersion()); if (verboseFlag.isEnabled()) { long t = mai.getLastModified(); --- 298,308 ---- } } return rc; } ! private static String getMAIText(ModuleArchiveInfo mai) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.printf(MAIFormat, mai.getName(), mai.getVersion()); if (verboseFlag.isEnabled()) { long t = mai.getLastModified();
*** 295,312 **** ); } return sw.toString(); } void usageError() { usageError(msg); } static void usageError(Messenger msg) { if (usage == null) { StringBuilder ub = new StringBuilder( ! "Usage: jrepo <command>\nwhere <command> includes:"); for (Command c : commands.values()) { String u = c.usage(); if (u != null) { ub.append("\n ").append(c.usage()); } --- 318,352 ---- ); } return sw.toString(); } + private static String getMText(Module m) { + return getMDText(m.getModuleDefinition()); + } + + private static String getMDText(ModuleDefinition md) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf(MDFormat, md.getName(), md.getVersion()); + if (verboseFlag.isEnabled()) { + pw.printf(MDFormatVerbose, + md.getRepository() == Repository.getBootstrapRepository() + ? "bootstrap" + : md.getRepository().getSourceLocation().toString()); + } + return sw.toString(); + } + void usageError() { usageError(msg); } static void usageError(Messenger msg) { if (usage == null) { StringBuilder ub = new StringBuilder( ! "Usage: jrepo <command>\nwhere <command> includes:"); // XXX i18n for (Command c : commands.values()) { String u = c.usage(); if (u != null) { ub.append("\n ").append(c.usage()); }
*** 317,327 **** } /** * Represents a flag given on the command line. Flags always are 2 * characters long, and start with a '-'. They can have additional ! * associated arguments (cf RepositoryFlag). */ private static class Flag { private final char name; private boolean enabled = false; --- 357,367 ---- } /** * Represents a flag given on the command line. Flags always are 2 * characters long, and start with a '-'. They can have additional ! * associated arguments (cf {@link #RepositoryFlag}). */ private static class Flag { private final char name; private boolean enabled = false;
*** 339,350 **** char getName() { return name; } ! /** @return the number of arguments consumed by this Flag. */ ! int set(String[] args, int pos) { enabled = true; return 1; } void reset() { --- 379,393 ---- char getName() { return name; } ! /** ! * @return the number of arguments consumed by this Flag ! * @throws IllegalArgumentException if invalid args are given ! */ ! int set(String[] args, int pos) throws IllegalArgumentException { enabled = true; return 1; } void reset() {
*** 365,390 **** RepositoryFlag() { super('r'); } ! int set(String[] args, int pos) { int rc = super.set(args, pos); location = args[pos + 1]; return rc + 1; } String getLocation() { return location; } void reset() { super.reset(); location = null; } } /* * Command types: An abstract base class, plus one concrete class for * each Command. */ --- 408,472 ---- RepositoryFlag() { super('r'); } ! @Override ! int set(String[] args, int pos) throws IllegalArgumentException { int rc = super.set(args, pos); location = args[pos + 1]; return rc + 1; } String getLocation() { return location; } + @Override void reset() { super.reset(); location = null; } } + private static class BindingFlag extends Flag { + String platform; + String arch; + + BindingFlag() { + super('b'); + } + + @Override + int set(String[] args, int pos) throws IllegalArgumentException { + int rc = super.set(args, pos); + String[] binding = args[pos + 1].split("-"); + if (binding.length != 2) { + throw new IllegalArgumentException( + "Must 2 and only 2 elements for platform-arch"); + } + platform = binding[0]; + arch = binding[1]; + return rc + 1; + } + + String getPlatform() { + return platform; + } + + String getArch() { + return arch; + } + + @Override + void reset() { + super.reset(); + platform = null; + arch = null; + } + } + /* * Command types: An abstract base class, plus one concrete class for * each Command. */
*** 428,438 **** if (f != null) { int numConsumed = f.set(args, i); i += numConsumed; // Increases at each iteration. rc += numConsumed; // Increases only when the arg is a flag. } else { ! throw new IllegalArgumentException("unrecognized flag: " + args[i]); } } else { i++; } } --- 510,521 ---- if (f != null) { int numConsumed = f.set(args, i); i += numConsumed; // Increases at each iteration. rc += numConsumed; // Increases only when the arg is a flag. } else { ! throw new IllegalArgumentException("unrecognized flag: " // XXX i18n ! + args[i]); } } else { i++; } }
*** 445,454 **** --- 528,538 ---- /** Returns a usage string describing this command, or null if the * command is a synonym for another command. */ abstract String usage(); + @Override public String toString() { return name; } /** * RepositoryVisitor types walk a parent chain of repositories, invoking * {@code doit} in each one. The abstract base class provides the recursion;
*** 457,469 **** * and the system repository is last. */ abstract class RepositoryVisitor { abstract void doit(Repository repo, Messenger msg); ! void doBefore(Messenger msg) { } ! void doAfter(Messenger msg) { } final void run(Repository repo, Messenger msg) { visit(repo, msg); } --- 541,553 ---- * and the system repository is last. */ abstract class RepositoryVisitor { abstract void doit(Repository repo, Messenger msg); ! void preVisit(Messenger msg) { } ! void postVisit(Messenger msg) { } final void run(Repository repo, Messenger msg) { visit(repo, msg); }
*** 470,486 **** private final void visit(Repository repo, Messenger msg) { Repository parent = parentFlag.isEnabled() ? repo.getParent() : null; if (parent != null) { visit(parent, msg); } ! doBefore(msg); doit(repo, msg); ! doAfter(msg); } } } /** Installs a JAM into a repository. */ private class InstallCommand extends Command { private String jamName; InstallCommand() { --- 554,741 ---- private final void visit(Repository repo, Messenger msg) { Repository parent = parentFlag.isEnabled() ? repo.getParent() : null; if (parent != null) { visit(parent, msg); } ! preVisit(msg); doit(repo, msg); ! postVisit(msg); } } } + + /** Lists dependencies of a module. */ + private class DependenciesCommand extends Command { + @SuppressWarnings("unchecked") + private final Map<Character, Flag> myFlags = (Map<Character, Flag>) commonFlags.clone(); + + private String name; + private Version version; + + // For printing module name, version. + private String moduleString; + + DependenciesCommand() { + super("dependencies"); + javaseFlag.register(myFlags); + bindingFlag.register(myFlags); + } + + @Override + void reset() { + javaseFlag.reset(); + bindingFlag.reset(); + } + + @Override + int parseFlags(String[] args, Map<Character, Flag> flags) { + return super.parseFlags(args, myFlags); + } + + boolean parseArgs(String[] args, Messenger msg) { + if (args.length > 0) { + name = args[0]; + } + if (args.length > 1) { + try { + version = Version.valueOf(args[1]); + } catch (IllegalArgumentException ex) { + return false; + } + } + if (args.length > 2) { + return false; + } + + if (DEBUG) debug("name: " + name + " ver: " + version + + " plat: " + bindingFlag.getPlatform() + + " arch: " + bindingFlag.getArch()); + return true; + } + + boolean run(Repository repo, Messenger msg) { + boolean rc = true; + if (name != null) { + VersionConstraint vc = (version == null + ? VersionConstraint.DEFAULT + : version.toVersionConstraint()); + printHeader(name, vc); + rc = depend(repo, name, vc, + bindingFlag.getPlatform(), bindingFlag.getArch()); + printTrailer(null); + } else { + for (ModuleArchiveInfo mai : repo.list()) { + reset(); + String maiName = mai.getName(); + VersionConstraint vc = mai.getVersion().toVersionConstraint(); + printHeader(maiName, vc); + rc &= depend(repo, maiName, vc, + mai.getPlatform(), mai.getArch()); + printTrailer("\n"); + } + } + return rc; + } + + boolean depend(Repository repo, String name, VersionConstraint constraint, + String platform, String arch) { + ImportTraverser traverser = new ImportTraverser(); + ImportTraverser.Visitor visitor = new ImportVisitor(traverser, msg); + try { + traverser.traverse(visitor, repo, name, constraint, platform, arch); + if (traverser.traversedAny()) { + return true; + } + if (verboseFlag.isEnabled()) { + msg.error("Cannot find module " + name + " in " // XXX i18n + + getRepositoryText(repo)); + } + return false; + } catch (ModuleInitializationException ex) { + msg.error("Cannot instantiate module for " + name // XXX i18n + + ": " + ex); + return false; + } + } + + + void printHeader(String name, VersionConstraint vc) { + if (verboseFlag.isEnabled()) { + msg.println("Dependencies for " // XXXi18n + + name + "-" + vc + ":"); + } + } + + void printTrailer(String s) { + if (verboseFlag.isEnabled()) { + msg.print(s); + } + } + + // TBD support platform binding. Ideally, want to allow specifying + // version, or binding, or both. + String usage() { + return "dependencies [-v] [-r repositoryLocation] [-b platform-arch]"// XXX i18n + + " [moduleName [moduleVersion] ]\n" + + " Lists all modules on which identified modules depend.\n" + + " If no moduleName is given, lists dependencies of all" + + " module archives in the repository\n" + + " which are instantiable on the current platform."; + } + } + + + private static class ImportVisitor extends ImportTraverser.Visitor { + private final Messenger msg; + + private static final String INDENT = " "; + private static final int INDENT_LENGTH = INDENT.length(); + + private String indent = ""; + + ImportVisitor(ImportTraverser traverser, Messenger msg) { + super(traverser); + this.msg = msg; + } + + @Override + protected void init(Module m) { + printModule(m); + } + + @Override + protected boolean preVisit(Module m) { + if (javaseFlag.isEnabled() == false + && m.getModuleDefinition().getName().startsWith("java.se")) { + return false; + } else { + indent += INDENT; + return true; + } + } + + @Override + protected void visit(Module m) { + printModule(m); + } + + @Override + protected void postVisit(Module m) { + if (javaseFlag.isEnabled() == false + && m.getModuleDefinition().getName().startsWith("java.se")) { + // empty + } else { + indent = indent.substring(INDENT_LENGTH); + } + } + + void printModule(Module m) { + msg.println(indent + getMText(m)); + } + } + /** Installs a JAM into a repository. */ private class InstallCommand extends Command { private String jamName; InstallCommand() {
*** 534,544 **** } return false; } String usage() { ! return "install [-v] -r repositoryLocation jamFile | jamURL\n" + " installs a module into a repository"; } } /** Uninstalls a module from a repository. */ --- 789,799 ---- } return false; } String usage() { ! return "install [-v] -r repositoryLocation jamFile | jamURL\n" // XXX i18n + " installs a module into a repository"; } } /** Uninstalls a module from a repository. */
*** 560,576 **** --- 815,833 ---- super("uninstall"); forceFlag.register(myFlags); interactiveFlag.register(myFlags); } + @Override void reset() { version = null; platformBinding = null; forceFlag.reset(); interactiveFlag.reset(); } + @Override int parseFlags(String[] args, Map<Character, Flag> flags) { return super.parseFlags(args, myFlags); } boolean parseArgs(String[] args, Messenger msg) {
*** 653,663 **** } return rc; } String usage() { ! return "uninstall [-v] [-f | -i] -r repositoryLocation moduleName [moduleVersion] [modulePlatformBinding]\n" + " removes a module from a repository, along with associated files."; } /** Uninstall the ModuleArchiveInfo from the Repository. */ private boolean uninstall(Repository repo, ModuleArchiveInfo mai, Messenger msg) { --- 910,921 ---- } return rc; } String usage() { ! return "uninstall [-v] [-f | -i] -r repositoryLocation moduleName"// XXX i18n ! + " [moduleVersion] [modulePlatformBinding]\n" + " removes a module from a repository, along with associated files."; } /** Uninstall the ModuleArchiveInfo from the Repository. */ private boolean uninstall(Repository repo, ModuleArchiveInfo mai, Messenger msg) {
*** 665,677 **** if (DEBUG) debug("Uninstalling " + getMAIText(mai)); try { rc = repo.uninstall(mai); if (verboseFlag.isEnabled()) { if (rc) { ! msg.println("Uninstalled " + getMAIText(mai)); } else { ! msg.error("Failed to uninstall " + getMAIText(mai)); } } } catch (Exception ex) { msg.error("Exception while uninstalling " + getInfo() + ": " + ex.getMessage()); --- 923,935 ---- if (DEBUG) debug("Uninstalling " + getMAIText(mai)); try { rc = repo.uninstall(mai); if (verboseFlag.isEnabled()) { if (rc) { ! msg.println("Uninstalled " + getMAIText(mai)); // XXX i18n } else { ! msg.error("Failed to uninstall " + getMAIText(mai)); // XXX i18n } } } catch (Exception ex) { msg.error("Exception while uninstalling " + getInfo() + ": " + ex.getMessage());
*** 775,788 **** --- 1033,1048 ---- ListCommand() { super("list"); parentFlag.register(myFlags); } + @Override void reset() { parentFlag.reset(); } + @Override int parseFlags(String[] args, Map<Character, Flag> flags) { return super.parseFlags(args, myFlags); } boolean parseArgs(String[] args, Messenger msg){
*** 801,820 **** ListRepositoryVisitor visitor = new ListRepositoryVisitor(); visitor.run(repo, msg); boolean found = visitor.wasFound(); if (verboseFlag.isEnabled() && !found) { if (moduleName != null) { ! msg.error("Could not find module name starting with '" + moduleName + "'"); } else { ! msg.error("Could not find any modules"); } } return found; } String usage() { ! return "list [-v] [-p] [-r repositoryLocation] moduleName\n" + " lists the modules in the repository"; } class ListRepositoryVisitor extends RepositoryVisitor { private boolean found = false; --- 1061,1083 ---- ListRepositoryVisitor visitor = new ListRepositoryVisitor(); visitor.run(repo, msg); boolean found = visitor.wasFound(); if (verboseFlag.isEnabled() && !found) { if (moduleName != null) { ! msg.error("Could not find module name starting with '"// ! // XXX i18n ! + moduleName + "'"); } else { ! msg.error("Could not find any modules"); // XXX i18n } } return found; } String usage() { ! return "list [-v] [-p] [-r repositoryLocation] moduleName\n"// ! // XXX i18n + " lists the modules in the repository"; } class ListRepositoryVisitor extends RepositoryVisitor { private boolean found = false;
*** 821,830 **** --- 1084,1098 ---- boolean wasFound() { return found; } void doit(Repository repo, Messenger msg) { boolean printedHeader = false; + List<ModuleArchiveInfo> maiList = repo.list(); + if (maiList.size() == 0 && verboseFlag.isEnabled()) { + msg.println(getRepositoryText(repo)); + msg.println(" empty"); + } else { for (ModuleArchiveInfo mai : repo.list()) { if (moduleName == null || mai.getName().startsWith(moduleName)) { if (!printedHeader) { msg.println(getRepositoryText(repo)); msg.println(verboseFlag.isEnabled() ? maiHeadingVerbose : maiHeading);
*** 832,840 **** --- 1100,1109 ---- } msg.println(getMAIText(mai)); found = true; } } + } } } } }