-
Notifications
You must be signed in to change notification settings - Fork 131
8371292: [lworld] Switch JLink to not use ImageReader API #1721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
1cc77d4
3fcfea6
a433f09
67984e2
a2f0c0c
fdcb73f
e52692f
533e5af
7263e2e
8e702fa
1f85ff7
726ace9
de2c1be
493930d
dffe937
a27a288
aac5c9e
8567038
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,8 +37,12 @@ | |
| import java.nio.file.StandardOpenOption; | ||
| import java.security.AccessController; | ||
| import java.security.PrivilegedAction; | ||
| import java.util.NoSuchElementException; | ||
| import java.util.Objects; | ||
| import java.util.function.Predicate; | ||
| import java.util.stream.IntStream; | ||
| import java.util.stream.Stream; | ||
|
|
||
| import jdk.internal.jimage.decompressor.Decompressor; | ||
|
|
||
| /** | ||
|
|
@@ -326,6 +330,58 @@ public String[] getEntryNames() { | |
| .toArray(String[]::new); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the "raw" API for accessing underlying jimage resource entries. | ||
| * | ||
| * <p>This is only meaningful for use by code dealing directly with jimage | ||
| * files, and cannot be used to reliably lookup resources used at runtime. | ||
| * | ||
| * <p>This API remains valid until the image reader from which it was | ||
| * obtained is closed. | ||
| */ | ||
| // Package visible for use by ImageReader. | ||
| ResourceEntries getResourceEntries() { | ||
| return new ResourceEntries() { | ||
| @Override | ||
| public Stream<String> entryNamesIn(String module) { | ||
| if (module.isEmpty() || module.equals("modules") || module.equals("packages")) { | ||
| throw new IllegalArgumentException("Invalid module name: " + module); | ||
| } | ||
| return IntStream.range(0, offsets.capacity()) | ||
| .map(offsets::get) | ||
| .filter(offset -> offset != 0) | ||
| // Reusing a location instance or getting the module | ||
david-beaumont marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // offset directly would save a lot of allocations here. | ||
| .mapToObj(offset -> ImageLocation.readFrom(BasicImageReader.this, offset)) | ||
| // Reverse lookup of module offset would be faster here. | ||
| .filter(loc -> module.equals(loc.getModule())) | ||
| .map(ImageLocation::getFullName); | ||
| } | ||
|
|
||
| private ImageLocation getResourceLocation(String name) { | ||
| // Other types of invalid name just result in no entry being found. | ||
| if (name.startsWith("/modules/") || name.startsWith("/packages/")) { | ||
| throw new IllegalArgumentException("Invalid entry name: " + name); | ||
| } | ||
|
||
| ImageLocation location = BasicImageReader.this.findLocation(name); | ||
| if (location == null) { | ||
| throw new NoSuchElementException("No such resource entry: " + name); | ||
| } | ||
| return location; | ||
| } | ||
|
|
||
| @Override | ||
| public long sizeOf(String name) { | ||
| return getResourceLocation(name).getUncompressedSize(); | ||
| } | ||
|
|
||
| @Override | ||
| public InputStream open(String name) { | ||
| return BasicImageReader.this.getResourceStream(getResourceLocation(name)); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| ImageLocation getLocation(int offset) { | ||
| return ImageLocation.readFrom(this, offset); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package jdk.internal.jimage; | ||
|
|
||
| import java.io.InputStream; | ||
| import java.util.stream.Stream; | ||
|
|
||
| /** | ||
| * Accesses the underlying resource entries in a jimage file. | ||
| * | ||
| * <p>This API is designed only for use by the jlink classes, which manipulate | ||
| * jimage files directly. For inspection of runtime resources, it is vital that | ||
| * {@code previewMode} is correctly observed, making this API unsuitable. | ||
|
||
| * | ||
| * <p>This API ignores the {@code previewMode} of the {@link ImageReader} from | ||
| * which it is obtained, and returns an unmapped view of entries (e.g. allowing | ||
| * for direct access of resources in the {@code META-INF/preview/...} namespace). | ||
| * | ||
| * <p>It disallows access to resource directories (i.e. {@code "/modules/..."} | ||
| * or packages (i.e. {@code "/packages/..."}. | ||
| */ | ||
| public interface ResourceEntries { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an API so that we can avoid using ImageReader directly in the jlink code. |
||
| /** | ||
| * Returns the full entry names for all resources in the given module, in | ||
| * random order. Entry names will always be prefixed by the given module | ||
| * name (e.g. "/<module-name/..."). | ||
| */ | ||
| Stream<String> entryNamesIn(String module); | ||
|
||
|
|
||
| /** | ||
| * Returns the (uncompressed) size of a resource given its full entry name. | ||
| * | ||
| * @throws java.util.NoSuchElementException if the resource does not exist. | ||
| */ | ||
| long sizeOf(String name); | ||
|
|
||
| /** | ||
| * Returns an {@link InputStream} for a resource given its full entry name. | ||
| * | ||
| * @throws java.util.NoSuchElementException if the resource does not exist. | ||
| */ | ||
| InputStream open(String name); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ | |
| */ | ||
| package jdk.tools.jlink.internal; | ||
|
|
||
| import java.io.Closeable; | ||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.nio.file.Path; | ||
|
|
@@ -34,7 +35,7 @@ | |
| * An Archive of all content, classes, resources, configuration files, and | ||
| * other, for a module. | ||
| */ | ||
| public interface Archive { | ||
| public interface Archive extends Closeable { | ||
david-beaumont marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** | ||
| * Entry is contained in an Archive | ||
|
|
@@ -59,11 +60,12 @@ public static enum EntryType { | |
| private final String path; | ||
|
|
||
| /** | ||
| * Constructs an entry of the given archive | ||
| * @param archive archive | ||
| * @param path | ||
| * @param name an entry name that does not contain the module name | ||
| * @param type | ||
| * Constructs an entry of the given archive. | ||
| * | ||
| * @param archive the archive in which this entry exists. | ||
| * @param path the complete path of the entry, including the module. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that now I removed the path() method I added, the path passed here serves absolutely no purpose other than to appear in the toString() output. I'd vote for removing it completely and simplifying callers. |
||
| * @param name an entry name relative to its containing module. | ||
| * @param type the entry type. | ||
| */ | ||
| public Entry(Archive archive, String path, String name, EntryType type) { | ||
| this.archive = Objects.requireNonNull(archive); | ||
|
|
@@ -72,10 +74,6 @@ public Entry(Archive archive, String path, String name, EntryType type) { | |
| this.type = Objects.requireNonNull(type); | ||
| } | ||
|
|
||
| public final Archive archive() { | ||
| return archive; | ||
| } | ||
|
|
||
| public final EntryType type() { | ||
| return type; | ||
| } | ||
|
|
@@ -134,5 +132,6 @@ public String toString() { | |
| /* | ||
| * Close the archive | ||
| */ | ||
| @Override | ||
| void close() throws IOException; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the implementation of the new, narrow, API. That's it.