--- a/jdk/test/tools/jar/modularJar/Basic.java Wed Nov 23 16:16:35 2016 +0000
+++ b/jdk/test/tools/jar/modularJar/Basic.java Thu Dec 01 08:57:53 2016 +0000
@@ -22,19 +22,18 @@
*/
import java.io.*;
+import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Method;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
+import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.function.Consumer;
import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.testlibrary.FileUtils;
@@ -76,7 +75,8 @@
Set.of("jdk.test.foo"),
null, // no uses
null, // no provides
- Set.of("jdk.test.foo.internal"));
+ Set.of("jdk.test.foo.internal",
+ "jdk.test.foo.resources"));
static TestModuleData BAR = new TestModuleData("bar",
"4.5.6.7",
"jdk.test.bar.Bar",
@@ -99,17 +99,18 @@
final String version;
final String message;
final String hashes;
- final Set<String> conceals;
+ final Set<String> packages;
TestModuleData(String mn, String v, String mc, String m, String h,
Set<String> requires, Set<String> exports, Set<String> uses,
- Set<String> provides, Set<String> conceals) {
+ Set<String> provides, Set<String> contains) {
moduleName = mn; mainClass = mc; version = v; message = m; hashes = h;
- this.requires = requires;
- this.exports = exports;
- this.uses = uses;
- this.provides = provides;
- this.conceals = conceals;
+ this.requires = requires != null ? requires : Collections.emptySet();
+ this.exports = exports != null ? exports : Collections.emptySet();
+ this.uses = uses != null ? uses : Collections.emptySet();;
+ this.provides = provides != null ? provides : Collections.emptySet();
+ this.packages = Stream.concat(this.exports.stream(), contains.stream())
+ .collect(Collectors.toSet());
}
static TestModuleData from(String s) {
try {
@@ -148,8 +149,8 @@
provides = stringToSet(line);
} else if (line.startsWith("hashes:")) {
hashes = line.substring("hashes:".length());
- } else if (line.startsWith("conceals:")) {
- line = line.substring("conceals:".length());
+ } else if (line.startsWith("contains:")) {
+ line = line.substring("contains:".length());
conceals = stringToSet(line);
} else {
throw new AssertionError("Unknown value " + line);
@@ -192,16 +193,14 @@
assertSetsEqual(expected.exports, received.exports);
assertSetsEqual(expected.uses, received.uses);
assertSetsEqual(expected.provides, received.provides);
- assertSetsEqual(expected.conceals, received.conceals);
+ assertSetsEqual(expected.packages, received.packages);
}
static void assertSetsEqual(Set<String> s1, Set<String> s2) {
- if (s1 == null && s2 == null) // none expected, or received
- return;
- assertTrue(s1.size() == s2.size(),
- "Unexpected set size difference: ", s1.size(), ", ", s2.size());
- s1.forEach(p -> assertTrue(s2.contains(p), "Expected ", p, ", in ", s2));
- }
+ if (!s1.equals(s2)) {
+ org.testng.Assert.assertTrue(false, s1 + " vs " + s2);
+ }
+ }
@BeforeTest
public void compileModules() throws Exception {
@@ -209,6 +208,11 @@
compileModule(BAR.moduleName, MODULE_CLASSES);
compileModule("baz"); // for service provider consistency checking
+ // copy resources
+ copyResource(TEST_SRC.resolve("src").resolve(FOO.moduleName),
+ MODULE_CLASSES.resolve(FOO.moduleName),
+ "jdk/test/foo/resources/foo.properties");
+
setupMRJARModuleInfo(FOO.moduleName);
setupMRJARModuleInfo(BAR.moduleName);
setupMRJARModuleInfo("baz");
@@ -228,6 +232,12 @@
"--no-manifest",
"-C", modClasses.toString(), ".")
.assertSuccess();
+
+ assertSetsEqual(readPackagesAttribute(modularJar),
+ Set.of("jdk.test.foo",
+ "jdk.test.foo.resources",
+ "jdk.test.foo.internal"));
+
java(mp, FOO.moduleName + "/" + FOO.mainClass)
.assertSuccess()
.resultChecker(r -> assertModuleData(r, FOO));
@@ -375,7 +385,8 @@
"--file=" + modularJar.toString(),
"--no-manifest",
"-C", modClasses.toString(), "module-info.class",
- "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+ "-C", modClasses.toString(), "jdk/test/foo/Foo.class",
+ "-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
.assertSuccess();
jar("--update",
"--file=" + modularJar.toString(),
@@ -471,13 +482,63 @@
"Expecting to find \"bar, requires foo,...\"",
"in output, but did not: [" + r.output + "]");
p = Pattern.compile(
- "conceals\\s+jdk.test.foo\\s+conceals\\s+jdk.test.foo.internal");
+ "contains\\s+jdk.test.foo\\s+contains\\s+jdk.test.foo.internal");
assertTrue(p.matcher(r.output).find(),
- "Expecting to find \"conceals jdk.test.foo,...\"",
+ "Expecting to find \"contains jdk.test.foo,...\"",
"in output, but did not: [" + r.output + "]");
});
}
+
+ @Test
+ public void partialUpdateFooPackagesAttribute() throws IOException {
+ Path mp = Paths.get("partialUpdateFooPackagesAttribute");
+ createTestDir(mp);
+ Path modClasses = MODULE_CLASSES.resolve(FOO.moduleName);
+ Path modularJar = mp.resolve(FOO.moduleName + ".jar");
+
+ // Not all files, and none from non-exported packages,
+ // i.e. no concealed list in first create
+ jar("--create",
+ "--file=" + modularJar.toString(),
+ "--no-manifest",
+ "-C", modClasses.toString(), "module-info.class",
+ "-C", modClasses.toString(), "jdk/test/foo/Foo.class")
+ .assertSuccess();
+
+ assertSetsEqual(readPackagesAttribute(modularJar),
+ Set.of("jdk.test.foo"));
+
+ jar("--update",
+ "--file=" + modularJar.toString(),
+ "-C", modClasses.toString(), "jdk/test/foo/resources/foo.properties")
+ .assertSuccess();
+
+ assertSetsEqual(readPackagesAttribute(modularJar),
+ Set.of("jdk.test.foo", "jdk.test.foo.resources"));
+
+ jar("--update",
+ "--file=" + modularJar.toString(),
+ "--main-class=" + FOO.mainClass,
+ "--module-version=" + FOO.version,
+ "--no-manifest",
+ "-C", modClasses.toString(), "jdk/test/foo/internal/Message.class")
+ .assertSuccess();
+
+ assertSetsEqual(readPackagesAttribute(modularJar),
+ Set.of("jdk.test.foo",
+ "jdk.test.foo.resources",
+ "jdk.test.foo.internal"));
+
+ java(mp, FOO.moduleName + "/" + FOO.mainClass)
+ .assertSuccess()
+ .resultChecker(r -> assertModuleData(r, FOO));
+ }
+
+ private Set<String> readPackagesAttribute(Path jar) {
+ return getModuleDescriptor(jar).packages();
+ }
+
@Test
public void hashBarInFooModule() throws IOException {
Path mp = Paths.get("dependencesFooBar");
@@ -506,6 +567,7 @@
.assertSuccess();
java(mp, BAR.moduleName + "/" + BAR.mainClass,
+ "--add-exports", "java.base/jdk.internal.misc=bar",
"--add-exports", "java.base/jdk.internal.module=bar")
.assertSuccess()
.resultChecker(r -> {
@@ -550,6 +612,7 @@
"-C", barClasses.toString(), ".").assertSuccess();
java(mp, BAR.moduleName + "/" + BAR.mainClass,
+ "--add-exports", "java.base/jdk.internal.misc=bar",
"--add-exports", "java.base/jdk.internal.module=bar")
.assertFailure()
.resultChecker(r -> {
@@ -750,12 +813,22 @@
static Path compileModule(String mn, Path mp)
throws IOException
{
- Path fooSourcePath = TEST_SRC.resolve("src").resolve(mn);
+ Path sourcePath = TEST_SRC.resolve("src").resolve(mn);
Path build = Files.createDirectories(MODULE_CLASSES.resolve(mn));
- javac(build, mp, fileList(fooSourcePath));
+ javac(build, mp, sourceList(sourcePath));
return build;
}
+ static void copyResource(Path srcDir, Path dir, String resource)
+ throws IOException
+ {
+ Path dest = dir.resolve(resource);
+ Files.deleteIfExists(dest);
+
+ Files.createDirectories(dest.getParent());
+ Files.copy(srcDir.resolve(resource), dest);
+ }
+
static void setupMRJARModuleInfo(String moduleName) throws IOException {
Path modClasses = MODULE_CLASSES.resolve(moduleName);
Path metaInfDir = MRJAR_DIR.resolve(moduleName).resolve("META-INF");
@@ -774,6 +847,18 @@
}
}
+ static ModuleDescriptor getModuleDescriptor(Path jar) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ try (JarFile jf = new JarFile(jar.toFile())) {
+ JarEntry entry = jf.getJarEntry("module-info.class");
+ try (InputStream in = jf.getInputStream(entry)) {
+ return ModuleDescriptor.read(in);
+ }
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
+ }
+
// Re-enable when there is support in javax.tools for module path
// static void javac(Path dest, Path... sourceFiles) throws IOException {
// out.printf("Compiling %d source files %s%n", sourceFiles.length,
@@ -817,6 +902,8 @@
commands.add(dest.toString());
if (dest.toString().contains("bar")) {
commands.add("--add-exports");
+ commands.add("java.base/jdk.internal.misc=bar");
+ commands.add("--add-exports");
commands.add("java.base/jdk.internal.module=bar");
}
if (modulePath != null) {
@@ -848,17 +935,10 @@
return run(new ProcessBuilder(commands));
}
- static Path[] fileList(Path directory) throws IOException {
- final List<Path> filePaths = new ArrayList<>();
- Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file,
- BasicFileAttributes attrs) {
- filePaths.add(file);
- return FileVisitResult.CONTINUE;
- }
- });
- return filePaths.toArray(new Path[filePaths.size()]);
+ static Path[] sourceList(Path directory) throws IOException {
+ return Files.find(directory, Integer.MAX_VALUE,
+ (file, attrs) -> (file.toString().endsWith(".java")))
+ .toArray(Path[]::new);
}
static void createTestDir(Path p) throws IOException{