Skip to content

Commit bc7a3d6

Browse files
david-beaumontRoger Riggs
authored andcommitted
8368031: Apply mainline changes to support preview mode work into Valhalla
Reviewed-by: liach, rriggs
1 parent 05d82ab commit bc7a3d6

File tree

9 files changed

+524
-112
lines changed

9 files changed

+524
-112
lines changed

src/java.base/share/classes/jdk/internal/jimage/ImageReader.java

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,45 @@ public Node findNode(String name) throws IOException {
137137
return reader.findNode(name);
138138
}
139139

140+
/**
141+
* Returns a resource node in the given module, or null if no resource of
142+
* that name exists.
143+
*
144+
* <p>This is equivalent to:
145+
* <pre>{@code
146+
* findNode("/modules/" + moduleName + "/" + resourcePath)
147+
* }</pre>
148+
* but more performant, and returns {@code null} for directories.
149+
*
150+
* @param moduleName The module name of the requested resource.
151+
* @param resourcePath Trailing module-relative resource path, not starting
152+
* with {@code '/'}.
153+
*/
154+
public Node findResourceNode(String moduleName, String resourcePath)
155+
throws IOException {
156+
ensureOpen();
157+
return reader.findResourceNode(moduleName, resourcePath);
158+
}
159+
160+
/**
161+
* Returns whether a resource exists in the given module.
162+
*
163+
* <p>This is equivalent to:
164+
* <pre>{@code
165+
* findResourceNode(moduleName, resourcePath) != null
166+
* }</pre>
167+
* but more performant, and will not create or cache new nodes.
168+
*
169+
* @param moduleName The module name of the resource being tested for.
170+
* @param resourcePath Trailing module-relative resource path, not starting
171+
* with {@code '/'}.
172+
*/
173+
public boolean containsResource(String moduleName, String resourcePath)
174+
throws IOException {
175+
ensureOpen();
176+
return reader.containsResource(moduleName, resourcePath);
177+
}
178+
140179
/**
141180
* Returns a copy of the content of a resource node. The buffer returned by
142181
* this method is not cached by the node, and each call returns a new array
@@ -276,10 +315,7 @@ public void close(ImageReader image) throws IOException {
276315
* Returns a node with the given name, or null if no resource or directory of
277316
* that name exists.
278317
*
279-
* <p>This is the only public API by which anything outside this class can access
280-
* {@code Node} instances either directly, or by resolving symbolic links.
281-
*
282-
* <p>Note also that there is no reentrant calling back to this method from within
318+
* <p>Note that there is no reentrant calling back to this method from within
283319
* the node handling code.
284320
*
285321
* @param name an absolute, {@code /}-separated path string, prefixed with either
@@ -291,6 +327,9 @@ synchronized Node findNode(String name) {
291327
// We cannot get the root paths ("/modules" or "/packages") here
292328
// because those nodes are already in the nodes cache.
293329
if (name.startsWith(MODULES_ROOT + "/")) {
330+
// This may perform two lookups, one for a directory (in
331+
// "/modules/...") and one for a non-prefixed resource
332+
// (with "/modules" removed).
294333
node = buildModulesNode(name);
295334
} else if (name.startsWith(PACKAGES_ROOT + "/")) {
296335
node = buildPackagesNode(name);
@@ -307,6 +346,55 @@ synchronized Node findNode(String name) {
307346
return node;
308347
}
309348

349+
/**
350+
* Returns a resource node in the given module, or null if no resource of
351+
* that name exists.
352+
*
353+
* <p>Note that there is no reentrant calling back to this method from within
354+
* the node handling code.
355+
*/
356+
Node findResourceNode(String moduleName, String resourcePath) {
357+
// Unlike findNode(), this method makes only one lookup in the
358+
// underlying jimage, but can only reliably return resource nodes.
359+
if (moduleName.indexOf('/') >= 0) {
360+
throw new IllegalArgumentException("invalid module name: " + moduleName);
361+
}
362+
String nodeName = MODULES_ROOT + "/" + moduleName + "/" + resourcePath;
363+
// Synchronize as tightly as possible to reduce locking contention.
364+
synchronized (this) {
365+
Node node = nodes.get(nodeName);
366+
if (node == null) {
367+
ImageLocation loc = findLocation(moduleName, resourcePath);
368+
if (loc != null && isResource(loc)) {
369+
node = newResource(nodeName, loc);
370+
nodes.put(node.getName(), node);
371+
}
372+
return node;
373+
} else {
374+
return node.isResource() ? node : null;
375+
}
376+
}
377+
}
378+
379+
/**
380+
* Returns whether a resource exists in the given module.
381+
*
382+
* <p>This method is expected to be called frequently for resources
383+
* which do not exist in the given module (e.g. as part of classpath
384+
* search). As such, it skips checking the nodes cache and only checks
385+
* for an entry in the jimage file, as this is faster if the resource
386+
* is not present. This also means it doesn't need synchronization.
387+
*/
388+
boolean containsResource(String moduleName, String resourcePath) {
389+
if (moduleName.indexOf('/') >= 0) {
390+
throw new IllegalArgumentException("invalid module name: " + moduleName);
391+
}
392+
// If the given module name is 'modules', then 'isResource()'
393+
// returns false to prevent false positives.
394+
ImageLocation loc = findLocation(moduleName, resourcePath);
395+
return loc != null && isResource(loc);
396+
}
397+
310398
/**
311399
* Builds a node in the "/modules/..." namespace.
312400
*

0 commit comments

Comments
 (0)