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;
}
}
+ }
}
}
}
}