Class NestedJarHandler
- java.lang.Object
-
- nonapi.io.github.classgraph.fastzipfilereader.NestedJarHandler
-
public class NestedJarHandler extends java.lang.ObjectOpen and read jarfiles, which may be nested within other jarfiles.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static classNestedJarHandler.CloseableUrlConnectionprivate static classNestedJarHandler.RecyclableInflaterWrapper class that allows anInflaterinstance 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>canonicalFileToPhysicalZipFileMapA singleton map from a zipfile'sFileto thePhysicalZipFilefor that file, used to ensure that theRandomAccessFileandFileChannelfor any given zipfile is opened only once.private java.util.concurrent.atomic.AtomicBooleanclosedTrue ifclose(LogNode)has been called.private static intDEFAULT_BUFFER_SIZEThe default size of a file buffer.private SingletonMap<FastZipEntry,ZipFileSlice,java.io.IOException>fastZipEntryToZipFileSliceMapA singleton map from aFastZipEntryto theZipFileSlicewrapping 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 intHTTP_TIMEOUTHTTP(S) timeout, ms.private Recycler<NestedJarHandler.RecyclableInflater,java.lang.RuntimeException>inflaterRecyclerA recycler forInflaterinstances.InterruptionCheckerinterruptionCheckerThe interruption checker.private static intMAX_INITIAL_BUFFER_SIZEThe maximum initial buffer size.SingletonMap<ModuleRef,Recycler<ModuleReaderProxy,java.io.IOException>,java.io.IOException>moduleRefToModuleReaderProxyRecyclerMapA singleton map from aModuleRefto aModuleReaderProxyrecycler for the module.SingletonMap<java.lang.String,java.util.Map.Entry<LogicalZipFile,java.lang.String>,java.io.IOException>nestedPathToLogicalZipFileAndPackageRootMapA 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>openSlicesFileSliceinstances that are currently open.ReflectionUtilsreflectionUtilsprivate static java.lang.reflect.MethodrunFinalizationMethodSystem.runFinalization() -- deprecated in JDK 18, so accessed by reflection.ScanSpecscanSpecTheScanSpec.static java.lang.StringTEMP_FILENAME_LEAF_SEPARATORThe separator between random temp filename part and leafname.private java.util.Set<java.io.File>tempFilesAny temporary files created while scanning.private SingletonMap<ZipFileSlice,LogicalZipFile,java.io.IOException>zipFileSliceToLogicalZipFileMapA singleton map from aZipFileSliceto theLogicalZipFilefor 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 voidclose(LogNode log)Close zipfiles, modules, and recyclers, and delete temporary files.voidcloseDirectByteBuffer(java.nio.ByteBuffer backingByteBuffer)private PhysicalZipFiledownloadJarFromURL(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.Stringleafname(java.lang.String path)Get the leafname of a path.java.io.FilemakeTempFile(java.lang.String filePathBase, boolean onlyUseLeafname)Create a temporary file, and mark it for deletion on exit.voidmarkSliceAsClosed(Slice slice)Mark aSliceas closed.voidmarkSliceAsOpen(Slice slice)Mark aSliceas open, so it can be closed when theScanResultis closed.java.io.InputStreamopenInflaterInputStream(java.io.InputStream rawInputStream)Wrap anInputStreamwith anInflaterInputStream, recycling theInflaterinstance.static byte[]readAllBytesAsArray(java.io.InputStream inputStream, long uncompressedLengthHint)Read all the bytes in anInputStream.SlicereadAllBytesWithSpilloverToDisk(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) voidremoveTempFile(java.io.File tempFile)Attempt to remove a temporary file.voidrunFinalizationMethod()private java.lang.StringsanitizeFilename(java.lang.String filename)Sanitize filename.private FileSlicespillToDisk(java.io.InputStream inputStream, java.lang.String tempFileBaseName, byte[] buf, byte[] overflowBuf, LogNode log)Spill anInputStreamto 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'sFileto thePhysicalZipFilefor that file, used to ensure that theRandomAccessFileandFileChannelfor any given zipfile is opened only once.
-
fastZipEntryToZipFileSliceMap
private SingletonMap<FastZipEntry,ZipFileSlice,java.io.IOException> fastZipEntryToZipFileSliceMap
A singleton map from aFastZipEntryto theZipFileSlicewrapping 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 aZipFileSliceto theLogicalZipFilefor 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 aModuleRefto aModuleReaderProxyrecycler for the module.
-
inflaterRecycler
private Recycler<NestedJarHandler.RecyclableInflater,java.lang.RuntimeException> inflaterRecycler
A recycler forInflaterinstances.
-
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.IOExceptionCreate 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.SecurityExceptionAttempt 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 aSliceas open, so it can be closed when theScanResultis closed.- Parameters:
slice- theSlicethat was just opened.- Throws:
java.io.IOException- Signals that an I/O exception has occurred.
-
markSliceAsClosed
public void markSliceAsClosed(Slice slice)
Mark aSliceas closed.- Parameters:
slice- theSliceto 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 aPhysicalZipFileinstance.- Parameters:
jarURL- the jar URLlog- the log- Returns:
- the temporary file or
ByteBufferthe jar was downloaded to, wrapped in aPhysicalZipFileinstance. - 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.IOExceptionWrap anInputStreamwith anInflaterInputStream, recycling theInflaterinstance.- 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- theInputStreamto 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
InputStreamcould be read into a byte array, anArraySlicewill be returned. If this fails and theInputStreamis spilled over to disk, aFileSlicewill 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 anInputStreamto 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.IOExceptionRead 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
InputStreamas 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)
-
-