/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This class implements the building of index of a zip archive and access to
* its context. It also uses a prebuilt index if available.
* It supports invocations where it will serialize an optimized zip index file
* to disk.
*
* In order to use a secondary index file, set "usezipindex" in the Options
* object when JavacFileManager is invoked. (You can pass "-XDusezipindex" on
* the command line.)
*
* provided using "-XDcachezipindexdir=<directory>". If this flag is not
* provided, the default location is the value of the "java.io.tmpdir" system
* property.
*
* If "-XDwritezipindexfiles" is specified, there will be new optimized index
* file created for each archive, used by the compiler for compilation, at the
* location specified by the "cachezipindexdir" option.
*
* If system property nonBatchMode option is specified the compiler will use
* timestamp checking to reindex the zip files if it is needed. In batch mode
* the timestamps are not checked and the compiler uses the cached indexes.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class ZipFileIndex {
private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
// ZipFileIndex data entries
private boolean readFromIndex = false;
private boolean triedToReadIndex = false;
private final int symbolFilePrefixLength;
private boolean hasPopulatedData = false;
private final boolean usePreindexedCache;
private boolean writeIndex = false;
public synchronized boolean isOpen() {
return (zipRandomFile != null);
}
this.symbolFilePrefix = symbolFilePrefix;
this.writeIndex = writeIndex;
this.usePreindexedCache = useCache;
this.preindexedCacheLocation = cacheLocation;
}
// Validate integrity of the zip file
checkIndex();
}
}
// Just in case...
closeFile();
super.finalize();
}
private boolean isUpToDate() {
&& hasPopulatedData) {
return true;
}
return false;
}
/**
* Here we need to make sure that the ZipFileIndex is valid. Check the timestamp of the file and
* if its the same as the one at the time the index was build we don't need to reopen anything.
*/
boolean isUpToDate = true;
if (!isUpToDate()) {
closeFile();
isUpToDate = false;
}
return;
}
hasPopulatedData = true;
if (readIndex()) {
return;
}
try {
openFile();
} finally {
if (zipRandomFile != null) {
closeFile();
}
}
}
}
}
private void cleanupState() {
// Make sure there is a valid but empty index if the file doesn't exist
}
public synchronized void close() {
writeIndex();
closeFile();
}
private void closeFile() {
if (zipRandomFile != null) {
try {
} catch (IOException ex) {
}
}
}
/**
* Returns the ZipFileIndexEntry for a path, if there is one.
*/
try {
checkIndex();
}
catch (IOException e) {
return null;
}
}
/**
* Returns a javac List of filenames within a directory in the ZipFileIndex.
*/
try {
checkIndex();
}
return ret;
}
catch (IOException e) {
}
}
try {
checkIndex();
}
return ret;
}
catch (IOException e) {
}
}
try {
checkIndex();
}
return allDirs;
}
catch (IOException e) {
}
}
/**
* Tests if a specific path exists in the zip. This method will return true
* for file entries and directories.
*
* @param path A path within the zip.
* @return True if the path is a file or dir, false otherwise.
*/
try {
checkIndex();
}
catch (IOException e) {
return false;
}
}
// The top level in a zip file is always a directory.
return true;
}
checkIndex();
}
throw new FileNotFoundException();
return entry.getLastModified();
}
throw new FileNotFoundException();
return 0;
}
// entry is not compressed?
return entry.compressedSize;
} else {
}
}
}
openFile();
closeFile();
return result;
}
throw new FileNotFoundException();
}
throws IOException {
return result;
}
// is this compressed - offset 8 in the ZipEntry header
return cbuf;
throw new ZipException("corrupted zip file");
return buf;
}
/**
*
*/
// entry is not compressed?
int offset = 0;
if (count == -1)
break;
}
}
if (count == -1)
throw new ZipException("corrupted zip file");
}
//----------------------------------------------------------------------------
// Zip utilities
//----------------------------------------------------------------------------
byte[] header = new byte[30];
throw new ZipException("corrupted zip file");
return header;
}
/*
* Inflate using the java.util.zip.Inflater class
*/
// construct the inflater object or reuse an existing one
try {
} catch (DataFormatException ex) {
return -1;
}
}
/**
* return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
* endian format.
*/
}
/**
* return the 4 bytes buf[i..i+3] as an integer in little endian format.
*/
}
/* ----------------------------------------------------------------------------
* ZipDirectory
* ----------------------------------------------------------------------------*/
private class ZipDirectory {
private int lastStart;
private int lastLen;
byte[] zipDir;
public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
this.zipRandomFile = zipRandomFile;
this.zipFileIndex = index;
}
/*
* the zip entry signature should be at offset 0, otherwise allow the
* calling logic to take evasive action by throwing ZipFormatException.
*/
try {
return true;
}
}
}
}
} finally {
}
throw new ZipFormatException("invalid zip magic");
}
/*
* Reads zip file central directory.
* For more details see readCEN in zip_util.c from the JDK sources.
* This is a Java port of that function.
*/
int endbuflen = 1024;
// There is a variable-length field after the dir offset record. We need to do consequential search.
while (endbufend >= 22) {
int i = endbuflen - 22;
while (i >= 0 &&
!(endbuf[i] == 0x50 &&
endbufpos + i + 22 +
i--;
}
if (i >= 0) {
// a negative offset or the entries field indicates a
// potential zip64 archive
throw new ZipFormatException("detected a zip64 archive");
}
return;
} else {
}
}
throw new ZipException("cannot read zip file");
}
// Add each of the files
if (entryCount > 0) {
int pos = 2;
for (int i = 0; i < entryCount; i++) {
}
// Add the accumulated dirs into the same list
// use shared RelativeDirectory objects for parent dirs
zipFileIndexEntry.isDir = true;
}
} else {
cleanupState();
}
}
throw new ZipException("cannot read zip file entry");
}
}
// Force any '\' to '/'. Keep the position of the last separator.
if (nextByte == (byte)'\\') {
} else if (nextByte == (byte)'/') {
}
}
if (index == 0) {
break;
}
index--;
}
}
// Sub directories
// Enter also all the parent directories
break;
else {
// use shared RelativeDirectory objects for parent dirs
}
}
}
else {
}
}
// For each dir create also a file
}
return pos + 46 +
}
}
/**
* Returns the last modified timestamp of a zip file.
* @return long
*/
synchronized (this) {
checkIndex();
return zipFileLastModified;
}
}
/** ------------------------------------------------------------------------
* DirectoryEntry class
* -------------------------------------------------------------------------*/
static class DirectoryEntry {
private boolean filesInited;
private boolean directoriesInited;
private boolean zipFileEntriesInited;
private boolean entriesInited;
private com.sun.tools.javac.util.List<String> zipFileEntriesFiles = com.sun.tools.javac.util.List.<String>nil();
private com.sun.tools.javac.util.List<String> zipFileEntriesDirectories = com.sun.tools.javac.util.List.<String>nil();
private com.sun.tools.javac.util.List<Entry> zipFileEntries = com.sun.tools.javac.util.List.<Entry>nil();
private int numEntries;
filesInited = false;
directoriesInited = false;
entriesInited = false;
this.zipFileIndex = index;
}
if (!filesInited) {
initEntries();
if (!e.isDir) {
}
}
filesInited = true;
}
return zipFileEntriesFiles;
}
if (!directoriesInited) {
initEntries();
if (e.isDir) {
}
}
directoriesInited = true;
}
return zipFileEntriesDirectories;
}
if (!zipFileEntriesInited) {
initEntries();
}
zipFileEntriesInited = true;
}
return zipFileEntries;
}
initEntries();
if (index < 0) {
return null;
}
}
private void initEntries() {
if (entriesInited) {
return;
}
if (!zipFileIndex.readFromIndex) {
}
} else {
try {
// Read the name bytes
byte [] zfieNameBytes = new byte[zfieNameBytesLen];
// Read isDir
}
} catch (Throwable t) {
// Do nothing
} finally {
try {
}
} catch (Throwable t) {
// Do nothing
}
}
}
}
entriesInited = true;
}
initEntries();
return entries;
}
}
private boolean readIndex() {
if (triedToReadIndex || !usePreindexedCache) {
return false;
}
boolean ret = false;
synchronized (this) {
triedToReadIndex = true;
try {
ret = false;
} else {
byte [] dirNameBytes = new byte[dirNameBytesLen];
}
ret = true;
}
} catch (Throwable t) {
// Do nothing
} finally {
try {
// Do nothing
}
}
}
if (ret == true) {
readFromIndex = true;
}
}
return ret;
}
private boolean writeIndex() {
boolean ret = false;
if (readFromIndex || !usePreindexedCache) {
return true;
}
if (!writeIndex) {
return true;
}
return false;
}
long writtenSoFar = 0;
try {
writtenSoFar += 8;
writtenSoFar += 4;
// Write the dir name bytes
writtenSoFar += 4;
// Write the number of files in the dir
writtenSoFar += 4;
// Write the offset of the file's data in the dir
writtenSoFar += 8;
}
// Fix up the offset in the directory table
// Now write each of the files in the DirectoryEntry
// Write the name bytes
writtenSoFar += 4;
// Write isDir
writtenSoFar += 1;
writtenSoFar += 4;
writtenSoFar += 4;
writtenSoFar += 4;
writtenSoFar += 8;
}
}
} catch (Throwable t) {
// Do nothing
} finally {
try {
}
} catch(IOException ioe) {
// Do nothing
}
}
return ret;
}
public boolean writeZipIndex() {
synchronized (this) {
return writeIndex();
}
}
if (zipIndexFile == null) {
return null;
}
}
return zipIndexFile;
}
return zipFile;
}
}
return absFile;
}
return rd;
}
return rd;
}
// Directory related
boolean isDir;
// File related
int offset;
int size;
int compressedSize;
long javatime;
private int nativetime;
}
}
}
return name;
}
public long getLastModified() {
if (javatime == 0) {
}
return javatime;
}
// based on dosToJavaTime in java.util.Zip, but avoiding the
// use of deprecated Date constructor
return c.getTimeInMillis();
}
}
public boolean isDirectory() {
return isDir;
}
if (c != 0)
return c;
}
}
if (!(o instanceof Entry))
return false;
}
public int hashCode() {
int hash = 7;
return hash;
}
}
}
/*
* Exception primarily used to implement a failover, used exclusively here.
*/
super(message);
}
}
}
}