/* ZipFile.java --
   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util.zip;

import gnu.java.util.EmptyEnumeration;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;

/**
 * This class represents a Zip archive.  You can ask for the contained
 * entries, or get an input stream for a file entry.  The entry is
 * automatically decompressed.
 *
 * This class is thread safe:  You can open input streams for arbitrary
 * entries in different threads.
 *
 * @author Jochen Hoenicke
 * @author Artur Biesiadowski
 */
public class ZipFile implements ZipConstants
{

  /**
   * Mode flag to open a zip file for reading.
   */
  public static final int OPEN_READ = 0x1;

  /**
   * Mode flag to delete a zip file after reading.
   */
  public static final int OPEN_DELETE = 0x4;

  /**
   * This field isn't defined in the JDK's ZipConstants, but should be.
   */
  static final int ENDNRD =  4;

  // Name of this zip file.
  private final String name;

  // File from which zip entries are read.
  private final RandomAccessFile raf;

  // The entries of this zip file when initialized and not yet closed.
  private LinkedHashMap<String, ZipEntry> entries;

  private boolean closed = false;


  /**
   * Helper function to open RandomAccessFile and throw the proper
   * ZipException in case opening the file fails.
   *
   * @param name the file name, or null if file is provided
   *
   * @param file the file, or null if name is provided
   *
   * @return the newly open RandomAccessFile, never null
   */
  private RandomAccessFile openFile(String name,
                                    File file)
    throws ZipException, IOException
  {
    try
      {
        return
          (name != null)
          ? new RandomAccessFile(name, "r")
          : new RandomAccessFile(file, "r");
      }
    catch (FileNotFoundException f)
      {
        ZipException ze = new ZipException(f.getMessage());
        ze.initCause(f);
        throw ze;
      }
  }


  /**
   * Opens a Zip file with the given name for reading.
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the file doesn't contain a valid zip
   * archive.
   */
  public ZipFile(String name) throws ZipException, IOException
  {
    this.raf = openFile(name,null);
    this.name = name;
    checkZipFile();
  }

  /**
   * Opens a Zip file reading the given File.
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the file doesn't contain a valid zip
   * archive.
   */
  public ZipFile(File file) throws ZipException, IOException
  {
    this.raf = openFile(null,file);
    this.name = file.getPath();
    checkZipFile();
  }

  /**
   * Opens a Zip file reading the given File in the given mode.
   *
   * If the OPEN_DELETE mode is specified, the zip file will be deleted at
   * some time moment after it is opened. It will be deleted before the zip
   * file is closed or the Virtual Machine exits.
   *
   * The contents of the zip file will be accessible until it is closed.
   *
   * @since JDK1.3
   * @param mode Must be one of OPEN_READ or OPEN_READ | OPEN_DELETE
   *
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the file doesn't contain a valid zip
   * archive.
   */
  public ZipFile(File file, int mode) throws ZipException, IOException
  {
    if (mode != OPEN_READ && mode != (OPEN_READ | OPEN_DELETE))
      throw new IllegalArgumentException("invalid mode");
    if ((mode & OPEN_DELETE) != 0)
      file.deleteOnExit();
    this.raf = openFile(null,file);
    this.name = file.getPath();
    checkZipFile();
  }

  private void checkZipFile() throws ZipException
  {
    boolean valid = false;

    try
      {
        byte[] buf = new byte[4];
        raf.readFully(buf);
        int sig = buf[0] & 0xFF
                | ((buf[1] & 0xFF) << 8)
                | ((buf[2] & 0xFF) << 16)
                | ((buf[3] & 0xFF) << 24);
        valid = sig == LOCSIG;
      }
    catch (IOException _)
      {
      }

    if (!valid)
      {
        try
          {
            raf.close();
          }
        catch (IOException _)
          {
          }
        throw new ZipException("Not a valid zip file");
      }
  }

  /**
   * Checks if file is closed and throws an exception.
   */
  private void checkClosed()
  {
    if (closed)
      throw new IllegalStateException("ZipFile has closed: " + name);
  }

  /**
   * Read the central directory of a zip file and fill the entries
   * array.  This is called exactly once when first needed. It is called
   * while holding the lock on <code>raf</code>.
   *
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the central directory is malformed
   */
  private void readEntries() throws ZipException, IOException
  {
    /* Search for the End Of Central Directory.  When a zip comment is
     * present the directory may start earlier.
     * Note that a comment has a maximum length of 64K, so that is the
     * maximum we search backwards.
     */
    PartialInputStream inp = new PartialInputStream(raf, 4096);
    long pos = raf.length() - ENDHDR;
    long top = Math.max(0, pos - 65536);
    do
      {
        if (pos < top)
          throw new ZipException
            ("central directory not found, probably not a zip file: " + name);
        inp.seek(pos--);
      }
    while (inp.readLeInt() != ENDSIG);

    if (inp.skip(ENDTOT - ENDNRD) != ENDTOT - ENDNRD)
      throw new EOFException(name);
    int count = inp.readLeShort();
    if (inp.skip(ENDOFF - ENDSIZ) != ENDOFF - ENDSIZ)
      throw new EOFException(name);
    int centralOffset = inp.readLeInt();

    entries = new LinkedHashMap<String, ZipEntry> (count+count/2);
    inp.seek(centralOffset);

    for (int i = 0; i < count; i++)
      {
        if (inp.readLeInt() != CENSIG)
          throw new ZipException("Wrong Central Directory signature: " + name);

        inp.skip(6);
        int method = inp.readLeShort();
        int dostime = inp.readLeInt();
        int crc = inp.readLeInt();
        int csize = inp.readLeInt();
        int size = inp.readLeInt();
        int nameLen = inp.readLeShort();
        int extraLen = inp.readLeShort();
        int commentLen = inp.readLeShort();
        inp.skip(8);
        int offset = inp.readLeInt();
        String name = inp.readString(nameLen);

        ZipEntry entry = new ZipEntry(name);
        entry.setMethod(method);
        entry.setCrc(crc & 0xffffffffL);
        entry.setSize(size & 0xffffffffL);
        entry.setCompressedSize(csize & 0xffffffffL);
        entry.setDOSTime(dostime);
        if (extraLen > 0)
          {
            byte[] extra = new byte[extraLen];
            inp.readFully(extra);
            entry.setExtra(extra);
          }
        if (commentLen > 0)
          {
            entry.setComment(inp.readString(commentLen));
          }
        entry.offset = offset;
        entries.put(name, entry);
      }
  }

  /**
   * Closes the ZipFile.  This also closes all input streams given by
   * this class.  After this is called, no further method should be
   * called.
   *
   * @exception IOException if a i/o error occured.
   */
  public void close() throws IOException
  {
    RandomAccessFile raf = this.raf;
    if (raf == null)
      return;

    synchronized (raf)
      {
        closed = true;
        entries = null;
        raf.close();
      }
  }

  /**
   * Calls the <code>close()</code> method when this ZipFile has not yet
   * been explicitly closed.
   */
  protected void finalize() throws IOException
  {
    if (!closed && raf != null) close();
  }

  /**
   * Returns an enumeration of all Zip entries in this Zip file.
   *
   * @exception IllegalStateException when the ZipFile has already been closed
   */
  public Enumeration<? extends ZipEntry> entries()
  {
    checkClosed();

    try
      {
        return new ZipEntryEnumeration(getEntries().values().iterator());
      }
    catch (IOException ioe)
      {
        return new EmptyEnumeration<ZipEntry>();
      }
  }

  /**
   * Checks that the ZipFile is still open and reads entries when necessary.
   *
   * @exception IllegalStateException when the ZipFile has already been closed.
   * @exception IOException when the entries could not be read.
   */
  private LinkedHashMap<String, ZipEntry> getEntries() throws IOException
  {
    synchronized(raf)
      {
        checkClosed();

        if (entries == null)
          readEntries();

        return entries;
      }
  }

  /**
   * Searches for a zip entry in this archive with the given name.
   *
   * @param name the name. May contain directory components separated by
   * slashes ('/').
   * @return the zip entry, or null if no entry with that name exists.
   *
   * @exception IllegalStateException when the ZipFile has already been closed
   */
  public ZipEntry getEntry(String name)
  {
    checkClosed();

    try
      {
        LinkedHashMap<String, ZipEntry> entries = getEntries();
        ZipEntry entry = entries.get(name);
        // If we didn't find it, maybe it's a directory.
        if (entry == null && !name.endsWith("/"))
          entry = entries.get(name + '/');
        return entry != null ? new ZipEntry(entry, name) : null;
      }
    catch (IOException ioe)
      {
        return null;
      }
  }

  /**
   * Creates an input stream reading the given zip entry as
   * uncompressed data.  Normally zip entry should be an entry
   * returned by getEntry() or entries().
   *
   * This implementation returns null if the requested entry does not
   * exist.  This decision is not obviously correct, however, it does
   * appear to mirror Sun's implementation, and it is consistant with
   * their javadoc.  On the other hand, the old JCL book, 2nd Edition,
   * claims that this should return a "non-null ZIP entry".  We have
   * chosen for now ignore the old book, as modern versions of Ant (an
   * important application) depend on this behaviour.  See discussion
   * in this thread:
   * http://gcc.gnu.org/ml/java-patches/2004-q2/msg00602.html
   *
   * @param entry the entry to create an InputStream for.
   * @return the input stream, or null if the requested entry does not exist.
   *
   * @exception IllegalStateException when the ZipFile has already been closed
   * @exception IOException if a i/o error occured.
   * @exception ZipException if the Zip archive is malformed.
   */
  public InputStream getInputStream(ZipEntry entry) throws IOException
  {
    checkClosed();

    LinkedHashMap<String, ZipEntry> entries = getEntries();
    String name = entry.getName();
    ZipEntry zipEntry = entries.get(name);
    if (zipEntry == null)
      return null;

    PartialInputStream inp = new PartialInputStream(raf, 1024);
    inp.seek(zipEntry.offset);

    if (inp.readLeInt() != LOCSIG)
      throw new ZipException("Wrong Local header signature: " + name);

    inp.skip(4);

    if (zipEntry.getMethod() != inp.readLeShort())
      throw new ZipException("Compression method mismatch: " + name);

    inp.skip(16);

    int nameLen = inp.readLeShort();
    int extraLen = inp.readLeShort();
    inp.skip(nameLen + extraLen);

    inp.setLength(zipEntry.getCompressedSize());

    int method = zipEntry.getMethod();
    switch (method)
      {
      case ZipOutputStream.STORED:
        return inp;
      case ZipOutputStream.DEFLATED:
        inp.addDummyByte();
        final Inflater inf = new Inflater(true);
        final int sz = (int) entry.getSize();
        return new InflaterInputStream(inp, inf)
        {
          public int available() throws IOException
          {
            if (sz == -1)
              return super.available();
            if (super.available() != 0)
              return sz - inf.getTotalOut();
            return 0;
          }
        };
      default:
        throw new ZipException("Unknown compression method " + method);
      }
  }

  /**
   * Returns the (path) name of this zip file.
   */
  public String getName()
  {
    return name;
  }

  /**
   * Returns the number of entries in this zip file.
   *
   * @exception IllegalStateException when the ZipFile has already been closed
   */
  public int size()
  {
    checkClosed();

    try
      {
        return getEntries().size();
      }
    catch (IOException ioe)
      {
        return 0;
      }
  }

  private static class ZipEntryEnumeration implements Enumeration<ZipEntry>
  {
    private final Iterator<ZipEntry> elements;

    public ZipEntryEnumeration(Iterator<ZipEntry> elements)
    {
      this.elements = elements;
    }

    public boolean hasMoreElements()
    {
      return elements.hasNext();
    }

    public ZipEntry nextElement()
    {
      /* We return a clone, just to be safe that the user doesn't
       * change the entry.
       */
      return (ZipEntry) (elements.next().clone());
    }
  }

  private static final class PartialInputStream extends InputStream
  {
    /**
     * The UTF-8 charset use for decoding the filenames.
     */
    private static final Charset UTF8CHARSET = Charset.forName("UTF-8");

    /**
     * The actual UTF-8 decoder. Created on demand.
     */
    private CharsetDecoder utf8Decoder;

    private final RandomAccessFile raf;
    private final byte[] buffer;
    private long bufferOffset;
    private int pos;
    private long end;
    // We may need to supply an extra dummy byte to our reader.
    // See Inflater.  We use a count here to simplify the logic
    // elsewhere in this class.  Note that we ignore the dummy
    // byte in methods where we know it is not needed.
    private int dummyByteCount;

    public PartialInputStream(RandomAccessFile raf, int bufferSize)
      throws IOException
    {
      this.raf = raf;
      buffer = new byte[bufferSize];
      bufferOffset = -buffer.length;
      pos = buffer.length;
      end = raf.length();
    }

    void setLength(long length)
    {
      end = bufferOffset + pos + length;
    }

    private void fillBuffer() throws IOException
    {
      synchronized (raf)
        {
          long len = end - bufferOffset;
          if (len == 0 && dummyByteCount > 0)
            {
              buffer[0] = 0;
              dummyByteCount = 0;
            }
          else
            {
              raf.seek(bufferOffset);
              raf.readFully(buffer, 0, (int) Math.min(buffer.length, len));
            }
        }
    }

    public int available()
    {
      long amount = end - (bufferOffset + pos);
      if (amount > Integer.MAX_VALUE)
        return Integer.MAX_VALUE;
      return (int) amount;
    }

    public int read() throws IOException
    {
      if (bufferOffset + pos >= end + dummyByteCount)
        return -1;
      if (pos == buffer.length)
        {
          bufferOffset += buffer.length;
          pos = 0;
          fillBuffer();
        }

      return buffer[pos++] & 0xFF;
    }

    public int read(byte[] b, int off, int len) throws IOException
    {
      if (len > end + dummyByteCount - (bufferOffset + pos))
        {
          len = (int) (end + dummyByteCount - (bufferOffset + pos));
          if (len == 0)
            return -1;
        }

      int totalBytesRead = Math.min(buffer.length - pos, len);
      System.arraycopy(buffer, pos, b, off, totalBytesRead);
      pos += totalBytesRead;
      off += totalBytesRead;
      len -= totalBytesRead;

      while (len > 0)
        {
          bufferOffset += buffer.length;
          pos = 0;
          fillBuffer();
          int remain = Math.min(buffer.length, len);
          System.arraycopy(buffer, pos, b, off, remain);
          pos += remain;
          off += remain;
          len -= remain;
          totalBytesRead += remain;
        }

      return totalBytesRead;
    }

    public long skip(long amount) throws IOException
    {
      if (amount < 0)
        return 0;
      if (amount > end - (bufferOffset + pos))
        amount = end - (bufferOffset + pos);
      seek(bufferOffset + pos + amount);
      return amount;
    }

    void seek(long newpos) throws IOException
    {
      long offset = newpos - bufferOffset;
      if (offset >= 0 && offset <= buffer.length)
        {
          pos = (int) offset;
        }
      else
        {
          bufferOffset = newpos;
          pos = 0;
          fillBuffer();
        }
    }

    void readFully(byte[] buf) throws IOException
    {
      if (read(buf, 0, buf.length) != buf.length)
        throw new EOFException();
    }

    void readFully(byte[] buf, int off, int len) throws IOException
    {
      if (read(buf, off, len) != len)
        throw new EOFException();
    }

    int readLeShort() throws IOException
    {
      int result;
      if(pos + 1 < buffer.length)
        {
          result = ((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8);
          pos += 2;
        }
      else
        {
          int b0 = read();
          int b1 = read();
          if (b1 == -1)
            throw new EOFException();
          result = (b0 & 0xff) | (b1 & 0xff) << 8;
        }
      return result;
    }

    int readLeInt() throws IOException
    {
      int result;
      if(pos + 3 < buffer.length)
        {
          result = (((buffer[pos + 0] & 0xff) | (buffer[pos + 1] & 0xff) << 8)
                   | ((buffer[pos + 2] & 0xff)
                       | (buffer[pos + 3] & 0xff) << 8) << 16);
          pos += 4;
        }
      else
        {
          int b0 = read();
          int b1 = read();
          int b2 = read();
          int b3 = read();
          if (b3 == -1)
            throw new EOFException();
          result =  (((b0 & 0xff) | (b1 & 0xff) << 8) | ((b2 & 0xff)
                    | (b3 & 0xff) << 8) << 16);
        }
      return result;
    }

    /**
     * Decode chars from byte buffer using UTF8 encoding.  This
     * operation is performance-critical since a jar file contains a
     * large number of strings for the name of each file in the
     * archive.  This routine therefore avoids using the expensive
     * utf8Decoder when decoding is straightforward.
     *
     * @param buffer the buffer that contains the encoded character
     *        data
     * @param pos the index in buffer of the first byte of the encoded
     *        data
     * @param length the length of the encoded data in number of
     *        bytes.
     *
     * @return a String that contains the decoded characters.
     */
    private String decodeChars(byte[] buffer, int pos, int length)
      throws IOException
    {
      String result;
      int i=length - 1;
      while ((i >= 0) && (buffer[i] <= 0x7f))
        {
          i--;
        }
      if (i < 0)
        {
          result = new String(buffer, 0, pos, length);
        }
      else
        {
          ByteBuffer bufferBuffer = ByteBuffer.wrap(buffer, pos, length);
          if (utf8Decoder == null)
            utf8Decoder = UTF8CHARSET.newDecoder();
          utf8Decoder.reset();
          char [] characters = utf8Decoder.decode(bufferBuffer).array();
          result = String.valueOf(characters);
        }
      return result;
    }

    String readString(int length) throws IOException
    {
      if (length > end - (bufferOffset + pos))
        throw new EOFException();

      String result = null;
      try
        {
          if (buffer.length - pos >= length)
            {
              result = decodeChars(buffer, pos, length);
              pos += length;
            }
          else
            {
              byte[] b = new byte[length];
              readFully(b);
              result = decodeChars(b, 0, length);
            }
        }
      catch (UnsupportedEncodingException uee)
        {
          throw new AssertionError(uee);
        }
      return result;
    }

    public void addDummyByte()
    {
      dummyByteCount = 1;
    }
  }
}
