Add a `NestedFileSystemProvider` implementation so that the JDK's
`ZipFileSystem` can load content from nested jars and nested
directory entries.
Creating a `ZipFileSystem` may be a relatively expensive operation as
zip structures need to be parsed and in the case of directory entries
a virtual datablock nees to be generated on the fly. As such, we
install the `ZipFileSystem` as late as possible since in a typical
application it may never be needed.
This commit also tweaks Gradle and Maven plugins to ensure that the
service loader file is written to repackaged jars.
Closes gh-7161
Update Gradle and Maven plugins to write an empty `META-INF/BOOT.SF`
file whenever there is a nested signed jar.
This update allows Oracle Java 17 to correctly verify the nested JARs.
The file is required because `JarVerifier` has code roughly equivalent
to:
if (!jarManifestNameChecked && SharedSecrets
.getJavaUtilZipFileAccess().getManifestName(jf, true) == null) {
throw new JarException("The JCE Provider " + jarURL.toString() +
" is not signed.");
}
The `SharedSecrets.getJavaUtilZipFileAccess().getManifestName(jf, true)`
call ends up in `ZipFile.getManifestName(onlyIfSignatureRelatedFiles)`
which is a private method that we cannot override in our `NestedJarFile`
subclass. By writing an empty `.SF` file we ensure that the `Manifest`
is always returned because there are always "signature related files".
Fixes gh-28837
Update `DefaultCleanerTracking` and `@AssertFileChannelDataBlocksClosed`
to capture and store the source object if it is a `Cleanable` so that
it can be released later.
Although the real cleaner cannot keep a reference to `obj`, it is safe
for us to do so in tests since we are in control of the object lifecycle
and we don't need it to be garbage collected.
This commit also updates the `UrlJarFile` to call the cleaner so that
it can be tracked.
See gh-37668
Update `NestedJarFile.close()` to call `super.close()` so that the outer
jar file is closed and files can hopefully be deleted on Windows.
See gh-37668
Rewrite nested jar code to better align with the implementations
provided in Java 17. This update makes two fundamental changes to
the previous implementation:
- Resource cleanup is now handled using the `java.lang.ref.Cleaner`
- Jar URLs now use the form `jar:nested:/my.jar/!nested.jar!/entry`
Unlike the previous `jar🫙/my,jar!/nested.jar!/entry` URL format,
the new format is compatible with Java's default Jar URL handler.
Specifically, it now only uses a single `jar:` prefix and it no longer
includes multiple `!/` separators.
In addition to the changes above, many of the ancillary classes have
also been refactored and updated to create cleaner APIs.
Closes gh-37668