/*
 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * 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.
 */

package com.sun.tools.javac.file;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.ZipException;

import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.file.RelativePath.RelativeFile;

/**
 * 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.)
 *
 * Location where to look for/generate optimized zip index files can be
 * provided using "{@code -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 final String MIN_CHAR = String.valueOf(Character.MIN_VALUE);
    private static final String MAX_CHAR = String.valueOf(Character.MAX_VALUE);

    public final static long NOT_MODIFIED = Long.MIN_VALUE;


    private static final boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.

    private Map<RelativeDirectory, DirectoryEntry> directories =
            Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
    private Set<RelativeDirectory> allDirs =
            Collections.<RelativeDirectory>emptySet();

    // ZipFileIndex data entries
    final File zipFile;
    private Reference<File> absFileRef;
    long zipFileLastModified = NOT_MODIFIED;
    private RandomAccessFile zipRandomFile;
    private Entry[] entries;

    private boolean readFromIndex = false;
    private File zipIndexFile = null;
    private boolean triedToReadIndex = false;
    final RelativeDirectory symbolFilePrefix;
    private final int symbolFilePrefixLength;
    private boolean hasPopulatedData = false;
    long lastReferenceTimeStamp = NOT_MODIFIED;

    private final boolean usePreindexedCache;
    private final String preindexedCacheLocation;

    private boolean writeIndex = false;

    private Map<String, SoftReference<RelativeDirectory>> relativeDirectoryCache =
            new HashMap<String, SoftReference<RelativeDirectory>>();


    public synchronized boolean isOpen() {
        return (zipRandomFile != null);
    }

    ZipFileIndex(File zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
            boolean useCache, String cacheLocation) throws IOException {
        this.zipFile = zipFile;
        this.symbolFilePrefix = symbolFilePrefix;
        this.symbolFilePrefixLength = (symbolFilePrefix == null ? 0 :
            symbolFilePrefix.getPath().getBytes("UTF-8").length);
        this.writeIndex = writeIndex;
        this.usePreindexedCache = useCache;
        this.preindexedCacheLocation = cacheLocation;

        if (zipFile != null) {
            this.zipFileLastModified = zipFile.lastModified();
        }

        // Validate integrity of the zip file
        checkIndex();
    }

    @Override
    public String toString() {
        return "ZipFileIndex[" + zipFile + "]";
    }

    // Just in case...
    @Override
    protected void finalize() throws Throwable {
        closeFile();
        super.finalize();
    }

    private boolean isUpToDate() {
        if (zipFile != null
                && ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified())
                && 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.
     */
    private void checkIndex() throws IOException {
        boolean isUpToDate = true;
        if (!isUpToDate()) {
            closeFile();
            isUpToDate = false;
        }

        if (zipRandomFile != null || isUpToDate) {
            lastReferenceTimeStamp = System.currentTimeMillis();
            return;
        }

        hasPopulatedData = true;

        if (readIndex()) {
            lastReferenceTimeStamp = System.currentTimeMillis();
            return;
        }

        directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
        allDirs = Collections.<RelativeDirectory>emptySet();

        try {
            openFile();
            long totalLength = zipRandomFile.length();
            ZipDirectory directory = new ZipDirectory(zipRandomFile, 0L, totalLength, this);
            directory.buildIndex();
        } finally {
            if (zipRandomFile != null) {
                closeFile();
            }
        }

        lastReferenceTimeStamp = System.currentTimeMillis();
    }

    private void openFile() throws FileNotFoundException {
        if (zipRandomFile == null && zipFile != null) {
            zipRandomFile = new RandomAccessFile(zipFile, "r");
        }
    }

    private void cleanupState() {
        // Make sure there is a valid but empty index if the file doesn't exist
        entries = Entry.EMPTY_ARRAY;
        directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
        zipFileLastModified = NOT_MODIFIED;
        allDirs = Collections.<RelativeDirectory>emptySet();
    }

    public synchronized void close() {
        writeIndex();
        closeFile();
    }

    private void closeFile() {
        if (zipRandomFile != null) {
            try {
                zipRandomFile.close();
            } catch (IOException ex) {
            }
            zipRandomFile = null;
        }
    }

    /**
     * Returns the ZipFileIndexEntry for a path, if there is one.
     */
    synchronized Entry getZipIndexEntry(RelativePath path) {
        try {
            checkIndex();
            DirectoryEntry de = directories.get(path.dirname());
            String lookFor = path.basename();
            return (de == null) ? null : de.getEntry(lookFor);
        }
        catch (IOException e) {
            return null;
        }
    }

    /**
     * Returns a javac List of filenames within a directory in the ZipFileIndex.
     */
    public synchronized com.sun.tools.javac.util.List<String> getFiles(RelativeDirectory path) {
        try {
            checkIndex();

            DirectoryEntry de = directories.get(path);
            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getFiles();

            if (ret == null) {
                return com.sun.tools.javac.util.List.<String>nil();
            }
            return ret;
        }
        catch (IOException e) {
            return com.sun.tools.javac.util.List.<String>nil();
        }
    }

    public synchronized List<String> getDirectories(RelativeDirectory path) {
        try {
            checkIndex();

            DirectoryEntry de = directories.get(path);
            com.sun.tools.javac.util.List<String> ret = de == null ? null : de.getDirectories();

            if (ret == null) {
                return com.sun.tools.javac.util.List.<String>nil();
            }

            return ret;
        }
        catch (IOException e) {
            return com.sun.tools.javac.util.List.<String>nil();
        }
    }

    public synchronized Set<RelativeDirectory> getAllDirectories() {
        try {
            checkIndex();
            if (allDirs == Collections.EMPTY_SET) {
                allDirs = new java.util.LinkedHashSet<RelativeDirectory>(directories.keySet());
            }

            return allDirs;
        }
        catch (IOException e) {
            return Collections.<RelativeDirectory>emptySet();
        }
    }

    /**
     * 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.
     */
    public synchronized boolean contains(RelativePath path) {
        try {
            checkIndex();
            return getZipIndexEntry(path) != null;
        }
        catch (IOException e) {
            return false;
        }
    }

    public synchronized boolean isDirectory(RelativePath path) throws IOException {
        // The top level in a zip file is always a directory.
        if (path.getPath().length() == 0) {
            lastReferenceTimeStamp = System.currentTimeMillis();
            return true;
        }

        checkIndex();
        return directories.get(path) != null;
    }

    public synchronized long getLastModified(RelativeFile path) throws IOException {
        Entry entry = getZipIndexEntry(path);
        if (entry == null)
            throw new FileNotFoundException();
        return entry.getLastModified();
    }

    public synchronized int length(RelativeFile path) throws IOException {
        Entry entry = getZipIndexEntry(path);
        if (entry == null)
            throw new FileNotFoundException();

        if (entry.isDir) {
            return 0;
        }

        byte[] header = getHeader(entry);
        // entry is not compressed?
        if (get2ByteLittleEndian(header, 8) == 0) {
            return entry.compressedSize;
        } else {
            return entry.size;
        }
    }

    public synchronized byte[] read(RelativeFile path) throws IOException {
        Entry entry = getZipIndexEntry(path);
        if (entry == null)
            throw new FileNotFoundException("Path not found in ZIP: " + path.path);
        return read(entry);
    }

    synchronized byte[] read(Entry entry) throws IOException {
        openFile();
        byte[] result = readBytes(entry);
        closeFile();
        return result;
    }

    public synchronized int read(RelativeFile path, byte[] buffer) throws IOException {
        Entry entry = getZipIndexEntry(path);
        if (entry == null)
            throw new FileNotFoundException();
        return read(entry, buffer);
    }

    synchronized int read(Entry entry, byte[] buffer)
            throws IOException {
        int result = readBytes(entry, buffer);
        return  result;
    }

    private byte[] readBytes(Entry entry) throws IOException {
        byte[] header = getHeader(entry);
        int csize = entry.compressedSize;
        byte[] cbuf = new byte[csize];
        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
        zipRandomFile.readFully(cbuf, 0, csize);

        // is this compressed - offset 8 in the ZipEntry header
        if (get2ByteLittleEndian(header, 8) == 0)
            return cbuf;

        int size = entry.size;
        byte[] buf = new byte[size];
        if (inflate(cbuf, buf) != size)
            throw new ZipException("corrupted zip file");

        return buf;
    }

    /**
     *
     */
    private int readBytes(Entry entry, byte[] buffer) throws IOException {
        byte[] header = getHeader(entry);

        // entry is not compressed?
        if (get2ByteLittleEndian(header, 8) == 0) {
            zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
            int offset = 0;
            int size = buffer.length;
            while (offset < size) {
                int count = zipRandomFile.read(buffer, offset, size - offset);
                if (count == -1)
                    break;
                offset += count;
            }
            return entry.size;
        }

        int csize = entry.compressedSize;
        byte[] cbuf = new byte[csize];
        zipRandomFile.skipBytes(get2ByteLittleEndian(header, 26) + get2ByteLittleEndian(header, 28));
        zipRandomFile.readFully(cbuf, 0, csize);

        int count = inflate(cbuf, buffer);
        if (count == -1)
            throw new ZipException("corrupted zip file");

        return entry.size;
    }

    //----------------------------------------------------------------------------
    // Zip utilities
    //----------------------------------------------------------------------------

    private byte[] getHeader(Entry entry) throws IOException {
        zipRandomFile.seek(entry.offset);
        byte[] header = new byte[30];
        zipRandomFile.readFully(header);
        if (get4ByteLittleEndian(header, 0) != 0x04034b50)
            throw new ZipException("corrupted zip file");
        if ((get2ByteLittleEndian(header, 6) & 1) != 0)
            throw new ZipException("encrypted zip file"); // offset 6 in the header of the ZipFileEntry
        return header;
    }

  /*
   * Inflate using the java.util.zip.Inflater class
   */
    private SoftReference<Inflater> inflaterRef;
    private int inflate(byte[] src, byte[] dest) {
        Inflater inflater = (inflaterRef == null ? null : inflaterRef.get());

        // construct the inflater object or reuse an existing one
        if (inflater == null)
            inflaterRef = new SoftReference<Inflater>(inflater = new Inflater(true));

        inflater.reset();
        inflater.setInput(src);
        try {
            return inflater.inflate(dest);
        } catch (DataFormatException ex) {
            return -1;
        }
    }

    /**
     * return the two bytes buf[pos], buf[pos+1] as an unsigned integer in little
     * endian format.
     */
    private static int get2ByteLittleEndian(byte[] buf, int pos) {
        return (buf[pos] & 0xFF) + ((buf[pos+1] & 0xFF) << 8);
    }

    /**
     * return the 4 bytes buf[i..i+3] as an integer in little endian format.
     */
    private static int get4ByteLittleEndian(byte[] buf, int pos) {
        return (buf[pos] & 0xFF) + ((buf[pos + 1] & 0xFF) << 8) +
                ((buf[pos + 2] & 0xFF) << 16) + ((buf[pos + 3] & 0xFF) << 24);
    }

    /* ----------------------------------------------------------------------------
     * ZipDirectory
     * ----------------------------------------------------------------------------*/

    private class ZipDirectory {
        private RelativeDirectory lastDir;
        private int lastStart;
        private int lastLen;

        byte[] zipDir;
        RandomAccessFile zipRandomFile = null;
        ZipFileIndex zipFileIndex = null;

        public ZipDirectory(RandomAccessFile zipRandomFile, long start, long end, ZipFileIndex index) throws IOException {
            this.zipRandomFile = zipRandomFile;
            this.zipFileIndex = index;
            hasValidHeader();
            findCENRecord(start, end);
        }

        /*
         * the zip entry signature should be at offset 0, otherwise allow the
         * calling logic to take evasive action by throwing ZipFormatException.
         */
        private boolean hasValidHeader() throws IOException {
            final long pos = zipRandomFile.getFilePointer();
            try {
                if (zipRandomFile.read() == 'P') {
                    if (zipRandomFile.read() == 'K') {
                        if (zipRandomFile.read() == 0x03) {
                            if (zipRandomFile.read() == 0x04) {
                                return true;
                            }
                        }
                    }
                }
            } finally {
                zipRandomFile.seek(pos);
            }
            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.
         */
        private void findCENRecord(long start, long end) throws IOException {
            long totalLength = end - start;
            int endbuflen = 1024;
            byte[] endbuf = new byte[endbuflen];
            long endbufend = end - start;

            // There is a variable-length field after the dir offset record. We need to do consequential search.
            while (endbufend >= 22) {
                if (endbufend < endbuflen)
                    endbuflen = (int)endbufend;
                long endbufpos = endbufend - endbuflen;
                zipRandomFile.seek(start + endbufpos);
                zipRandomFile.readFully(endbuf, 0, endbuflen);
                int i = endbuflen - 22;
                while (i >= 0 &&
                        !(endbuf[i] == 0x50 &&
                        endbuf[i + 1] == 0x4b &&
                        endbuf[i + 2] == 0x05 &&
                        endbuf[i + 3] == 0x06 &&
                        endbufpos + i + 22 +
                        get2ByteLittleEndian(endbuf, i + 20) == totalLength)) {
                    i--;
                }

                if (i >= 0) {
                    zipDir = new byte[get4ByteLittleEndian(endbuf, i + 12)];
                    int sz = get4ByteLittleEndian(endbuf, i + 16);
                    // a negative offset or the entries field indicates a
                    // potential zip64 archive
                    if (sz < 0 || get2ByteLittleEndian(endbuf, i + 10) == 0xffff) {
                        throw new ZipFormatException("detected a zip64 archive");
                    }
                    zipRandomFile.seek(start + sz);
                    zipRandomFile.readFully(zipDir, 0, zipDir.length);
                    return;
                } else {
                    endbufend = endbufpos + 21;
                }
            }
            throw new ZipException("cannot read zip file");
        }

        private void buildIndex() throws IOException {
            int len = zipDir.length;

            // Add each of the files
            if (len > 0) {
                directories = new LinkedHashMap<RelativeDirectory, DirectoryEntry>();
                ArrayList<Entry> entryList = new ArrayList<Entry>();
                for (int pos = 0; pos < len; ) {
                    pos = readEntry(pos, entryList, directories);
                }

                // Add the accumulated dirs into the same list
                for (RelativeDirectory d: directories.keySet()) {
                    // use shared RelativeDirectory objects for parent dirs
                    RelativeDirectory parent = getRelativeDirectory(d.dirname().getPath());
                    String file = d.basename();
                    Entry zipFileIndexEntry = new Entry(parent, file);
                    zipFileIndexEntry.isDir = true;
                    entryList.add(zipFileIndexEntry);
                }

                entries = entryList.toArray(new Entry[entryList.size()]);
                Arrays.sort(entries);
            } else {
                cleanupState();
            }
        }

        private int readEntry(int pos, List<Entry> entryList,
                Map<RelativeDirectory, DirectoryEntry> directories) throws IOException {
            if (get4ByteLittleEndian(zipDir, pos) != 0x02014b50) {
                throw new ZipException("cannot read zip file entry");
            }

            int dirStart = pos + 46;
            int fileStart = dirStart;
            int fileEnd = fileStart + get2ByteLittleEndian(zipDir, pos + 28);

            if (zipFileIndex.symbolFilePrefixLength != 0 &&
                    ((fileEnd - fileStart) >= symbolFilePrefixLength)) {
                dirStart += zipFileIndex.symbolFilePrefixLength;
               fileStart += zipFileIndex.symbolFilePrefixLength;
            }
            // Force any '\' to '/'. Keep the position of the last separator.
            for (int index = fileStart; index < fileEnd; index++) {
                byte nextByte = zipDir[index];
                if (nextByte == (byte)'\\') {
                    zipDir[index] = (byte)'/';
                    fileStart = index + 1;
                } else if (nextByte == (byte)'/') {
                    fileStart = index + 1;
                }
            }

            RelativeDirectory directory = null;
            if (fileStart == dirStart)
                directory = getRelativeDirectory("");
            else if (lastDir != null && lastLen == fileStart - dirStart - 1) {
                int index = lastLen - 1;
                while (zipDir[lastStart + index] == zipDir[dirStart + index]) {
                    if (index == 0) {
                        directory = lastDir;
                        break;
                    }
                    index--;
                }
            }

            // Sub directories
            if (directory == null) {
                lastStart = dirStart;
                lastLen = fileStart - dirStart - 1;

                directory = getRelativeDirectory(new String(zipDir, dirStart, lastLen, "UTF-8"));
                lastDir = directory;

                // Enter also all the parent directories
                RelativeDirectory tempDirectory = directory;

                while (directories.get(tempDirectory) == null) {
                    directories.put(tempDirectory, new DirectoryEntry(tempDirectory, zipFileIndex));
                    if (tempDirectory.path.indexOf("/") == tempDirectory.path.length() - 1)
                        break;
                    else {
                        // use shared RelativeDirectory objects for parent dirs
                        tempDirectory = getRelativeDirectory(tempDirectory.dirname().getPath());
                    }
                }
            }
            else {
                if (directories.get(directory) == null) {
                    directories.put(directory, new DirectoryEntry(directory, zipFileIndex));
                }
            }

            // For each dir create also a file
            if (fileStart != fileEnd) {
                Entry entry = new Entry(directory,
                        new String(zipDir, fileStart, fileEnd - fileStart, "UTF-8"));

                entry.setNativeTime(get4ByteLittleEndian(zipDir, pos + 12));
                entry.compressedSize = get4ByteLittleEndian(zipDir, pos + 20);
                entry.size = get4ByteLittleEndian(zipDir, pos + 24);
                entry.offset = get4ByteLittleEndian(zipDir, pos + 42);
                entryList.add(entry);
            }

            return pos + 46 +
                    get2ByteLittleEndian(zipDir, pos + 28) +
                    get2ByteLittleEndian(zipDir, pos + 30) +
                    get2ByteLittleEndian(zipDir, pos + 32);
        }
    }

    /**
     * Returns the last modified timestamp of a zip file.
     * @return long
     */
    public long getZipFileLastModified() throws IOException {
        synchronized (this) {
            checkIndex();
            return zipFileLastModified;
        }
    }

    /** ------------------------------------------------------------------------
     *  DirectoryEntry class
     * -------------------------------------------------------------------------*/

    static class DirectoryEntry {
        private boolean filesInited;
        private boolean directoriesInited;
        private boolean zipFileEntriesInited;
        private boolean entriesInited;

        private long writtenOffsetOffset = 0;

        private RelativeDirectory dirName;

        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 List<Entry> entries = new ArrayList<Entry>();

        private ZipFileIndex zipFileIndex;

        private int numEntries;

        DirectoryEntry(RelativeDirectory dirName, ZipFileIndex index) {
            filesInited = false;
            directoriesInited = false;
            entriesInited = false;

            this.dirName = dirName;
            this.zipFileIndex = index;
        }

        private com.sun.tools.javac.util.List<String> getFiles() {
            if (!filesInited) {
                initEntries();
                for (Entry e : entries) {
                    if (!e.isDir) {
                        zipFileEntriesFiles = zipFileEntriesFiles.append(e.name);
                    }
                }
                filesInited = true;
            }
            return zipFileEntriesFiles;
        }

        private com.sun.tools.javac.util.List<String> getDirectories() {
            if (!directoriesInited) {
                initEntries();
                for (Entry e : entries) {
                    if (e.isDir) {
                        zipFileEntriesDirectories = zipFileEntriesDirectories.append(e.name);
                    }
                }
                directoriesInited = true;
            }
            return zipFileEntriesDirectories;
        }

        private com.sun.tools.javac.util.List<Entry> getEntries() {
            if (!zipFileEntriesInited) {
                initEntries();
                zipFileEntries = com.sun.tools.javac.util.List.nil();
                for (Entry zfie : entries) {
                    zipFileEntries = zipFileEntries.append(zfie);
                }
                zipFileEntriesInited = true;
            }
            return zipFileEntries;
        }

        private Entry getEntry(String rootName) {
            initEntries();
            int index = Collections.binarySearch(entries, new Entry(dirName, rootName));
            if (index < 0) {
                return null;
            }

            return entries.get(index);
        }

        private void initEntries() {
            if (entriesInited) {
                return;
            }

            if (!zipFileIndex.readFromIndex) {
                int from = -Arrays.binarySearch(zipFileIndex.entries,
                        new Entry(dirName, ZipFileIndex.MIN_CHAR)) - 1;
                int to = -Arrays.binarySearch(zipFileIndex.entries,
                        new Entry(dirName, MAX_CHAR)) - 1;

                for (int i = from; i < to; i++) {
                    entries.add(zipFileIndex.entries[i]);
                }
            } else {
                File indexFile = zipFileIndex.getIndexFile();
                if (indexFile != null) {
                    RandomAccessFile raf = null;
                    try {
                        raf = new RandomAccessFile(indexFile, "r");
                        raf.seek(writtenOffsetOffset);

                        for (int nFiles = 0; nFiles < numEntries; nFiles++) {
                            // Read the name bytes
                            int zfieNameBytesLen = raf.readInt();
                            byte [] zfieNameBytes = new byte[zfieNameBytesLen];
                            raf.read(zfieNameBytes);
                            String eName = new String(zfieNameBytes, "UTF-8");

                            // Read isDir
                            boolean eIsDir = raf.readByte() == (byte)0 ? false : true;

                            // Read offset of bytes in the real Jar/Zip file
                            int eOffset = raf.readInt();

                            // Read size of the file in the real Jar/Zip file
                            int eSize = raf.readInt();

                            // Read compressed size of the file in the real Jar/Zip file
                            int eCsize = raf.readInt();

                            // Read java time stamp of the file in the real Jar/Zip file
                            long eJavaTimestamp = raf.readLong();

                            Entry rfie = new Entry(dirName, eName);
                            rfie.isDir = eIsDir;
                            rfie.offset = eOffset;
                            rfie.size = eSize;
                            rfie.compressedSize = eCsize;
                            rfie.javatime = eJavaTimestamp;
                            entries.add(rfie);
                        }
                    } catch (Throwable t) {
                        // Do nothing
                    } finally {
                        try {
                            if (raf != null) {
                                raf.close();
                            }
                        } catch (Throwable t) {
                            // Do nothing
                        }
                    }
                }
            }

            entriesInited = true;
        }

        List<Entry> getEntriesAsCollection() {
            initEntries();

            return entries;
        }
    }

    private boolean readIndex() {
        if (triedToReadIndex || !usePreindexedCache) {
            return false;
        }

        boolean ret = false;
        synchronized (this) {
            triedToReadIndex = true;
            RandomAccessFile raf = null;
            try {
                File indexFileName = getIndexFile();
                raf = new RandomAccessFile(indexFileName, "r");

                long fileStamp = raf.readLong();
                if (zipFile.lastModified() != fileStamp) {
                    ret = false;
                } else {
                    directories = new LinkedHashMap<RelativeDirectory, DirectoryEntry>();
                    int numDirs = raf.readInt();
                    for (int nDirs = 0; nDirs < numDirs; nDirs++) {
                        int dirNameBytesLen = raf.readInt();
                        byte [] dirNameBytes = new byte[dirNameBytesLen];
                        raf.read(dirNameBytes);

                        RelativeDirectory dirNameStr = getRelativeDirectory(new String(dirNameBytes, "UTF-8"));
                        DirectoryEntry de = new DirectoryEntry(dirNameStr, this);
                        de.numEntries = raf.readInt();
                        de.writtenOffsetOffset = raf.readLong();
                        directories.put(dirNameStr, de);
                    }
                    ret = true;
                    zipFileLastModified = fileStamp;
                }
            } catch (Throwable t) {
                // Do nothing
            } finally {
                if (raf != null) {
                    try {
                        raf.close();
                    } catch (Throwable tt) {
                        // Do nothing
                    }
                }
            }
            if (ret == true) {
                readFromIndex = true;
            }
        }

        return ret;
    }

    private boolean writeIndex() {
        boolean ret = false;
        if (readFromIndex || !usePreindexedCache) {
            return true;
        }

        if (!writeIndex) {
            return true;
        }

        File indexFile = getIndexFile();
        if (indexFile == null) {
            return false;
        }

        RandomAccessFile raf = null;
        long writtenSoFar = 0;
        try {
            raf = new RandomAccessFile(indexFile, "rw");

            raf.writeLong(zipFileLastModified);
            writtenSoFar += 8;

            List<DirectoryEntry> directoriesToWrite = new ArrayList<DirectoryEntry>();
            Map<RelativeDirectory, Long> offsets = new HashMap<RelativeDirectory, Long>();
            raf.writeInt(directories.keySet().size());
            writtenSoFar += 4;

            for (RelativeDirectory dirName: directories.keySet()) {
                DirectoryEntry dirEntry = directories.get(dirName);

                directoriesToWrite.add(dirEntry);

                // Write the dir name bytes
                byte [] dirNameBytes = dirName.getPath().getBytes("UTF-8");
                int dirNameBytesLen = dirNameBytes.length;
                raf.writeInt(dirNameBytesLen);
                writtenSoFar += 4;

                raf.write(dirNameBytes);
                writtenSoFar += dirNameBytesLen;

                // Write the number of files in the dir
                List<Entry> dirEntries = dirEntry.getEntriesAsCollection();
                raf.writeInt(dirEntries.size());
                writtenSoFar += 4;

                offsets.put(dirName, new Long(writtenSoFar));

                // Write the offset of the file's data in the dir
                dirEntry.writtenOffsetOffset = 0L;
                raf.writeLong(0L);
                writtenSoFar += 8;
            }

            for (DirectoryEntry de : directoriesToWrite) {
                // Fix up the offset in the directory table
                long currFP = raf.getFilePointer();

                long offsetOffset = offsets.get(de.dirName).longValue();
                raf.seek(offsetOffset);
                raf.writeLong(writtenSoFar);

                raf.seek(currFP);

                // Now write each of the files in the DirectoryEntry
                List<Entry> list = de.getEntriesAsCollection();
                for (Entry zfie : list) {
                    // Write the name bytes
                    byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
                    int zfieNameBytesLen = zfieNameBytes.length;
                    raf.writeInt(zfieNameBytesLen);
                    writtenSoFar += 4;
                    raf.write(zfieNameBytes);
                    writtenSoFar += zfieNameBytesLen;

                    // Write isDir
                    raf.writeByte(zfie.isDir ? (byte)1 : (byte)0);
                    writtenSoFar += 1;

                    // Write offset of bytes in the real Jar/Zip file
                    raf.writeInt(zfie.offset);
                    writtenSoFar += 4;

                    // Write size of the file in the real Jar/Zip file
                    raf.writeInt(zfie.size);
                    writtenSoFar += 4;

                    // Write compressed size of the file in the real Jar/Zip file
                    raf.writeInt(zfie.compressedSize);
                    writtenSoFar += 4;

                    // Write java time stamp of the file in the real Jar/Zip file
                    raf.writeLong(zfie.getLastModified());
                    writtenSoFar += 8;
                }
            }
        } catch (Throwable t) {
            // Do nothing
        } finally {
            try {
                if (raf != null) {
                    raf.close();
                }
            } catch(IOException ioe) {
                // Do nothing
            }
        }

        return ret;
    }

    public boolean writeZipIndex() {
        synchronized (this) {
            return writeIndex();
        }
    }

    private File getIndexFile() {
        if (zipIndexFile == null) {
            if (zipFile == null) {
                return null;
            }

            zipIndexFile = new File((preindexedCacheLocation == null ? "" : preindexedCacheLocation) +
                    zipFile.getName() + ".index");
        }

        return zipIndexFile;
    }

    public File getZipFile() {
        return zipFile;
    }

    File getAbsoluteFile() {
        File absFile = (absFileRef == null ? null : absFileRef.get());
        if (absFile == null) {
            absFile = zipFile.getAbsoluteFile();
            absFileRef = new SoftReference<File>(absFile);
        }
        return absFile;
    }

    private RelativeDirectory getRelativeDirectory(String path) {
        RelativeDirectory rd;
        SoftReference<RelativeDirectory> ref = relativeDirectoryCache.get(path);
        if (ref != null) {
            rd = ref.get();
            if (rd != null)
                return rd;
        }
        rd = new RelativeDirectory(path);
        relativeDirectoryCache.put(path, new SoftReference<RelativeDirectory>(rd));
        return rd;
    }

    static class Entry implements Comparable<Entry> {
        public static final Entry[] EMPTY_ARRAY = {};

        // Directory related
        RelativeDirectory dir;
        boolean isDir;

        // File related
        String name;

        int offset;
        int size;
        int compressedSize;
        long javatime;

        private int nativetime;

        public Entry(RelativePath path) {
            this(path.dirname(), path.basename());
        }

        public Entry(RelativeDirectory directory, String name) {
            this.dir = directory;
            this.name = name;
        }

        public String getName() {
            return new RelativeFile(dir, name).getPath();
        }

        public String getFileName() {
            return name;
        }

        public long getLastModified() {
            if (javatime == 0) {
                    javatime = dosToJavaTime(nativetime);
            }
            return javatime;
        }

        // based on dosToJavaTime in java.util.Zip, but avoiding the
        // use of deprecated Date constructor
        private static long dosToJavaTime(int dtime) {
            Calendar c = Calendar.getInstance();
            c.set(Calendar.YEAR,        ((dtime >> 25) & 0x7f) + 1980);
            c.set(Calendar.MONTH,       ((dtime >> 21) & 0x0f) - 1);
            c.set(Calendar.DATE,        ((dtime >> 16) & 0x1f));
            c.set(Calendar.HOUR_OF_DAY, ((dtime >> 11) & 0x1f));
            c.set(Calendar.MINUTE,      ((dtime >>  5) & 0x3f));
            c.set(Calendar.SECOND,      ((dtime <<  1) & 0x3e));
            c.set(Calendar.MILLISECOND, 0);
            return c.getTimeInMillis();
        }

        void setNativeTime(int natTime) {
            nativetime = natTime;
        }

        public boolean isDirectory() {
            return isDir;
        }

        public int compareTo(Entry other) {
            RelativeDirectory otherD = other.dir;
            if (dir != otherD) {
                int c = dir.compareTo(otherD);
                if (c != 0)
                    return c;
            }
            return name.compareTo(other.name);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof Entry))
                return false;
            Entry other = (Entry) o;
            return dir.equals(other.dir) && name.equals(other.name);
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 97 * hash + (this.dir != null ? this.dir.hashCode() : 0);
            hash = 97 * hash + (this.name != null ? this.name.hashCode() : 0);
            return hash;
        }

        @Override
        public String toString() {
            return isDir ? ("Dir:" + dir + " : " + name) :
                (dir + ":" + name);
        }
    }

    /*
     * Exception primarily used to implement a failover, used exclusively here.
     */

    static final class ZipFormatException extends IOException {
        private static final long serialVersionUID = 8000196834066748623L;
        protected ZipFormatException(String message) {
            super(message);
        }

        protected ZipFormatException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}
