mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-12 04:05:26 +00:00
8386842: Preview files in root directory not recognized in system image
Reviewed-by: alanb, sherman, liach
This commit is contained in:
parent
157cca7802
commit
c042ad289d
@ -486,7 +486,7 @@ public final class ImageReader implements AutoCloseable {
|
||||
ImageLocation loc = null;
|
||||
if (isPreviewEnabled) {
|
||||
// We must test preview location first (if in preview mode).
|
||||
loc = findLocation(moduleName, PREVIEW_RESOURCE_PREFIX + resourcePath);
|
||||
loc = findLocation(moduleName, PREVIEW_RESOURCE_PREFIX + "/" + resourcePath);
|
||||
}
|
||||
if (loc == null) {
|
||||
loc = findLocation(moduleName, resourcePath);
|
||||
@ -531,7 +531,7 @@ public final class ImageReader implements AutoCloseable {
|
||||
return node.isResource();
|
||||
}
|
||||
}
|
||||
loc = findLocation(moduleName, PREVIEW_RESOURCE_PREFIX + resourcePath);
|
||||
loc = findLocation(moduleName, PREVIEW_RESOURCE_PREFIX + "/" + resourcePath);
|
||||
}
|
||||
if (loc == null) {
|
||||
loc = findLocation(moduleName, resourcePath);
|
||||
@ -561,7 +561,19 @@ public final class ImageReader implements AutoCloseable {
|
||||
// Now try the non-prefixed resource name, but be careful to avoid false
|
||||
// positives for names like "/modules/modules/xxx" which could return a
|
||||
// location of a directory entry.
|
||||
loc = findLocation(name.substring(MODULES_PREFIX.length()));
|
||||
String resourceName = name.substring(MODULES_PREFIX.length());
|
||||
if (isPreviewEnabled) {
|
||||
// Root-level preview resources are not pre-cached when an image
|
||||
// is opened, so check for them first.
|
||||
int pathStart = resourceName.indexOf('/', 1);
|
||||
if (pathStart > 1 && resourceName.indexOf('/', pathStart + 1) < 0) {
|
||||
loc = findLocation(resourceName.substring(0, pathStart)
|
||||
+ PREVIEW_INFIX + "/" + resourceName.substring(pathStart + 1));
|
||||
}
|
||||
}
|
||||
if (loc == null) {
|
||||
loc = findLocation(resourceName);
|
||||
}
|
||||
return loc != null && loc.getType() == RESOURCE
|
||||
? ensureCached(newResource(name, loc))
|
||||
: null;
|
||||
@ -649,6 +661,36 @@ public final class ImageReader implements AutoCloseable {
|
||||
private Directory completeModuleDirectory(Directory dir, ImageLocation loc) {
|
||||
assert dir.getName().equals(loc.getFullName()) : "Mismatched location for directory: " + dir;
|
||||
List<Node> previewOnlyNodes = getPreviewNodesToMerge(dir);
|
||||
if (isPreviewEnabled && previewOnlyNodes.isEmpty()) {
|
||||
// When opening an image in preview mode, packages that have preview
|
||||
// content are eagerly processed, caching preview resources and
|
||||
// preview-only directories for direct lookup. Root-level preview
|
||||
// resources are omitted during this process, since they have no
|
||||
// package path and the empty package is not represented under
|
||||
// "/packages", and must be processed separately.
|
||||
int moduleStart = MODULES_PREFIX.length() + 1;
|
||||
if (dir.getName().indexOf('/', moduleStart) < 0) {
|
||||
ImageLocation previewLoc = findLocation(dir.getName() + PREVIEW_INFIX);
|
||||
if (previewLoc != null) {
|
||||
previewOnlyNodes = createChildNodes(previewLoc, 0, childLoc -> {
|
||||
String baseName = getBaseName(childLoc);
|
||||
String nonPreviewChildName = dir.getName() + "/" + baseName;
|
||||
boolean isPreviewOnly = ImageLocation.isPreviewOnly(childLoc.getFlags());
|
||||
LocationType type = childLoc.getType();
|
||||
if (type == RESOURCE) {
|
||||
Node childNode = nodes.computeIfAbsent(nonPreviewChildName, n -> newResource(n, childLoc));
|
||||
return isPreviewOnly ? childNode : null;
|
||||
} else {
|
||||
assert type == MODULES_DIR : "Invalid location type: " + childLoc;
|
||||
Node childNode = nodes.get(nonPreviewChildName);
|
||||
assert !(isPreviewOnly && childNode == null) :
|
||||
"Inconsistent child node: " + nonPreviewChildName;
|
||||
return isPreviewOnly ? childNode : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// We hide preview names from direct lookup, but must also prevent
|
||||
// the preview directory from appearing in any META-INF directories.
|
||||
boolean parentIsMetaInfDir = isMetaInf(dir);
|
||||
|
||||
@ -46,6 +46,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@ -59,7 +60,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8385355
|
||||
* @bug 8385355 8386842
|
||||
* @summary Tests for ImageReader.
|
||||
* @modules java.base/jdk.internal.jimage
|
||||
* jdk.jlink/jdk.tools.jlink.internal
|
||||
@ -86,6 +87,11 @@ public class ImageReaderTest {
|
||||
"!META-INF/z",
|
||||
"!META-INF/collision/child.properties",
|
||||
"!META-INF/collision",
|
||||
// Non-class resource in top level directory
|
||||
"!fileA.txt",
|
||||
"!fileB.txt",
|
||||
"!META-INF/preview/fileA.txt",
|
||||
"!META-INF/preview/fileB.txt",
|
||||
// Replaces original class in preview mode.
|
||||
"@com.foo.HasPreviewVersion",
|
||||
// New class in existing package in preview mode.
|
||||
@ -96,6 +102,11 @@ public class ImageReaderTest {
|
||||
// Two new packages in preview mode (new symbolic links).
|
||||
"@com.bar.preview.stuff.Foo",
|
||||
"@com.bar.preview.stuff.Bar"),
|
||||
"modbaz", Arrays.asList(
|
||||
"!file.txt",
|
||||
"!normal.txt",
|
||||
"!META-INF/preview/file.txt",
|
||||
"!META-INF/preview/previewOnly.txt"),
|
||||
"modgus", Arrays.asList(
|
||||
// A second module with a preview-only empty package (preview).
|
||||
"@com.bar.preview.other.Gus"));
|
||||
@ -270,6 +281,18 @@ public class ImageReaderTest {
|
||||
assertAbsent(reader, "/modules/modfoo/com/foo/bar/IsPreviewOnly.class");
|
||||
assertDirContents(reader, "/modules/modfoo/com/foo", "HasPreviewVersion.class", "NormalFoo.class", "bar");
|
||||
assertDirContents(reader, "/modules/modfoo/com/foo/bar", "NormalBar.class");
|
||||
|
||||
// Non-class resource in top level directory
|
||||
assertResource(reader, "modfoo", "fileA.txt");
|
||||
assertNonPreviewResourceVersion(reader, "modfoo", "fileA.txt");
|
||||
assertNode(reader, "/modules/modfoo/fileB.txt");
|
||||
assertNonPreviewResourceVersion(reader, "modfoo", "fileB.txt");
|
||||
assertDirContents(reader, "/modules/modfoo", "META-INF", "module-info.class", "fileA.txt", "fileB.txt", "com");
|
||||
|
||||
assertAbsent(reader, "/modules/modbaz/previewOnly.txt");
|
||||
assertDirContents(reader, "/modules/modbaz", "META-INF", "module-info.class", "file.txt", "normal.txt");
|
||||
assertNonPreviewResourceVersion(reader, "modbaz", "file.txt");
|
||||
assertNonPreviewResourceVersion(reader, "modbaz", "normal.txt");
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,6 +312,20 @@ public class ImageReaderTest {
|
||||
assertResource(reader, "modfoo", "com/foo/bar/IsPreviewOnly.class");
|
||||
assertDirContents(reader, "/modules/modfoo/com/foo", "HasPreviewVersion.class", "NormalFoo.class", "bar");
|
||||
assertDirContents(reader, "/modules/modfoo/com/foo/bar", "NormalBar.class", "IsPreviewOnly.class");
|
||||
|
||||
// Non-class resource in top level directory
|
||||
assertResource(reader, "modfoo", "fileA.txt");
|
||||
assertPreviewResourceVersion(reader, "modfoo", "fileA.txt");
|
||||
assertNode(reader, "/modules/modfoo/fileB.txt");
|
||||
assertPreviewResourceVersion(reader, "modfoo", "fileB.txt");
|
||||
assertDirContents(reader, "/modules/modfoo/com", "foo");
|
||||
assertDirContents(reader, "/modules/modfoo", "META-INF", "module-info.class", "fileA.txt", "fileB.txt", "com");
|
||||
|
||||
assertNode(reader, "/modules/modbaz/previewOnly.txt");
|
||||
assertDirContents(reader, "/modules/modbaz", "META-INF", "module-info.class", "file.txt", "normal.txt", "previewOnly.txt");
|
||||
assertPreviewResourceVersion(reader, "modbaz", "file.txt");
|
||||
assertNonPreviewResourceVersion(reader, "modbaz", "normal.txt");
|
||||
assertPreviewResourceVersion(reader, "modbaz", "previewOnly.txt");
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,6 +442,17 @@ public class ImageReaderTest {
|
||||
assertSame(resNode, reader.findNode(nodeName));
|
||||
}
|
||||
|
||||
private static void assertNonPreviewResourceVersion(ImageReader reader, String modName, String resPath) throws IOException {
|
||||
Node resNode = reader.findResourceNode(modName, resPath);
|
||||
assertArrayEquals(resPath.getBytes(StandardCharsets.UTF_8), reader.getResource(resNode));
|
||||
}
|
||||
|
||||
private static void assertPreviewResourceVersion(ImageReader reader, String modName, String resPath) throws IOException {
|
||||
Node resNode = reader.findResourceNode(modName, resPath);
|
||||
String name = "META-INF/preview/" + resPath;
|
||||
assertArrayEquals(name.getBytes(StandardCharsets.UTF_8), reader.getResource(resNode));
|
||||
}
|
||||
|
||||
private static void assertNonPreviewVersion(ImageClassLoader loader, String module, String fqn) throws IOException {
|
||||
assertEquals("Class: " + fqn, loader.loadAndGetToString(module, fqn));
|
||||
}
|
||||
@ -441,7 +489,7 @@ public class ImageReaderTest {
|
||||
|
||||
classes.forEach(fqn -> {
|
||||
if (fqn.startsWith("!")) {
|
||||
jar.addEntry(fqn.substring(1), "resource".getBytes(StandardCharsets.UTF_8));
|
||||
jar.addEntry(fqn.substring(1), fqn.substring(1).getBytes(StandardCharsets.UTF_8));
|
||||
return;
|
||||
}
|
||||
boolean isPreviewEntry = fqn.startsWith("@");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user