--- old/src/share/classes/sun/module/repository/RepositoryConfig.java Wed Aug 6 09:30:39 2008
+++ new/src/share/classes/sun/module/repository/RepositoryConfig.java Wed Aug 6 09:30:39 2008
@@ -34,7 +34,6 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.module.Modules;
-import java.module.ModuleSystemPermission;
import java.module.Repository;
import java.net.MalformedURLException;
import java.net.URI;
@@ -142,20 +141,10 @@
/**
* Sets the application repository.
* @param r {@code Repository} that will be the application repository
- * SecurityException if a security manager exists and its
- * checkPermission method denies access to shutdown the
- * repository.
* @throws IllegalArgumentException if the application repository has already
* been set via this method.
- * @throws SecurityException if a security manager exists and its
- * {@code checkPermission} method denies access to set the system
- * repository.
*/
public static void setApplicationRepository(Repository r) throws IllegalArgumentException {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(new ModuleSystemPermission("setApplicationRepository"));
- }
if (applicationRepositoryWasSet) {
throw new IllegalArgumentException("Application repository is already set.");
} else {
--- old/src/share/classes/sun/module/tools/JRepo.java Wed Aug 6 09:30:41 2008
+++ new/src/share/classes/sun/module/tools/JRepo.java Wed Aug 6 09:30:41 2008
@@ -45,7 +45,7 @@
import java.text.DateFormat;
import java.util.Arrays;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -53,6 +53,7 @@
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;
@@ -114,8 +115,8 @@
/** 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();
+ /** 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 commonFlags = new HashMap();
@@ -123,6 +124,7 @@
static {
repositoryFlag.register(commonFlags);
verboseFlag.register(commonFlags);
+ helpFlag.register(commonFlags);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
@@ -144,10 +146,12 @@
msg = new Messenger("jrepo", out, err, reader);
synchronized(commands) {
if (commands.isEmpty()) {
- new ListCommand().register(commands);
+ new DependenciesCommand().register(commands);
new InstallCommand().register(commands);
+ new HelpCommand().register(commands);
+ new ListCommand().register(commands);
new UninstallCommand().register(commands);
- new DependenciesCommand().register(commands);
+ new ValidateCommand().register(commands);
}
}
reset();
@@ -170,6 +174,11 @@
return false;
}
+ if (helpFlag.isEnabled()) {
+ cmd.usageError(msg);
+ return true;
+ }
+
Repository repo = null;
try {
repo = getRepository();
@@ -225,6 +234,7 @@
parentFlag.reset();
repositoryFlag.reset();
verboseFlag.reset();
+ helpFlag.reset();
for (Command cmd : commands.values()) {
cmd.reset();
}
@@ -264,12 +274,16 @@
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 {
- usageError();
+ cmd.usageError(msg);
return null;
}
} catch (ArrayIndexOutOfBoundsException e) {
@@ -277,7 +291,7 @@
}
} catch (IllegalArgumentException ex) {
msg.error(ex.getMessage());
- usageError();
+ cmd.usageError(msg);
return null;
}
return cmd;
@@ -287,17 +301,6 @@
/** 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;
@@ -333,9 +336,6 @@
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();
@@ -432,43 +432,6 @@
}
}
- 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.
@@ -504,7 +467,7 @@
* @return number of flags found.
* @throws IllegalArgumentException if an invalid flag is given.
*/
- int parseFlags(String[] args, Map flags) {
+/* int parseFlags(String[] args, Map flags) {
int rc = 0;
int i = 0;
while (i < args.length) {
@@ -519,6 +482,9 @@
throw new IllegalArgumentException("unrecognized flag: " // XXX i18n
+ args[i]);
}
+ } if (s.charAt(0) == '-') {
+ throw new IllegalArgumentException("invalid flag: " // XXX i18n
+ + args[i]);
} else {
i++;
}
@@ -525,11 +491,44 @@
}
return rc;
}
+*/
+ int parseFlags(String[] args, Map 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);
- /** Returns a usage string describing this command, or null if the
+ /** 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();
@@ -582,13 +581,11 @@
DependenciesCommand() {
super("dependencies");
javaseFlag.register(myFlags);
- bindingFlag.register(myFlags);
}
@Override
void reset() {
javaseFlag.reset();
- bindingFlag.reset();
}
@Override
@@ -611,9 +608,7 @@
return false;
}
- if (DEBUG) debug("name: " + name + " ver: " + version
- + " plat: " + bindingFlag.getPlatform()
- + " arch: " + bindingFlag.getArch());
+ if (DEBUG) debug("name: " + name + " ver: " + version);
return true;
}
@@ -624,8 +619,7 @@
? VersionConstraint.DEFAULT
: version.toVersionConstraint());
printHeader(name, vc);
- rc = depend(repo, name, vc,
- bindingFlag.getPlatform(), bindingFlag.getArch());
+ rc = depend(repo, name, vc);
printTrailer(null);
} else {
for (ModuleArchiveInfo mai : repo.list()) {
@@ -633,8 +627,7 @@
String maiName = mai.getName();
VersionConstraint vc = mai.getVersion().toVersionConstraint();
printHeader(maiName, vc);
- rc &= depend(repo, maiName, vc,
- mai.getPlatform(), mai.getArch());
+ rc &= depend(repo, maiName, vc);
printTrailer("\n");
}
}
@@ -641,12 +634,11 @@
return rc;
}
- boolean depend(Repository repo, String name, VersionConstraint constraint,
- String platform, String arch) {
+ 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, platform, arch);
+ traverser.traverse(visitor, repo, name, constraint);
if (traverser.traversedAny()) {
return true;
}
@@ -677,8 +669,8 @@
}
String usage() {
- return "dependencies [-v] [-r repositoryLocation] [-b platform-arch]"// XXX i18n
- + " [moduleName [moduleVersion] ]\n"
+ // 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"
@@ -735,15 +727,56 @@
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 myFlags = (Map) 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 flags) {
+ return super.parseFlags(args, myFlags);
+ }
+
boolean parseArgs(String[] args, Messenger msg) {
boolean rc = false;
if (!parentFlag.isEnabled()
@@ -780,7 +813,27 @@
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) {
@@ -793,8 +846,8 @@
}
String usage() {
- return "install [-v] -r repositoryLocation jamFile | jamURL\n" // XXX i18n
- + " installs a module into a repository";
+ return "install [-v] [-q] -r repositoryLocation jamFile | jamURL\n" // XXX i18n
+ + " Installs a module into a repository.";
}
}
@@ -916,7 +969,7 @@
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.";
+ + " Removes a module from a repository, along with associated files.";
}
/** Uninstall the ModuleArchiveInfo from the Repository. */
@@ -1027,6 +1080,60 @@
}
}
+ /** Provides a way to sort ModuleArchiveInfo instances. */
+ static class MAIComparator implements Comparator {
+ 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")
@@ -1075,8 +1182,9 @@
}
String usage() {
- return "list [-v] [-p] [-r repositoryLocation] moduleName\n"// XXX i18n
- + " lists the modules in the repository";
+ 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 {
@@ -1091,7 +1199,10 @@
msg.println(getRepositoryText(repo));
msg.println(" empty");
} else {
- for (ModuleArchiveInfo mai : repo.list()) {
+ TreeSet sorted =
+ new TreeSet(MAIComparator.getInstance());
+ sorted.addAll(repo.list());
+ for (ModuleArchiveInfo mai : sorted) {
if (moduleName == null || mai.getName().startsWith(moduleName)) {
if (!printedHeader) {
msg.println(getRepositoryText(repo));
@@ -1106,4 +1217,115 @@
}
}
}
+
+ /** Runs shallow and/or deep validation on one or more modules. */
+ class ValidateCommand extends Command {
+ @SuppressWarnings("unchecked")
+ private final Map myFlags = (Map) 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 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 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";
+ }
+ }
}
--- old/test/java/module/modinit/JRepoDependenciesTest.java Wed Aug 6 09:30:42 2008
+++ new/test/java/module/modinit/JRepoDependenciesTest.java Wed Aug 6 09:30:42 2008
@@ -28,7 +28,6 @@
/**
* @test
- * @library ../tools ../tools/jrepo
* @compile -XDignore.symbol.file
* RunMTest.java
* classp/MainX.java
@@ -131,7 +130,7 @@
}
protected void runTest(RunMTest mTest) throws Exception {
- Repository parent = sun.module.repository.RepositoryConfig.getSystemRepository();
+ Repository parent = sun.module.repository.RepositoryConfig.getApplicationRepository();
Repository repository = Modules.newLocalRepository(
mTest.getName(), mTest.outputDirectory, null, parent);
--- /dev/null Wed Aug 6 09:30:38 2008
+++ new/test/java/module/modinit/JRepoInstallTest.java Wed Aug 6 09:30:43 2008
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.module.*;
+import java.util.*;
+import sun.module.JamUtils;
+import sun.module.tools.JRepo;
+
+/**
+ * @test
+ * @compile -XDignore.symbol.file
+ * RunMTest.java
+ * classp/MainX.java
+ * JRepoInstallTest.java
+ * @run main/othervm
+ * -DTestDescriptionFactory.classname=JRepoInstallTest$MyFactory
+ * JRepoInstallTest
+ */
+public class JRepoInstallTest {
+ private static final boolean debug = Boolean.getBoolean("module.tools.debug");
+
+ private static final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ private static final PrintStream resultStream = new PrintStream(baos);
+
+ private static final String[] tests = {
+ "basic/import.mtest",
+ };
+
+
+ public static void realMain(String args[]) throws Throwable {
+ RunMTest.main(tests);
+ }
+
+ /** Return an array of Strings from the given String. */
+ static String[] getArgs(String s) {
+ List args = new ArrayList();
+ StringTokenizer st = new StringTokenizer(s);
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (debug) System.err.println("adding arg " + token);
+ args.add(token);
+ }
+ if (debug) System.err.println("args length is " + args.size());
+ return args.toArray(new String[0]);
+ }
+
+ public static class MyFactory extends RunMTest.TestDescriptionFactory {
+
+ protected RunMTest.TestDescription doCreate(String name) {
+ return new MyTestDescription(name);
+ }
+ }
+
+ public static class MyTestDescription extends RunMTest.TestDescription {
+ MyTestDescription(String name) {
+ super(name);
+ }
+
+ protected void runTest(RunMTest mTest) throws Exception {
+ if (name.equals("m2")) {
+ // Only run this for m1.
+ return;
+ }
+
+ // Enables shadow file copies in the repository if we're running
+ // on Windows. This is to prevent file locking in the source
+ // location.
+ if (System.getProperty("os.platform").equalsIgnoreCase("windows")) {
+ System.setProperty("java.module.repository.shadowcopyfiles", "true");
+ }
+
+ Repository parent = sun.module.repository.RepositoryConfig.getApplicationRepository();
+ Repository repository = Modules.newLocalRepository(
+ mTest.getName(), mTest.outputDirectory, null, parent);
+
+ ModuleArchiveInfo[] maiList = new ModuleArchiveInfo[2];
+ for (ModuleArchiveInfo mai : repository.list()) {
+ if (mai.getName().equals("m1")) {
+ maiList[0] = mai;
+ } else if (mai.getName().equals("m2")) {
+ maiList[1] = mai;
+ }
+ }
+
+ JRepo jr = new JRepo(new PrintStream(System.out), resultStream, null);
+
+ // An mtest's initial repository has modules already installed.
+ // Since here we test installation itself, do so in a new
+ // repository.
+ File repoDir = new File(mTest.outputDirectory, "installA");
+ check(JamUtils.recursiveDelete(repoDir));
+ check(repoDir.mkdirs());
+ repository = Modules.newLocalRepository(
+ mTest.getName() + "installA", repoDir, null, parent);
+
+ // Install m1 with the -q flag, which should succeed even though
+ // m2 is not installed.
+ try {
+ check(jr.run(getArgs(
+ "install -q -r "
+ + repoDir.getAbsolutePath() + " "
+ + maiList[0].getFileName())));
+ pass();
+ } catch (Throwable t) {
+ unexpected(t);
+ }
+
+ // In a new repository, install m2 then m1: this should work:
+ repoDir = new File(mTest.outputDirectory, "installB");
+ check(JamUtils.recursiveDelete(repoDir));
+ check(repoDir.mkdirs());
+ repository = Modules.newLocalRepository(
+ mTest.getName() + "installB", repoDir, null, parent);
+ ModuleArchiveInfo maiM2 = repository.install(
+ new File(maiList[1].getFileName()).toURI());
+ check(maiM2 != null);
+ try {
+ check(jr.run(getArgs(
+ "install -r "
+ + repoDir.getAbsolutePath() + " "
+ + maiList[0].getFileName())));
+ pass();
+ } catch (Throwable t) {
+ unexpected(t);
+ }
+
+ // In a new repository, install m1 without the -q flag: this
+ // should fail
+ repoDir = new File(mTest.outputDirectory, "installC");
+ check(JamUtils.recursiveDelete(repoDir));
+ check(repoDir.mkdirs());
+ repository = Modules.newLocalRepository(
+ mTest.getName() + "installC", repoDir, null, parent);
+ try {
+ check(false == jr.run(getArgs(
+ "install -r "
+ + repoDir.getAbsolutePath() + " "
+ + maiList[0].getFileName())));
+ checkOutput("no module definition in the repository can satisfy the import dependency ModuleDependency");
+ } catch (Throwable t) {
+ pass();
+ }
+ }
+
+ static void checkOutput(String expected) {
+ String actual = baos.toString();
+ check(actual.contains(expected));
+ baos.reset();
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static boolean pass() {passed++; return true;}
+ static boolean fail() {failed++; Thread.dumpStack(); return false;}
+ static boolean fail(String msg) {System.err.println(msg); return fail();}
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
+ static boolean equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) return pass();
+ else return fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.println("\nPassed = " + passed + " failed = " + failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Wed Aug 6 09:30:39 2008
+++ new/test/java/module/modinit/JRepoValidateTest.java Wed Aug 6 09:30:44 2008
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.module.*;
+import java.util.*;
+import sun.module.JamUtils;
+import sun.module.tools.JRepo;
+
+/**
+ * @test
+ * @compile -XDignore.symbol.file
+ * RunMTest.java
+ * classp/MainX.java
+ * JRepoValidateTest.java
+ * @run main/othervm
+ * -DTestDescriptionFactory.classname=JRepoValidateTest$MyFactory
+ * JRepoValidateTest
+ */
+public class JRepoValidateTest {
+ private static final boolean debug = Boolean.getBoolean("module.tools.debug");
+
+ private static final ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
+ private static final PrintStream outStream = new PrintStream(outBytes);
+ private static final ByteArrayOutputStream errBytes = new ByteArrayOutputStream();
+ private static final PrintStream errStream = new PrintStream(errBytes);
+
+ private static final String[] tests = {
+ "basic/import.mtest",
+ };
+
+
+ public static void realMain(String args[]) throws Throwable {
+ RunMTest.main(tests);
+ }
+
+ /** Return an array of Strings from the given String. */
+ static String[] getArgs(String s) {
+ List args = new ArrayList();
+ StringTokenizer st = new StringTokenizer(s);
+ while (st.hasMoreTokens()) {
+ String token = st.nextToken();
+ if (debug) System.err.println("adding arg " + token);
+ args.add(token);
+ }
+ if (debug) System.err.println("args length is " + args.size());
+ return args.toArray(new String[0]);
+ }
+
+ public static class MyFactory extends RunMTest.TestDescriptionFactory {
+
+ protected RunMTest.TestDescription doCreate(String name) {
+ return new MyTestDescription(name);
+ }
+ }
+
+ public static class MyTestDescription extends RunMTest.TestDescription {
+ MyTestDescription(String name) {
+ super(name);
+ }
+
+ protected void runTest(RunMTest mTest) throws Exception {
+ if (name.equals("m2")) {
+ // Only run this for m1.
+ return;
+ }
+
+ Repository parent = sun.module.repository.RepositoryConfig.getApplicationRepository();
+ Repository repository = Modules.newLocalRepository(
+ mTest.getName(), mTest.outputDirectory, null, parent);
+
+ ModuleArchiveInfo[] maiList = new ModuleArchiveInfo[2];
+
+ for (ModuleArchiveInfo mai : repository.list()) {
+ if (mai.getName().equals("m1")) {
+ maiList[0] = mai;
+ } else if (mai.getName().equals("m2")) {
+ maiList[1] = mai;
+ }
+ }
+
+ JRepo jr = new JRepo(outStream, errStream, null);
+
+ // Check deep validation on module m1 which imports m2
+ try {
+ check(jr.run(getArgs(
+ "validate -d -v -r "
+ + mTest.outputDirectory.getAbsolutePath() + " "
+ + maiList[0].getName())));
+ checkOutput("passed deep validation", outBytes);
+ } catch (Throwable t) {
+ unexpected(t);
+ }
+
+ // Check shallow validation on module m1 which imports m2
+ try {
+ check(jr.run(getArgs(
+ "validate -v -r "
+ + mTest.outputDirectory.getAbsolutePath() + " "
+ + maiList[0].getName())));
+ checkOutput("passed shallow validation", outBytes);
+ } catch (Throwable t) {
+ unexpected(t);
+ }
+
+ // Install m1 into a new repository, and validate, expecting failure
+ File repoDir = new File(mTest.outputDirectory, "validateA");
+ check(JamUtils.recursiveDelete(repoDir));
+ check(repoDir.mkdirs());
+ repository = Modules.newLocalRepository(
+ mTest.getName() + "validateA", repoDir, null, parent);
+ check(repository.install(
+ new File(maiList[0].getFileName()).toURI()) != null);
+ try {
+ check(false == jr.run(getArgs(
+ "validate -d -r "
+ + repoDir.getAbsolutePath() + " "
+ + maiList[0].getName())));
+ checkOutput("no module definition in the repository can satisfy the import dependency ModuleDependency", errBytes);
+ } catch (Throwable t) {
+ unexpected(t);
+ }
+ }
+
+ static void checkOutput(String expected, ByteArrayOutputStream baos) {
+ String actual = baos.toString();
+ if (!check(actual.contains(expected))) {
+ System.err.println(
+ "Got\n'" + actual + "'\nbut expected\n'" + expected + "'");
+ }
+ // Reset both streams after checking either one.
+ outBytes.reset();
+ errBytes.reset();
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static boolean pass() {passed++; return true;}
+ static boolean fail() {failed++; Thread.dumpStack(); return false;}
+ static boolean fail(String msg) {System.err.println(msg); return fail();}
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
+ static boolean equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) return pass();
+ else return fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.println("\nPassed = " + passed + " failed = " + failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- old/test/java/module/repository/LocalRepositoryTest.java Wed Aug 6 09:30:46 2008
+++ new/test/java/module/repository/LocalRepositoryTest.java Wed Aug 6 09:30:45 2008
@@ -68,11 +68,12 @@
}
public static void realMain(String[] args) throws Throwable {
+ boolean onWindows = System.getProperty("os.platform").equalsIgnoreCase("windows");
// Enables shadow file copies in the repository if we're running
// on Windows. This is to prevent file locking in the
// source location.
- if (System.getProperty("os.platform").equalsIgnoreCase("windows")) {
+ if (onWindows) {
System.setProperty("java.module.repository.shadowcopyfiles", "true");
}
@@ -177,7 +178,11 @@
repo.reload();
if (readOnlyChangeOK) {
-// check(repo.isReadOnly());
+ if (!onWindows) {
+ // I/O APIs are not completely honest about writability of
+ // directories on Windows; see 4939819 and 6728842.
+ check(repo.isReadOnly());
+ }
}
// Check initial module is installed
--- old/test/java/module/tools/jrepo/JRepoTest.java Wed Aug 6 09:30:47 2008
+++ new/test/java/module/tools/jrepo/JRepoTest.java Wed Aug 6 09:30:47 2008
@@ -49,7 +49,7 @@
*/
check(!jr.run(new String[] {" "}) && usageOK(0));
check(!jr.run(getArgs("notASubCcommand")) && usageOK(0));
- check(!jr.run(getArgs("list -+")) && usageOK(1));
+ check(!jr.run(getArgs("list -+")) && usageOK(-5));
/*
* Do many tests on a LocalRepository, then a few on a URLRepository
@@ -69,10 +69,10 @@
/* Check install command */
- check(!jr.run(getArgs("install")) && usageOK(0));
- check(!jr.run(getArgs("install repo module")) && usageOK(0));
+ check(!jr.run(getArgs("install")) && usageOK(-3));
+ check(!jr.run(getArgs("install repo module")) && usageOK(-3));
check(!jr.run(getArgs("install -r repoDoesNotExist module")) && errorOK(1));
- check(!jr.run(getArgs("install -p -r repoDoesNotExist module")) && errorOK(13));
+ check(!jr.run(getArgs("install -p -r repoDoesNotExist module")) && errorOK(4));
// Create a directory for a local repository.
File localRepoDir = new File(tmp, "JRepoTestLocalRepoDir");
@@ -87,7 +87,7 @@
// Verify silent output
File jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "JRepoModuleA", "1.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "JRepoModuleA", "1.0", "platform1", "archA", false, jamDir);
jamFile.deleteOnExit();
String jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -r " + repo + " " + jam)) && outputOK(0));
@@ -94,7 +94,7 @@
// Verify verbose output
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "JRepoModuleB", "1.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "JRepoModuleB", "1.0", "platform2", "archB", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
@@ -101,12 +101,12 @@
// Verify multiple versions of same named module
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "JRepoModuleB", "2.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "JRepoModuleB", "2.0", "platform3", "archC", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "JRepoModuleB", "2.5", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "JRepoModuleB", "2.5", "platform4", "archD", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
@@ -115,7 +115,7 @@
check(jr.run(getArgs("list -v -r " + repo)) && outputOK(6));
// Verify -p is not applicable to install
- check(!jr.run(getArgs("install -p -r " + repo + " " + jam)) && usageOK(1));
+ check(!jr.run(getArgs("install -p -r " + repo + " " + jam)) && usageOK(-4));
/* Check list command */
@@ -130,6 +130,9 @@
check(jr.run(getArgs("l -v -r " + repo)) && outputOK(6));
check(jr.run(getArgs("list -p -v -r " + repo)) && outputOK(28));
+ // Check that repositories are shown in sorted order
+ check(jr.run(getArgs("l -v -r " + repo)) && sortedOK());
+
// Nonexist things are not there
check(!jr.run(getArgs("list ThisWillNotBeFound")) && outputOK(0));
check(!jr.run(getArgs("list -v ThisWillNotBeFound")) && errorOK(1));
@@ -154,10 +157,10 @@
/* Check uninstall command */
- check(!jr.run(getArgs("uninstall")) && usageOK(0));
- check(!jr.run(getArgs("uninstall repo MODULE")) && usageOK(0));
+ check(!jr.run(getArgs("uninstall")) && usageOK(-3));
+ check(!jr.run(getArgs("uninstall repo MODULE")) && usageOK(-3));
check(!jr.run(getArgs("uninstall -r repoDoesNotExist module")) && errorOK(1));
- check(!jr.run(getArgs("uninstall -p -r repoDoesNotExist module")) && errorOK(13));
+ check(!jr.run(getArgs("uninstall -p -r repoDoesNotExist module")) && errorOK(4));
check(!jr.run(getArgs("uninstall -r " + repo + " Fred")) && errorOK(0));
check(!jr.run(getArgs("uninstall -v -r " + repo + " Fred")) && errorOK(1));
@@ -164,7 +167,7 @@
// Install one more module for tests below
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "JRepoModuleC", "1.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "JRepoModuleC", "1.0", "platform5", "archE", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("ins -v -r " + repo + " " + jam)) && outputOK(1));
@@ -190,12 +193,12 @@
// Install more modules to verify -i works
jamFile = JamBuilder.createJam(
- "jrepotest", "Interact", "JRepoModuleD", "2.7", "platform", "arch", false, jamDir);
+ "jrepotest", "Interact", "JRepoModuleD", "2.7", "platform6", "archF", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
jamFile = JamBuilder.createJam(
- "jrepotest", "Interact", "JRepoModuleD", "3.1", "platform", "arch", false, jamDir);
+ "jrepotest", "Interact", "JRepoModuleD", "3.1", "platform7", "archG", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + repo + " " + jam)) && outputOK(1));
@@ -236,13 +239,13 @@
// Verify multiple versions of same named module
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "URLModuleX", "7.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "URLModuleX", "7.0", "platform8", "archH", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
jamFile = JamBuilder.createJam(
- "jrepotest", "Example", "URLModuleX", "13.0", "platform", "arch", false, jamDir);
+ "jrepotest", "Example", "URLModuleX", "13.0", "platform9", "archI", false, jamDir);
jamFile.deleteOnExit();
jam = jamFile.getCanonicalPath();
check(jr.run(getArgs("install -v -r " + urlRepoPath + " " + jam)) && outputOK(1));
@@ -312,10 +315,36 @@
/** Check that usage is provided as expected. */
static boolean usageOK(int len) throws Throwable {
- // Add number of default lines of usage output to given value.
- return checkOutput(12 + len, berr);
+ // If len < 0, use negative of that, else use len + default
+ return checkOutput(len < 0 ? -len : 20 + len, berr);
}
+ /** Check that output is sorted, after skipping the firsts header line. */
+ static boolean sortedOK() throws Throwable {
+ int numFailed = failed;
+ String allLines = bout.toString();
+ if (debug) System.err.println("Checking sort order on '" + allLines + "'");
+ BufferedReader r = new BufferedReader(new StringReader(allLines));
+ check(r.readLine() != null); // Skip heading
+ List lines = new ArrayList();
+ String s;
+ while ((s = r.readLine()) != null) {
+ check(!lines.contains(s));
+ check(lines.add(s));
+ }
+ String prev = lines.get(2);
+ for (int i = 3; i < lines.size(); i++) {
+ String cur = lines.get(i);
+ if (!check(prev.compareTo(cur) < 0)) {
+ System.err.println(
+ "'" + prev + "'\nis not less than \n'" + cur + "'");
+ }
+ prev = cur;
+ }
+ bout.reset();
+ return numFailed == failed;
+ }
+
//--------------------- Infrastructure ---------------------------
static volatile int passed = 0, failed = 0;
static boolean pass() {passed++; return true;}