Skip to content
Luke Hutchison edited this page Nov 20, 2021 · 5 revisions

See also the ClassGraph API overview.

Contents

Resource usage pattern

💡 If you just need the content of the resource as a String, call Resource#getContentAsString().

A Resource can be opened as a ByteBuffer, InputStream or loaded as a byte[] array. For ByteBuffer and InputStream, be sure to call .close() on the Resource once you have finished with it:

ResourceList matchingResources = scanResult.getResourcesWithPath("config/cfg.xml");
for (Resource resource : matchingResources) {
    try {
        InputStream inputStream = resource.open();
        // ... Use inputStream ...
    } finally {
        resource.close();
    }
}

The above is equivalent to the following pattern (putting Resource resToClose = resource; as the first entry in the try header will cause resource to be closed after inputStream is closed):

ResourceList matchingResources = scanResult.getResourcesWithPath("config/cfg.xml");
for (Resource resource : matchingResources) {
    try (Resource resToClose = resource; InputStream inputStream = resource.open()) {
        // ... Use inputStream ...
    }
}

Alternatively you can use the ResourceList#forEach*() methods, which call Resource#close() for you:

ResourceList matchingResources = scanResult.getResourcesWithPath("config/cfg.xml");
matchingResources.forEachInputStreamIgnoringIOException((resource, inputStream) -> {
    // ... Use inputStream ...
});

Resource

A reference to a file found within a classath directory or jarfile, or within a module. Obtained by calling ScanResult#getAllResources() and related methods.

In addition to optionally scanning classes on the classpath, ClassGraph always records the names of all resources (files) encountered in accepted packages during the scan (including classfiles and non-class files). The content of any resource file, or resource files with paths matching a certain pattern, can be read after the scan.

Behind the scenes, ClassGraph tries to open resources as memory-mapped file channel wherever possible for speed, while transparently translating from the fastest available API for accessing any given resource to whichever API mechanism you want to use to read the resource, allowing you to access the resource as either an InputStream, ByteBuffer or byte[] array, in the fastest way possible.

  • Reading resource content:

    💡 The best way to read from resources is by filtering a ResourceList for resources with paths of interest, then calling .forEachByteArrayIgnoringIOException(ByteArrayConsumer), .forEachByteArrayThrowingIOException(ByteArrayConsumerThrowsIOException), .forEachInputStreamIgnoringIOException(InputStreamConsumer), .forEachInputStreamThrowingIOException(InputStreamConsumerThrowsIOException), .forEachByteBufferIgnoringIOException(InputStreamConsumer) or .forEachByteBufferThrowingIOException(InputStreamConsumerTrowsIOException), since these all properly close the Resource after the consumer has read from the resource.

    💡 However, if you want to read the contents of a Resource manually, using one of the following methods, don't forget to call Resource#close() when you have finished reading from the resource.

    💡 ClassGraph will transparently translate the mechanism for accessing the underlying resource type (whether the resource is a file in a directory, or an entry in a jarfile, or a resource in a module) to ByteBuffer, InputStream or byte[] array, in the most efficient manner possible.

    🛑 Important: Resource is not threadsafe -- you should only have any given Resource open in one thread at a time.

    • .open() opens the resource as an InputStream.
    • .read() opens the resource as a ByteBuffer. Note that you must call .close() on the Resource when you are finished with this ByteBuffer to release the ByteBuffer. Alternatively, call Resource#readCloseable() instead (see below).
    • .readCloseable() returns a CloseableByteBuffer that implements the Closeable interface, so that when its close() method is called, it automatically calls Resource#close() to release the wrapped ByteBuffer. Call CloseableByteBuffer#getByteBuffer() to get the wrapped ByteBuffer.
    • .load() loads the entire content of the resource as a byte[] array. (This calls .close() on the Resource once all content is loaded.)
    • **.getContentAsString()** is a convenience method that calls .load() to get the resource content, then defines and returns String. (Assumes UTF8 encoding.)
    • .close() closes the underlying InputStream or releases/unmaps the underlying ByteBuffer for the Resource.
  • Reading resource metadata:

    • .getLength() returns the length of the resource in bytes, or -1 if unknown. The value generally remains unknown until .read() or .load() is called. If you call .open(), the length of the resulting InputStream may or may not be known.
    • getPosixPermissions() returns the POSIX file permissions for the Resource as a Set<PosixFilePermission>, obtained from either the directory entry for the containing directory (for dir-based resources), or the zipfile central directory (for jarfile resources). If not available or unknown (e.g. for system module resources or jlink'd resources), returns null.
    • getLastModified() returns the last modified timestamp for the resource (in milliseconds since the epoch), if known. If not available or unknown (e.g. for system module resources or jlink'd resources), returns 0L.
    • .getPath() returns the path of the resource, relative to the package root, as a String. For example, for a resource path of BOOT-INF/classes/com/xyz/resource.xml and a package root of BOOT-INF/classes/, returns com/xyz/resource.xml.
    • .getPathRelativeToClasspathElement() returns the path of the resource relative to the classpath element (instead of relative to the package root) as a String. For example, for a resource path of BOOT-INF/classes/com/xyz/resource.xml, returns BOOT-INF/classes/com/xyz/resource.xml, even if the package root is BOOT-INF/classes/.
    • .getURI() returns a URI for the resource.
    • .getURL() returns a URL for the resource. Note that this will throw IllegalArgumentException if the resource was obtained from a system module or a jlink'd runtime image, since the URI scheme of jrt: is only supported by URI, not by URL.
    • .getClasspathElementURI() returns a URI for the classpath element containing the resource.
    • .getClasspathElementURL() returns a URL for the classpath element containing the resource. Note that this will throw IllegalArgumentException if the resource was obtained from a system module or a jlink'd runtime image, since the URI scheme of jrt: is only supported by URI, not by URL.
    • .getClasspathElementFile() returns a File for the classpath element containing the resource, or null if the resource was contained in a system module or jlinkd runtime image (since the .getClasspathElementURI()will return aURIwithjrt:` scheme, which cannot be resolved to a file).
    • .getModuleRef() returns a ModuleRef for the module containing the resource, or null if the resource was contained in a directory or jarfile on the traditional classpath.

ResourceList

Extends ArrayList<Resource> with the following convenience methods:

  • Converting to Map:
    • .asMap() returns the ResourceList as a Map<String, ResourceList> that maps paths to a ResourceList of resources that have each path.

      💡 If the resource path is duplicated across different classpath elements, the ResourceList in the map values will contain more than one element. See also .findDuplicatePaths().

  • Reading resource metadata for each Resource in the list:
    • .getPaths() returns a list of the paths of resources in this list relative to the package root, by calling .getPath() for each Resource in the list. Returns a List<String>.
    • .getPathsRelativeToClasspathElement() returns a list of the paths of resources in this list relative to the classpath element (instead of relative to the package root) by calling .getPathRelativeToClasspathElement() for each Resource in the list. Returns a List<String>.
    • .getURLs() returns a list of the URLs of resources in this list, as a List<URL>. You should probably use .getURIs() instead, since resource URIs can contain jrt:/ schemes if the resource is in a jlink'd image or a system module, and URL does not support this scheme.
    • .getURIs() returns a list of the URIs of resources in this list, as a List<URI>.
    • .getAsStrings() returns a list of the result of calling .toString() on each Resource object in this list, producing a List<string> of String representations of each Resource location.
  • Filtering Resource elements:
    • .filter(ResourceFilter filter) returns a ResourceList that is a subset of the original list, obtained by applying the given filter predicate to each Resource in the list.
      • ResourceFilter is a FunctionalInterface with the single abstract method boolean accept(Resource resource).
    • .classFilesOnly() returns a ResourceList that is the subset of the original list whose Resource paths end with ".class".
    • .nonClassFilesOnly() returns a ResourceList that is the subset of the original list whose Resource paths do not end with ".class".
  • Finding resources with duplicate paths:
    • .findDuplicatePaths() returns all Resource elements in this ResourceList with duplicated paths, as a List<Entry<String, ResourceList>> set of Entry pairs, with the path as the key, and the ResourceList (consisting of two or more Resource elements) as the value.
  • Reading content of each Resource in the list: (these methods all have unique names to avoid running into problems of ambiguous overloaded method resolution when lambdas are used rather than classes for the consumer parameter):

    💡 ClassGraph will transparently translate the mechanism for accessing the underlying resource type (whether the resource is a file in a directory, or an entry in a jarfile, or a resource in a module) to ByteBuffer, InputStream or byte[] array, in the most efficient manner possible.

    • .forEachByteArrayIgnoringIOException(ByteArrayConsumer consumer) loads the complete content of each resource in the list, calls the ByteArrayConsumer with the content, then calls Resource#close() to clean up resources. Any IOException thrown while trying to open or read a resource causes the resource to be skipped.
      • ByteArrayConsumer is a FunctionalInterface with the single abstract method void accept(Resource resource, byte[] byteArray)
    • .forEachByteArrayThrowingIOException(ByteArrayConsumerThrowsIOException consumer) loads the complete content of each resource in the list, calls the ByteArrayConsumer with the content, then calls Resource#close() to clean up resources. Any IOException thrown while trying to open or read a resource causes the exception to be thrown to the caller.
      • ByteArrayConsumerThrowsIOException is a FunctionalInterface with the single abstract method void accept(Resource resource, byte[] byteArray) throws IOException
    • .forEachInputStreamIgnoringIOException(InputStreamConsumer consumer) opens each resource in the list as an InputStream, calls the InputStreamConsumer with the content, then calls Resource#close() to close the InputStream. Any IOException thrown while trying to open or read a resource causes the resource to be skipped.
      • InputStreamConsumer is a FunctionalInterface with the single abstract method void accept(Resource resource, InputStream inputStream)
    • .forEachInputStreamThrowingingIOException(InputStreamConsumerThrowsIOException consumer) opens each resource in the list as an InputStream, calls the InputStreamConsumer with the content, then calls Resource#close() to close the InputStream. Any IOException thrown while trying to open or read a resource causes the resource to be thrown to the caller.
      • InputStreamConsumerThrowsIOException is a FunctionalInterface with the single abstract method void accept(Resource resource, InputStream inputStream) throws IOException
    • .forEachByteBufferIgnoringIOException(InputStreamConsumer consumer) opens each resource in the list as a ByteBuffer (memory-mapped if possible), calls the ByteBufferConsumer with the content, then calls Resource#close() to release the ByteBuffer. Any IOException thrown while trying to open or read a resource causes the resource to be skipped.
      • ByteBufferConsumer is a FunctionalInterface with the single abstract method void accept(Resource resource, ByteBuffer byteBuffer)
    • .forEachByteBufferThrowingIOException(InputStreamConsumerThrowsIOException consumer) opens each resource in the list as a ByteBuffer (memory-mapped if possible), calls the ByteBufferConsumer with the content, then calls Resource#close() to release the ByteBuffer. Any IOException thrown while trying to open or read a resource causes the resource to be thrown to the caller.
      • ByteBufferConsumerThrowsIOException is a FunctionalInterface with the single abstract method void accept(Resource resource, ByteBuffer byteBuffer) throws IOException
Clone this wiki locally