Class NestedJarHandler
- java.lang.Object
-
- nonapi.io.github.classgraph.fastzipfilereader.NestedJarHandler
-
public class NestedJarHandler extends java.lang.Object
Open and read jarfiles, which may be nested within other jarfiles.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
NestedJarHandler.CloseableUrlConnection
private static class
NestedJarHandler.RecyclableInflater
Wrapper class that allows anInflater
instance to be reset for reuse and then recycled by aRecycler
.
-
Field Summary
Fields Modifier and Type Field Description private SingletonMap<java.io.File,PhysicalZipFile,java.io.IOException>
canonicalFileToPhysicalZipFileMap
A singleton map from a zipfile'sFile
to thePhysicalZipFile
for that file, used to ensure that theRandomAccessFile
andFileChannel
for any given zipfile is opened only once.private java.util.concurrent.atomic.AtomicBoolean
closed
True ifclose(LogNode)
has been called.private static int
DEFAULT_BUFFER_SIZE
The default size of a file buffer.private SingletonMap<FastZipEntry,ZipFileSlice,java.io.IOException>
fastZipEntryToZipFileSliceMap
A singleton map from aFastZipEntry
to theZipFileSlice
wrapping either the zip entry data, if the entry is stored, or a ByteBuffer, if the zip entry was inflated to memory, or a physical file on disk if the zip entry was inflated to a temporary file.private static int
HTTP_TIMEOUT
HTTP(S) timeout, ms.private Recycler<NestedJarHandler.RecyclableInflater,java.lang.RuntimeException>
inflaterRecycler
A recycler forInflater
instances.InterruptionChecker
interruptionChecker
The interruption checker.private static int
MAX_INITIAL_BUFFER_SIZE
The maximum initial buffer size.SingletonMap<ModuleRef,Recycler<ModuleReaderProxy,java.io.IOException>,java.io.IOException>
moduleRefToModuleReaderProxyRecyclerMap
A singleton map from aModuleRef
to aModuleReaderProxy
recycler for the module.SingletonMap<java.lang.String,java.util.Map.Entry<LogicalZipFile,java.lang.String>,java.io.IOException>
nestedPathToLogicalZipFileAndPackageRootMap
A singleton map from nested jarfile path to a tuple of the logical zipfile for the path, and the package root within the logical zipfile.private java.util.Set<Slice>
openSlices
FileSlice
instances that are currently open.ReflectionUtils
reflectionUtils
private static java.lang.reflect.Method
runFinalizationMethod
System.runFinalization() -- deprecated in JDK 18, so accessed by reflection.ScanSpec
scanSpec
TheScanSpec
.static java.lang.String
TEMP_FILENAME_LEAF_SEPARATOR
The separator between random temp filename part and leafname.private java.util.Set<java.io.File>
tempFiles
Any temporary files created while scanning.private SingletonMap<ZipFileSlice,LogicalZipFile,java.io.IOException>
zipFileSliceToLogicalZipFileMap
A singleton map from aZipFileSlice
to theLogicalZipFile
for that slice.
-
Constructor Summary
Constructors Constructor Description NestedJarHandler(ScanSpec scanSpec, InterruptionChecker interruptionChecker, ReflectionUtils reflectionUtils)
A handler for nested jars.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
close(LogNode log)
Close zipfiles, modules, and recyclers, and delete temporary files.void
closeDirectByteBuffer(java.nio.ByteBuffer backingByteBuffer)
private PhysicalZipFile
downloadJarFromURL(java.lang.String jarURL, LogNode log)
Download a jar from a URL to a temporary file, or to a ByteBuffer if the temporary directory is not writeable or full.private static java.lang.String
leafname(java.lang.String path)
Get the leafname of a path.java.io.File
makeTempFile(java.lang.String filePathBase, boolean onlyUseLeafname)
Create a temporary file, and mark it for deletion on exit.void
markSliceAsClosed(Slice slice)
Mark aSlice
as closed.void
markSliceAsOpen(Slice slice)
Mark aSlice
as open, so it can be closed when theScanResult
is closed.java.io.InputStream
openInflaterInputStream(java.io.InputStream rawInputStream)
Wrap anInputStream
with anInflaterInputStream
, recycling theInflater
instance.static byte[]
readAllBytesAsArray(java.io.InputStream inputStream, long uncompressedLengthHint)
Read all the bytes in anInputStream
.Slice
readAllBytesWithSpilloverToDisk(java.io.InputStream inputStream, java.lang.String tempFileBaseName, long inputStreamLengthHint, LogNode log)
Read all the bytes in anInputStream
, with spillover to a temporary file on disk if a maximum buffer size is exceeded.(package private) void
removeTempFile(java.io.File tempFile)
Attempt to remove a temporary file.void
runFinalizationMethod()
private java.lang.String
sanitizeFilename(java.lang.String filename)
Sanitize filename.private FileSlice
spillToDisk(java.io.InputStream inputStream, java.lang.String tempFileBaseName, byte[] buf, byte[] overflowBuf, LogNode log)
Spill anInputStream
to disk if the stream is too large to fit in RAM.
-
-
-
Field Detail
-
reflectionUtils
public ReflectionUtils reflectionUtils
-
canonicalFileToPhysicalZipFileMap
private SingletonMap<java.io.File,PhysicalZipFile,java.io.IOException> canonicalFileToPhysicalZipFileMap
A singleton map from a zipfile'sFile
to thePhysicalZipFile
for that file, used to ensure that theRandomAccessFile
andFileChannel
for any given zipfile is opened only once.
-
fastZipEntryToZipFileSliceMap
private SingletonMap<FastZipEntry,ZipFileSlice,java.io.IOException> fastZipEntryToZipFileSliceMap
A singleton map from aFastZipEntry
to theZipFileSlice
wrapping either the zip entry data, if the entry is stored, or a ByteBuffer, if the zip entry was inflated to memory, or a physical file on disk if the zip entry was inflated to a temporary file.
-
zipFileSliceToLogicalZipFileMap
private SingletonMap<ZipFileSlice,LogicalZipFile,java.io.IOException> zipFileSliceToLogicalZipFileMap
A singleton map from aZipFileSlice
to theLogicalZipFile
for that slice.
-
nestedPathToLogicalZipFileAndPackageRootMap
public SingletonMap<java.lang.String,java.util.Map.Entry<LogicalZipFile,java.lang.String>,java.io.IOException> nestedPathToLogicalZipFileAndPackageRootMap
A singleton map from nested jarfile path to a tuple of the logical zipfile for the path, and the package root within the logical zipfile.
-
moduleRefToModuleReaderProxyRecyclerMap
public SingletonMap<ModuleRef,Recycler<ModuleReaderProxy,java.io.IOException>,java.io.IOException> moduleRefToModuleReaderProxyRecyclerMap
A singleton map from aModuleRef
to aModuleReaderProxy
recycler for the module.
-
inflaterRecycler
private Recycler<NestedJarHandler.RecyclableInflater,java.lang.RuntimeException> inflaterRecycler
A recycler forInflater
instances.
-
tempFiles
private java.util.Set<java.io.File> tempFiles
Any temporary files created while scanning.
-
TEMP_FILENAME_LEAF_SEPARATOR
public static final java.lang.String TEMP_FILENAME_LEAF_SEPARATOR
The separator between random temp filename part and leafname.- See Also:
- Constant Field Values
-
closed
private final java.util.concurrent.atomic.AtomicBoolean closed
True ifclose(LogNode)
has been called.
-
interruptionChecker
public InterruptionChecker interruptionChecker
The interruption checker.
-
DEFAULT_BUFFER_SIZE
private static final int DEFAULT_BUFFER_SIZE
The default size of a file buffer.- See Also:
- Constant Field Values
-
MAX_INITIAL_BUFFER_SIZE
private static final int MAX_INITIAL_BUFFER_SIZE
The maximum initial buffer size.- See Also:
- Constant Field Values
-
HTTP_TIMEOUT
private static final int HTTP_TIMEOUT
HTTP(S) timeout, ms.- See Also:
- Constant Field Values
-
runFinalizationMethod
private static java.lang.reflect.Method runFinalizationMethod
System.runFinalization() -- deprecated in JDK 18, so accessed by reflection.
-
-
Constructor Detail
-
NestedJarHandler
public NestedJarHandler(ScanSpec scanSpec, InterruptionChecker interruptionChecker, ReflectionUtils reflectionUtils)
A handler for nested jars.- Parameters:
scanSpec
- TheScanSpec
.interruptionChecker
- the interruption checker
-
-
Method Detail
-
leafname
private static java.lang.String leafname(java.lang.String path)
Get the leafname of a path.- Parameters:
path
- the path- Returns:
- the string
-
sanitizeFilename
private java.lang.String sanitizeFilename(java.lang.String filename)
Sanitize filename.- Parameters:
filename
- the filename- Returns:
- the sanitized filename
-
makeTempFile
public java.io.File makeTempFile(java.lang.String filePathBase, boolean onlyUseLeafname) throws java.io.IOException
Create a temporary file, and mark it for deletion on exit.- Parameters:
filePathBase
- The path to derive the temporary filename from.onlyUseLeafname
- If true, only use the leafname of filePath to derive the temporary filename.- Returns:
- The temporary
File
. - Throws:
java.io.IOException
- If the temporary file could not be created.
-
removeTempFile
void removeTempFile(java.io.File tempFile) throws java.io.IOException, java.lang.SecurityException
Attempt to remove a temporary file.- Parameters:
tempFile
- the temp file- Throws:
java.io.IOException
- If the temporary file could not be removed.java.lang.SecurityException
- If the temporary file is inaccessible.
-
markSliceAsOpen
public void markSliceAsOpen(Slice slice) throws java.io.IOException
Mark aSlice
as open, so it can be closed when theScanResult
is closed.- Parameters:
slice
- theSlice
that was just opened.- Throws:
java.io.IOException
- Signals that an I/O exception has occurred.
-
markSliceAsClosed
public void markSliceAsClosed(Slice slice)
Mark aSlice
as closed.- Parameters:
slice
- theSlice
to close.
-
downloadJarFromURL
private PhysicalZipFile downloadJarFromURL(java.lang.String jarURL, LogNode log) throws java.io.IOException, java.lang.InterruptedException
Download a jar from a URL to a temporary file, or to a ByteBuffer if the temporary directory is not writeable or full. The downloaded jar is returned wrapped in aPhysicalZipFile
instance.- Parameters:
jarURL
- the jar URLlog
- the log- Returns:
- the temporary file or
ByteBuffer
the jar was downloaded to, wrapped in aPhysicalZipFile
instance. - Throws:
java.io.IOException
- If the jar could not be downloaded, or the jar URL is malformed.java.lang.InterruptedException
- if the thread was interruptedjava.lang.IllegalArgumentException
- If the temp dir is not writeable, or has insufficient space to download the jar. (This is thrown as a separate exception from IOException, so that the case of an unwriteable temp dir can be handled separately, by downloading the jar to a ByteBuffer in RAM.)
-
openInflaterInputStream
public java.io.InputStream openInflaterInputStream(java.io.InputStream rawInputStream) throws java.io.IOException
Wrap anInputStream
with anInflaterInputStream
, recycling theInflater
instance.- Parameters:
rawInputStream
- the raw input stream- Returns:
- the inflater input stream
- Throws:
java.io.IOException
- Signals that an I/O exception has occurred.
-
readAllBytesWithSpilloverToDisk
public Slice readAllBytesWithSpilloverToDisk(java.io.InputStream inputStream, java.lang.String tempFileBaseName, long inputStreamLengthHint, LogNode log) throws java.io.IOException
Read all the bytes in anInputStream
, with spillover to a temporary file on disk if a maximum buffer size is exceeded.- Parameters:
inputStream
- theInputStream
to read from.tempFileBaseName
- the source URL or zip entry that inputStream was opened from (used to name temporary file, if needed).inputStreamLengthHint
- the length of inputStream if known, else -1L.log
- the log.- Returns:
- if the
InputStream
could be read into a byte array, anArraySlice
will be returned. If this fails and theInputStream
is spilled over to disk, aFileSlice
will be returned. - Throws:
java.io.IOException
- If the contents could not be read.
-
spillToDisk
private FileSlice spillToDisk(java.io.InputStream inputStream, java.lang.String tempFileBaseName, byte[] buf, byte[] overflowBuf, LogNode log) throws java.io.IOException
Spill anInputStream
to disk if the stream is too large to fit in RAM.- Parameters:
inputStream
- TheInputStream
.tempFileBaseName
- The stem to base the temporary filename on.buf
- The first buffer to write to the beginning of the file, or null if none.overflowBuf
- The second buffer to write to the beginning of the file, or null if none. (Should have same nullity as buf.)log
- The log.- Returns:
- the file slice
- Throws:
java.io.IOException
- If anything went wrong creating or writing to the temp file.
-
readAllBytesAsArray
public static byte[] readAllBytesAsArray(java.io.InputStream inputStream, long uncompressedLengthHint) throws java.io.IOException
Read all the bytes in anInputStream
.- Parameters:
inputStream
- TheInputStream
.uncompressedLengthHint
- The length of the data once inflated from theInputStream
, if known, otherwise -1L.- Returns:
- The contents of the
InputStream
as a byte array. - Throws:
java.io.IOException
- If the contents could not be read.
-
close
public void close(LogNode log)
Close zipfiles, modules, and recyclers, and delete temporary files. Called byScanResult.close()
.- Parameters:
log
- The log.
-
runFinalizationMethod
public void runFinalizationMethod()
-
closeDirectByteBuffer
public void closeDirectByteBuffer(java.nio.ByteBuffer backingByteBuffer)
-
-