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

Print this page

        

*** 43,60 **** 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; /** --- 43,61 ---- import java.security.AccessController; import java.security.PrivilegedAction; import java.text.DateFormat; import java.util.Arrays; import java.util.ArrayList; ! import java.util.Comparator; 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 java.util.TreeSet; import sun.module.repository.RepositoryConfig; import sun.security.action.GetPropertyAction; import sun.tools.jar.CommandLine; /**
*** 112,130 **** 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); verboseFlag.register(commonFlags); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.printf(MAIFormat, "Name", "Version"); // XXX i18n maiHeading = sw.toString(); --- 113,132 ---- private static final RepositoryFlag repositoryFlag = new RepositoryFlag(); /** Indicates dependencies command should display info on core modules. */ private static final Flag javaseFlag = new Flag('j'); ! /** Causes an individual command to print help and exit. */ ! private static final Flag helpFlag = new Flag('h'); /** Contains the flags that are common to all commands. */ private static final HashMap<Character, Flag> commonFlags = new HashMap<Character, Flag>(); static { repositoryFlag.register(commonFlags); verboseFlag.register(commonFlags); + helpFlag.register(commonFlags); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.printf(MAIFormat, "Name", "Version"); // XXX i18n maiHeading = sw.toString();
*** 142,155 **** 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(); } --- 144,159 ---- public JRepo(PrintStream out, PrintStream err, BufferedReader reader) { msg = new Messenger("jrepo", out, err, reader); synchronized(commands) { if (commands.isEmpty()) { ! new DependenciesCommand().register(commands); new InstallCommand().register(commands); + new HelpCommand().register(commands); + new ListCommand().register(commands); new UninstallCommand().register(commands); ! new ValidateCommand().register(commands); } } reset(); }
*** 168,177 **** --- 172,186 ---- if (DEBUG && cmd != null) debug("running " + cmd); if (cmd == null) { return false; } + if (helpFlag.isEnabled()) { + cmd.usageError(msg); + return true; + } + Repository repo = null; try { repo = getRepository(); repo.shutdownOnExit(true); } catch (IOException ex) {
*** 223,232 **** --- 232,242 ---- private void reset() { moduleName = null; parentFlag.reset(); repositoryFlag.reset(); verboseFlag.reset(); + helpFlag.reset(); for (Command cmd : commands.values()) { cmd.reset(); } }
*** 262,305 **** return null; } try { int numFlags = cmd.parseFlags(args, commonFlags); args = Arrays.copyOfRange(args, numFlags + 1, args.length); try { if (cmd.parseArgs(args, msg)) { return cmd; } else { ! usageError(); return null; } } catch (ArrayIndexOutOfBoundsException e) { usageError(); } } catch (IllegalArgumentException ex) { msg.error(ex.getMessage()); ! usageError(); return null; } 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 { - try { - rc = "Repository " + u.toURL().toExternalForm(); - } catch (MalformedURLException ex) { - rc = "Repository unknown"; - } - } - */ rc = "[" + repo.toString() + "]"; return rc; } --- 272,308 ---- return null; } try { int numFlags = cmd.parseFlags(args, commonFlags); + if (helpFlag.isEnabled()) { + return cmd; + } + args = Arrays.copyOfRange(args, numFlags + 1, args.length); try { if (cmd.parseArgs(args, msg)) { return cmd; } else { ! cmd.usageError(msg); return null; } } catch (ArrayIndexOutOfBoundsException e) { usageError(); } } catch (IllegalArgumentException ex) { msg.error(ex.getMessage()); ! cmd.usageError(msg); return null; } return cmd; } /** Returns a user-grokkable description of the repository. */ private static String getRepositoryText(Repository repo) { String rc; rc = "[" + repo.toString() + "]"; return rc; }
*** 331,343 **** 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()); md.getRepository().getName()); } return sw.toString(); } --- 334,343 ----
*** 430,476 **** 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. */ --- 430,439 ----
*** 502,512 **** /** * Parse the Flags for this command. * @return number of flags found. * @throws IllegalArgumentException if an invalid flag is given. */ ! int parseFlags(String[] args, Map<Character, Flag> flags) { int rc = 0; int i = 0; while (i < args.length) { String s = args[i]; if (s.length() == 2 && s.charAt(0) == '-') { --- 465,475 ---- /** * Parse the Flags for this command. * @return number of flags found. * @throws IllegalArgumentException if an invalid flag is given. */ ! /* int parseFlags(String[] args, Map<Character, Flag> flags) { int rc = 0; int i = 0; while (i < args.length) { String s = args[i]; if (s.length() == 2 && s.charAt(0) == '-') {
*** 517,537 **** rc += numConsumed; // Increases only when the arg is a flag. } else { throw new IllegalArgumentException("unrecognized flag: " // XXX i18n + args[i]); } } else { i++; } } return rc; } /** Represents the actual behavior of the command. */ abstract boolean run(Repository repo, Messenger msg); ! /** Returns a usage string describing this command, or null if the * command is a synonym for another command. */ abstract String usage(); @Override --- 480,536 ---- rc += numConsumed; // Increases only when the arg is a flag. } else { throw new IllegalArgumentException("unrecognized flag: " // XXX i18n + args[i]); } + } if (s.charAt(0) == '-') { + throw new IllegalArgumentException("invalid flag: " // XXX i18n + + args[i]); } else { i++; } } return rc; } + */ + int parseFlags(String[] args, Map<Character, Flag> flags) { + int rc = 0; + int i = 0; + while (i < args.length) { + String s = args[i]; + if (s.charAt(0) == '-') { + if (s.length() == 2) { + Flag f = flags.get(s.charAt(1)); + 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 { + throw new IllegalArgumentException("invalid flag: " // XXX i18n + + args[i]); + } + } else { + i++; + } + } + return rc; + } /** Represents the actual behavior of the command. */ abstract boolean run(Repository repo, Messenger msg); ! /** Prints command-specific usage message. */ ! void usageError(Messenger msg) { ! msg.error("Synopsis for " + name + ": \n" + usage()); ! } ! ! /** ! *Returns a usage string describing this command, or null if the * command is a synonym for another command. */ abstract String usage(); @Override
*** 580,596 **** 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); --- 579,593 ----
*** 609,621 **** } 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; --- 606,616 ---- } if (args.length > 2) { return false; } ! if (DEBUG) debug("name: " + name + " ver: " + version); return true; } boolean run(Repository repo, Messenger msg) { boolean rc = true;
*** 622,654 **** 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 --- 617,646 ---- if (name != null) { VersionConstraint vc = (version == null ? VersionConstraint.DEFAULT : version.toVersionConstraint()); printHeader(name, vc); ! rc = depend(repo, name, vc); 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); printTrailer("\n"); } } return rc; } ! boolean depend(Repository repo, String name, VersionConstraint constraint) { ImportTraverser traverser = new ImportTraverser(); ImportTraverser.Visitor visitor = new ImportVisitor(traverser, msg); try { ! traverser.traverse(visitor, repo, name, constraint); if (traverser.traversedAny()) { return true; } if (verboseFlag.isEnabled()) { msg.error("Cannot find module " + name + " in " // XXX i18n
*** 675,686 **** msg.print(s); } } 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."; } --- 667,678 ---- msg.print(s); } } String usage() { ! // XXX i18n ! return "dependencies [-v] [-r repositoryLocation] [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."; }
*** 734,751 **** --- 726,784 ---- void printModule(Module m) { msg.println(indent + getMText(m)); } } + + /** Prints help. */ + private class HelpCommand extends Command { + HelpCommand() { + super("help"); + } + + boolean parseArgs(String[] args, Messenger msg) { + return true; + } + + boolean run(Repository repo, Messenger msg) { + JRepo.this.usageError(msg); + return true; + } + + String usage() { + return "help\n Prints brief help text for all commands.\n" + + " Each command allows a -h option which gives help for that command."; + } + } + + /** Installs a JAM into a repository. */ private class InstallCommand extends Command { + @SuppressWarnings("unchecked") + private final Map<Character, Flag> myFlags = (Map<Character, Flag>) commonFlags.clone(); + + /** When used, prevents checking of installed module's dependencies. */ + private Flag quickInstallFlag = new Flag('q'); + private String jamName; InstallCommand() { super("install"); + quickInstallFlag.register(myFlags); } + @Override + void reset() { + jamName = null; + quickInstallFlag.reset(); + } + + @Override + int parseFlags(String[] args, Map<Character, Flag> flags) { + return super.parseFlags(args, myFlags); + } + boolean parseArgs(String[] args, Messenger msg) { boolean rc = false; if (!parentFlag.isEnabled() && repositoryFlag.getLocation() != null && args.length == 1) {
*** 778,788 **** --- 811,841 ---- try { ModuleArchiveInfo mai = repo.install(new URL(jamURL).toURI()); if (verboseFlag.isEnabled()) { msg.println("Installed " + jamName + ": " + getMAIText(mai)); } + if (!quickInstallFlag.isEnabled()) { + ModuleDefinition md = repo.find( + mai.getName(), mai.getVersion().toVersionConstraint()); + if (md == null) { + msg.error("Warning: " + jamName + + " was installed but cannot be found"); + } else { + try { + Module m = md.getModuleInstance(); + } catch (ModuleInitializationException ex) { + msg.error("Cannot install " + ex.getMessage()); + if (!repo.uninstall(mai)) { + msg.error("Could not uninstall " + mai); + } + return false; + } + } + } return true; + } catch (IllegalStateException ex) { + msg.error("Cannot install " + jamName + ": " + ex.getMessage()); } catch (URISyntaxException ex) { msg.error("Cannot install " + jamName + ": no such file, or malformed URI"); } catch (MalformedURLException ex) { msg.error("Cannot install " + jamName + ": no such file, or malformed URL"); } catch (IOException ex) {
*** 791,802 **** } 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. */ private class UninstallCommand extends Command { --- 844,855 ---- } return false; } String usage() { ! return "install [-v] [-q] -r repositoryLocation jamFile | jamURL\n" // XXX i18n ! + " Installs a module into a repository."; } } /** Uninstalls a module from a repository. */ private class UninstallCommand extends Command {
*** 914,924 **** } 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) { boolean rc = false; --- 967,977 ---- } 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) { boolean rc = false;
*** 1025,1034 **** --- 1078,1141 ---- } return s; } } + /** Provides a way to sort ModuleArchiveInfo instances. */ + static class MAIComparator implements Comparator<ModuleArchiveInfo> { + private static final MAIComparator instance = new MAIComparator(); + + private MAIComparator() { } + + static MAIComparator getInstance() { + return instance; + } + + public int compare(ModuleArchiveInfo o1, ModuleArchiveInfo o2) { + int rc = o1.getName().compareTo(o2.getName()); + if (rc != 0) { + return rc; + } + + rc = o1.getVersion().compareTo(o2.getVersion()); + if (rc != 0) { + return rc; + } + + rc = compareStrings(o1.getPlatform(), o2.getPlatform()); + if (rc != 0) { + return rc; + } + + return compareStrings(o1.getArch(), o2.getArch()); + } + + // Compare two Strings. If neither is null, compare them + // lexicographically. If both are null, return 0. If the first is + // null, return -1; else 1. + private int compareStrings(String s1, String s2) { + int rc = 0; + if (s2 != null && s2 != null) { + rc = s1.compareTo(s2); + if (rc != 0) { + return rc; + } + } + if (s1 == null) { + return -1; + } else if (s2 == null) { + return 1; + } + return 0; + } + + @Override + public boolean equals(Object o) { + return this == o; + } + } + /** Prints information about modules found in repositories. */ private class ListCommand extends Command { @SuppressWarnings("unchecked") private final Map<Character, Flag> myFlags = (Map<Character, Flag>) commonFlags.clone();
*** 1073,1084 **** } 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; --- 1180,1192 ---- } return found; } String usage() { ! return "list [-v] [-p] [-r repositoryLocation] [moduleName]\n"// XXX i18n ! + " Lists the modules in the repository that match the given name.\n" ! + " If no moduleName is given, lists all modules in the repository."; } class ListRepositoryVisitor extends RepositoryVisitor { private boolean found = false;
*** 1089,1099 **** 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); printedHeader = true; --- 1197,1210 ---- List<ModuleArchiveInfo> maiList = repo.list(); if (maiList.size() == 0 && verboseFlag.isEnabled()) { msg.println(getRepositoryText(repo)); msg.println(" empty"); } else { ! TreeSet<ModuleArchiveInfo> sorted = ! new TreeSet<ModuleArchiveInfo>(MAIComparator.getInstance()); ! sorted.addAll(repo.list()); ! for (ModuleArchiveInfo mai : sorted) { if (moduleName == null || mai.getName().startsWith(moduleName)) { if (!printedHeader) { msg.println(getRepositoryText(repo)); msg.println(verboseFlag.isEnabled() ? maiHeadingVerbose : maiHeading); printedHeader = true;
*** 1104,1109 **** --- 1215,1331 ---- } } } } } + + /** Runs shallow and/or deep validation on one or more modules. */ + class ValidateCommand extends Command { + @SuppressWarnings("unchecked") + private final Map<Character, Flag> myFlags = (Map<Character, Flag>) commonFlags.clone(); + + /** Indicates that deep validation should be run. */ + private Flag deepValidateFlag = new Flag('d'); + + private String name; + private Version version; + + ValidateCommand() { + super("validate"); + deepValidateFlag.register(myFlags); + } + + @Override + void reset() { + deepValidateFlag.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); + return true; + } + + boolean run(Repository repo, Messenger msg) { + boolean rc = true; + if (name != null) { + VersionConstraint vc = (version == null + ? VersionConstraint.DEFAULT + : version.toVersionConstraint()); + + List<ModuleDefinition> mdList = repo.find(Query.module(name, vc)); + if (mdList.size() == 1) { + rc = validate(mdList.get(0), msg); + } else { + throw new IllegalArgumentException( + "more than one matching module found for name=" + name + + " version=" + vc); + } + } else { + for (ModuleDefinition md : repo.findAll()) { + rc &= validate(md, msg); + } + } + return rc; + } + + /** @return true if the module passes validation validation. */ + boolean validate(ModuleDefinition md, Messenger msg) { + boolean rc = false; + try { + Module m = md.getModuleInstance(); + if (deepValidateFlag.isEnabled()) { + if (m.supportsDeepValidation()) { + try { + m.deepValidate(); + if (verboseFlag.isEnabled()) { + msg.println( + "Module " + m + " passed deep validation"); // XXX i18n + } + rc = true; + } catch (ModuleInitializationException ex) { + msg.error( + "Module " + m + " failed deep validation"); // XXX i18n + } + } + } else { + // Module was instantiated => passed shallow validation + if (verboseFlag.isEnabled()) { + msg.println( + "Module " + m + " passed shallow validation"); // XXX i18n + } + rc = true; + } + } catch (ModuleInitializationException ex) { + msg.error("Could not initialize module for " + md // XXX i18n + + ": " + ex.getMessage()); + } + return rc; + } + + String usage() { + // XXX i18n + return "validate [-v] [-d] [-r repositoryLocation] [moduleName [moduleVersion] ]\n" + + " Runs deep validation on the identified modules.\n" + + " If no moduleName is given, validates all module" + + " archives in the repository.\n"; + } + } }