Previously, available() would return 0 initially and then negative
values once some data head been read. It should be a positive value
(for entries with content) initially a decrease as data is read
reaching zero once an entry's data has been read in its entirety.
This commit initialises the count of the remaining bytes to
be equal to the entry's uncompressed size. It also removes logic
that closes the stream when remaining equals zero upon read or skip.
This condition was not reached before as remaining would become
negative as soon as any data was read or skipped. With the correct
initialization of remaining, the condition is now reached and it
results in test failures due to premature closure. Furthermore, the
javadoc of read and skip do not require the stream to be closed
when the reach end of file.
Closes gh-47056
Replace the string based `JarFileUrlKey` and cache with a simple key
built directly from URL components. This should allow cache lookups
to remain fast whilst removing any `URLStreamHandler.getHostAddress`
calls.
Prior to this commit, we assumed that it was safe to use the URL
directly as a cache key as long as it had an empty or null `host`.
This assumption isn't correct when Palo Alto Network Cortex XDR agent
is present as it appears to intercept calls to `getHostAddress`
and, unlike the JDK code, always perform a DNS lookup.
Fixes gh-46401
Update `JarFileUrlKey` so that only URLs that have a cheap `equals()`
method call are cached. This should prevent expensive DNS lookups from
being performed.
Fixes gh-46015
Update jar mode launchers to catch all exceptions and return a non-zero
exit code. This refinement also allows us to consolidate the existing
error reporting logic to a central locations. Modes that wish to report
a simple error rather than a full stacktrace can throw the newly
introduced `JarModeErrorException`.
Fixes gh-43435
Update `Path` creation for nested locations to allow both UNC and classic
file references to be used. This commit attempts to align our URL
handling with that of standard file URLs. The `NestedLocation` class
no longer attempts to remove leading all `\` characters and instead
only removes the first `\` when the second char is `:`. This duplicates
the logic found in Java's own internal `WindowsUriSupport` class which
is used when calling `Path.of(url)` with a `file:` URL.
Fixes gh-40549
Fix regression in `JarUrlConnection` where a NullPointerException could
be thrown internally causing performance issues.
When the SecurityManager is present, the following stack trace is
thrown:
java.lang.NullPointerException: Cannot invoke "java.net.URLConnection.getPermission()" because "this.jarFileConnection" is null
at org.springframework.boot.loader.net.protocol.jar.JarUrlConnection.getPermission(JarUrlConnection.java:175)
at java.base/jdk.internal.loader.URLClassPath.check(URLClassPath.java:553)
at java.base/jdk.internal.loader.URLClassPath$Loader.findResource(URLClassPath.java:612)
at java.base/jdk.internal.loader.URLClassPath.findResource(URLClassPath.java:296)
at java.base/java.net.URLClassLoader$2.run(URLClassLoader.java:629)
at java.base/java.net.URLClassLoader$2.run(URLClassLoader.java:627)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.net.URLClassLoader.findResource(URLClassLoader.java:626)
at org.springframework.boot.loader.net.protocol.jar.JarUrlClassLoader.findResource(JarUrlClassLoader.java:70)
at java.base/java.lang.ClassLoader.getResource(ClassLoader.java:1403)
at java.base/java.net.URLClassLoader.getResourceAsStream(URLClassLoader.java:290)
at java.base/java.lang.Class.getResourceAsStream(Class.java:2850)
See gh-39856
Refine the fix for gh-38611 so that `ClosedByInterruptException` no
longer retries in a loop.
Our previous fix was flawed due to the fact that another interrupt
could occur after we clear the first and whilst we are reading data.
If this happens 10 times in a row, we raise an exception and end up
causing NoClassDefFoundError errors.
Our new approach retains the use of `FileChannel` and a direct buffer
up to the point that a `ClosedByInterruptException` is raised or the
thread is detected as interrupted. At that point, we temporarily
switch to using a `RandomAccessFile` to access the data. This will
block the thread until the data has been read.
Fixes gh-40096
Rename the internal `FileChannelDataBlock` to `FileDataBlock` since we
want to fallback to a `RandomAccessFile` when a thread is interrupted.
See gh-40096
URL can contains empty spaced encoded as %20, so it should be decoded
before passing it to NestedLocation. NestedLocation expects file system
path which should not contain URL encoded values.
See gh-39675