20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.jimage;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
32 import java.nio.ByteBuffer;
33 import java.nio.ByteOrder;
34 import java.nio.IntBuffer;
35 import java.nio.channels.FileChannel;
36 import java.nio.file.Path;
37 import java.nio.file.StandardOpenOption;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.util.Objects;
41 import java.util.stream.IntStream;
42 import jdk.internal.jimage.decompressor.Decompressor;
43
44 /**
45 * @implNote This class needs to maintain JDK 8 source compatibility.
46 *
47 * It is used internally in the JDK to implement jimage/jrtfs access,
48 * but also compiled and delivered as part of the jrtfs.jar to support access
49 * to the jimage file provided by the shipped JDK by tools running on JDK 8.
50 */
51 public class BasicImageReader implements AutoCloseable {
52 @SuppressWarnings({ "removal", "suppression" })
53 private static boolean isSystemProperty(String key, String value, String def) {
54 // No lambdas during bootstrap
55 return AccessController.doPrivileged(
56 new PrivilegedAction<Boolean>() {
57 @Override
58 public Boolean run() {
59 return value.equals(System.getProperty(key, def));
60 }
61 });
300 // index is twos complement of location attributes index.
301 return -index - 1;
302 } else if (index > 0) {
303 // index is hash seed needed to compute location attributes index.
304 return ImageStringsReader.hashCode(module, name, index) % count;
305 } else {
306 // No entry.
307 return -1;
308 }
309 }
310
311 public String[] getEntryNames() {
312 return IntStream.range(0, offsets.capacity())
313 .map(offsets::get)
314 .filter(o -> o != 0)
315 .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
316 .sorted()
317 .toArray(String[]::new);
318 }
319
320 ImageLocation getLocation(int offset) {
321 return ImageLocation.readFrom(this, offset);
322 }
323
324 public long[] getAttributes(int offset) {
325 if (offset < 0 || offset >= locations.limit()) {
326 throw new IndexOutOfBoundsException("offset");
327 }
328 return ImageLocation.decompress(locations, offset);
329 }
330
331 public String getString(int offset) {
332 if (offset < 0 || offset >= strings.limit()) {
333 throw new IndexOutOfBoundsException("offset");
334 }
335 return ImageStringsReader.stringFromByteBuffer(strings, offset);
336 }
337
338 public int match(int offset, String string, int stringOffset) {
339 if (offset < 0 || offset >= strings.limit()) {
|
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.jimage;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
32 import java.nio.ByteBuffer;
33 import java.nio.ByteOrder;
34 import java.nio.IntBuffer;
35 import java.nio.channels.FileChannel;
36 import java.nio.file.Path;
37 import java.nio.file.StandardOpenOption;
38 import java.security.AccessController;
39 import java.security.PrivilegedAction;
40 import java.util.NoSuchElementException;
41 import java.util.Objects;
42 import java.util.Random;
43 import java.util.stream.IntStream;
44 import java.util.stream.Stream;
45
46 import jdk.internal.jimage.decompressor.Decompressor;
47
48 /**
49 * @implNote This class needs to maintain JDK 8 source compatibility.
50 *
51 * It is used internally in the JDK to implement jimage/jrtfs access,
52 * but also compiled and delivered as part of the jrtfs.jar to support access
53 * to the jimage file provided by the shipped JDK by tools running on JDK 8.
54 */
55 public class BasicImageReader implements AutoCloseable {
56 @SuppressWarnings({ "removal", "suppression" })
57 private static boolean isSystemProperty(String key, String value, String def) {
58 // No lambdas during bootstrap
59 return AccessController.doPrivileged(
60 new PrivilegedAction<Boolean>() {
61 @Override
62 public Boolean run() {
63 return value.equals(System.getProperty(key, def));
64 }
65 });
304 // index is twos complement of location attributes index.
305 return -index - 1;
306 } else if (index > 0) {
307 // index is hash seed needed to compute location attributes index.
308 return ImageStringsReader.hashCode(module, name, index) % count;
309 } else {
310 // No entry.
311 return -1;
312 }
313 }
314
315 public String[] getEntryNames() {
316 return IntStream.range(0, offsets.capacity())
317 .map(offsets::get)
318 .filter(o -> o != 0)
319 .mapToObj(o -> ImageLocation.readFrom(this, o).getFullName())
320 .sorted()
321 .toArray(String[]::new);
322 }
323
324 /**
325 * Returns the "raw" API for accessing underlying jimage resource entries.
326 *
327 * <p>This is only meaningful for use by code dealing directly with jimage
328 * files, and cannot be used to reliably lookup resources used at runtime.
329 *
330 * <p>This API remains valid until the image reader from which it was
331 * obtained is closed.
332 */
333 // Package visible for use by ImageReader.
334 ResourceEntries getResourceEntries() {
335 return new ResourceEntries() {
336 @Override
337 public Stream<String> getEntryNames(String module) {
338 if (module.isEmpty() || module.equals("modules") || module.equals("packages")) {
339 throw new IllegalArgumentException("Invalid module name: " + module);
340 }
341 return IntStream.range(0, offsets.capacity())
342 .map(offsets::get)
343 .filter(offset -> offset != 0)
344 // Reusing a location instance or getting the module
345 // offset directly would save a lot of allocations here.
346 .mapToObj(offset -> ImageLocation.readFrom(BasicImageReader.this, offset))
347 // Reverse lookup of module offset would be faster here.
348 .filter(loc -> module.equals(loc.getModule()))
349 .map(ImageLocation::getFullName);
350 }
351
352 private ImageLocation getResourceLocation(String name) {
353 if (!name.startsWith("/modules/") && !name.startsWith("/packages/")) {
354 ImageLocation location = BasicImageReader.this.findLocation(name);
355 if (location != null) {
356 return location;
357 }
358 }
359 throw new NoSuchElementException("No such resource entry: " + name);
360 }
361
362 @Override
363 public long getSize(String name) {
364 return getResourceLocation(name).getUncompressedSize();
365 }
366
367 @Override
368 public byte[] getBytes(String name) {
369 return BasicImageReader.this.getResource(getResourceLocation(name));
370 }
371 };
372 }
373
374 ImageLocation getLocation(int offset) {
375 return ImageLocation.readFrom(this, offset);
376 }
377
378 public long[] getAttributes(int offset) {
379 if (offset < 0 || offset >= locations.limit()) {
380 throw new IndexOutOfBoundsException("offset");
381 }
382 return ImageLocation.decompress(locations, offset);
383 }
384
385 public String getString(int offset) {
386 if (offset < 0 || offset >= strings.limit()) {
387 throw new IndexOutOfBoundsException("offset");
388 }
389 return ImageStringsReader.stringFromByteBuffer(strings, offset);
390 }
391
392 public int match(int offset, String string, int stringOffset) {
393 if (offset < 0 || offset >= strings.limit()) {
|