public class NestedJarHandler extends Object
Somewhat paradoxically, the fastest way to support scanning zipfiles-within-zipfiles is to unzip the inner zipfile to a temporary file on disk, because the inner zipfile can only be read using ZipInputStream, not ZipFile (the ZipFile constructors only take a File argument). ZipInputStream doesn't have methods for reading the zip directory at the beginning of the stream, so using ZipInputStream rather than ZipFile, you have to decompress the entire zipfile to read all the directory entries. However, there may be many non-whitelisted entries in the zipfile, so this could be a lot of wasted work.
ClassGraph makes two passes, one to read the zipfile directory, which whitelist and blacklist criteria are applied to (this is a fast operation when using ZipFile), and then an additional pass to read only whitelisted (non-blacklisted) entries. Therefore, in the general case, the ZipFile API is always going to be faster than ZipInputStream. Therefore, decompressing the inner zipfile to disk is the only efficient option.
Modifier and Type | Field | Description |
---|---|---|
static String |
TEMP_FILENAME_LEAF_SEPARATOR |
The separator between random temp filename part and leafname.
|
Constructor | Description |
---|---|
NestedJarHandler(ScanSpec scanSpec,
LogNode log) |
A handler for nested jars.
|
Modifier and Type | Method | Description |
---|---|---|
void |
close(LogNode log) |
Close zipfiles and modules, and delete temporary files.
|
void |
closeRecyclers() |
Close zipfiles and modules.
|
Map.Entry<File,Set<String>> |
getInnermostNestedJar(String nestedJarPath,
LogNode log) |
Get a File for a given (possibly nested) jarfile path, unzipping the first N-1 segments of an N-segment
'!'-delimited path to temporary files, then returning the File reference for the N-th temporary file.
|
JarfileMetadataReader |
getJarfileMetadataReader(File zipFile,
String jarfilePackageRoot,
LogNode log) |
Get a
JarfileMetadataReader singleton for a given jarfile (so that the manifest and ZipEntries will
only be read once). |
Recycler<ModuleReaderProxy,IOException> |
getModuleReaderProxyRecycler(ModuleRef moduleRef,
LogNode log) |
Get a ModuleReaderProxy recycler given a ModuleRef.
|
File |
getOutermostJar(File jarFile) |
Given a File reference for an inner nested jarfile, find the outermost jarfile it was extracted from.
|
Recycler<ZipFile,IOException> |
getZipFileRecycler(File zipFile,
LogNode log) |
Get a ZipFile recycler given the (non-nested) canonical path of a jarfile.
|
public static final String TEMP_FILENAME_LEAF_SEPARATOR
public Recycler<ZipFile,IOException> getZipFileRecycler(File zipFile, LogNode log) throws Exception
zipFile
- The zipfile.log
- The log.Exception
- If the zipfile could not be opened.public JarfileMetadataReader getJarfileMetadataReader(File zipFile, String jarfilePackageRoot, LogNode log) throws Exception
JarfileMetadataReader
singleton for a given jarfile (so that the manifest and ZipEntries will
only be read once).zipFile
- The zipfile.jarfilePackageRoot
- The package root within the zipfile.log
- The log.JarfileMetadataReader
.Exception
- If the zipfile could not be opened.public Recycler<ModuleReaderProxy,IOException> getModuleReaderProxyRecycler(ModuleRef moduleRef, LogNode log) throws Exception
public Map.Entry<File,Set<String>> getInnermostNestedJar(String nestedJarPath, LogNode log) throws Exception
If the path does not contain '!', returns the File represented by the path.
All path segments should end in a jarfile extension, e.g. ".jar" or ".zip".
nestedJarPath
- The nested jar path.log
- The log.Entry<File, Set<String>>
, where the File
is the innermost jar, and the
Set<String>
is the set of all relative paths of scanning roots within the innermost jar (may
be empty, or may contain strings like "target/classes" or similar). If there was an issue with the
path, returns null.Exception
- If the innermost jarfile could not be extracted.public File getOutermostJar(File jarFile)
jarFile
- The jarfile.public void closeRecyclers()
public void close(LogNode log)
log
- The log.Copyright © 2018. All rights reserved.