/* ZipOutputStream.java --
   Copyright (C) 2001, 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 java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Vector;

/**
 * This is a FilterOutputStream that writes the files into a zip
 * archive one after another.  It has a special method to start a new
 * zip entry.  The zip entries contains information about the file name
 * size, compressed size, CRC, etc.
 *
 * It includes support for STORED and DEFLATED entries.
 *
 * This class is not thread safe.
 *
 * @author Jochen Hoenicke 
 */
public class ZipOutputStream extends DeflaterOutputStream implements ZipConstants
{
  private Vector entries = new Vector();
  private CRC32 crc = new CRC32();
  private ZipEntry curEntry = null;

  private int curMethod;
  private int size;
  private int offset = 0;

  private byte[] zipComment = new byte[0];
  private int defaultMethod = DEFLATED;

  /**
   * Our Zip version is hard coded to 1.0 resp. 2.0
   */
  private static final int ZIP_STORED_VERSION = 10;
  private static final int ZIP_DEFLATED_VERSION = 20;

  /**
   * Compression method.  This method doesn't compress at all.
   */
  public static final int STORED = 0;
  
  /**
   * Compression method.  This method uses the Deflater.
   */
  public static final int DEFLATED = 8;

  /**
   * Creates a new Zip output stream, writing a zip archive.
   * @param out the output stream to which the zip archive is written.
   */
  public ZipOutputStream(OutputStream out)
  {
    super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
  }

  /**
   * Set the zip file comment.
   * @param comment the comment.
   * @exception IllegalArgumentException if encoding of comment is
   * longer than 0xffff bytes.
   */
  public void setComment(String comment)
  {
    byte[] commentBytes;
    try
      {
	commentBytes = comment.getBytes("UTF-8");
      }
    catch (UnsupportedEncodingException uee)
      {
	throw new AssertionError(uee);
      }
    if (commentBytes.length > 0xffff)
      throw new IllegalArgumentException("Comment too long.");
    zipComment = commentBytes;
  }
  
  /**
   * Sets default compression method.  If the Zip entry specifies
   * another method its method takes precedence.
   * @param method the method.
   * @exception IllegalArgumentException if method is not supported.
   * @see #STORED
   * @see #DEFLATED
   */
  public void setMethod(int method)
  {
    if (method != STORED && method != DEFLATED)
      throw new IllegalArgumentException("Method not supported.");
    defaultMethod = method;
  }

  /**
   * Sets default compression level.  The new level will be activated
   * immediately.  
   * @exception IllegalArgumentException if level is not supported.
   * @see Deflater
   */
  public void setLevel(int level)
  {
    def.setLevel(level);
  }
  
  /**
   * Write an unsigned short in little endian byte order.
   */
  private void writeLeShort(int value) throws IOException 
  {
    out.write(value & 0xff);
    out.write((value >> 8) & 0xff);
  }

  /**
   * Write an int in little endian byte order.
   */
  private void writeLeInt(int value) throws IOException 
  {
    writeLeShort(value);
    writeLeShort(value >> 16);
  }

  /**
   * Write a long value as an int.  Some of the zip constants
   * are declared as longs even though they fit perfectly well
   * into integers.
   */
  private void writeLeInt(long value) throws IOException
  {
    writeLeInt((int) value);
  }

  /**
   * Starts a new Zip entry. It automatically closes the previous
   * entry if present.  If the compression method is stored, the entry
   * must have a valid size and crc, otherwise all elements (except
   * name) are optional, but must be correct if present.  If the time
   * is not set in the entry, the current time is used.
   * @param entry the entry.
   * @exception IOException if an I/O error occured.
   * @exception ZipException if stream was finished.
   */
  public void putNextEntry(ZipEntry entry) throws IOException
  {
    if (entries == null)
      throw new ZipException("ZipOutputStream was finished");

    int method = entry.getMethod();
    int flags = 0;
    if (method == -1)
      method = defaultMethod;

    if (method == STORED)
      {
	if (entry.getCompressedSize() >= 0)
	  {
	    if (entry.getSize() < 0)
	      entry.setSize(entry.getCompressedSize());
	    else if (entry.getSize() != entry.getCompressedSize())
	      throw new ZipException
		("Method STORED, but compressed size != size");
	  }
	else
	  entry.setCompressedSize(entry.getSize());

	if (entry.getSize() < 0)
	  throw new ZipException("Method STORED, but size not set");
	if (entry.getCrc() < 0)
	  throw new ZipException("Method STORED, but crc not set");
      }
    else if (method == DEFLATED)
      {
	if (entry.getCompressedSize() < 0
	    || entry.getSize() < 0 || entry.getCrc() < 0)
	  flags |= 8;
      }

    if (curEntry != null)
      closeEntry();

    if (entry.getTime() < 0)
      entry.setTime(System.currentTimeMillis());

    entry.flags = flags;
    entry.offset = offset;
    entry.setMethod(method);
    curMethod = method;
    /* Write the local file header */
    writeLeInt(LOCSIG);
    writeLeShort(method == STORED
		 ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
    writeLeShort(flags);
    writeLeShort(method);
    writeLeInt(entry.getDOSTime());
    if ((flags & 8) == 0)
      {
	writeLeInt((int)entry.getCrc());
	writeLeInt((int)entry.getCompressedSize());
	writeLeInt((int)entry.getSize());
      }
    else
      {
	writeLeInt(0);
	writeLeInt(0);
	writeLeInt(0);
      }
    byte[] name;
    try
      {
	name = entry.getName().getBytes("UTF-8");
      }
    catch (UnsupportedEncodingException uee)
      {
	throw new AssertionError(uee);
      }
    if (name.length > 0xffff)
      throw new ZipException("Name too long.");
    byte[] extra = entry.getExtra();
    if (extra == null)
      extra = new byte[0];
    writeLeShort(name.length);
    writeLeShort(extra.length);
    out.write(name);
    out.write(extra);

    offset += LOCHDR + name.length + extra.length;

    /* Activate the entry. */

    curEntry = entry;
    crc.reset();
    if (method == DEFLATED)
      def.reset();
    size = 0;
  }

  /**
   * Closes the current entry.
   * @exception IOException if an I/O error occured.
   * @exception ZipException if no entry is active.
   */
  public void closeEntry() throws IOException
  {
    if (curEntry == null)
      throw new ZipException("No open entry");

    /* First finish the deflater, if appropriate */
    if (curMethod == DEFLATED)
      super.finish();

    int csize = curMethod == DEFLATED ? def.getTotalOut() : size;

    if (curEntry.getSize() < 0)
      curEntry.setSize(size);
    else if (curEntry.getSize() != size)
      throw new ZipException("size was "+size
			     +", but I expected "+curEntry.getSize());

    if (curEntry.getCompressedSize() < 0)
      curEntry.setCompressedSize(csize);
    else if (curEntry.getCompressedSize() != csize)
      throw new ZipException("compressed size was "+csize
			     +", but I expected "+curEntry.getSize());

    if (curEntry.getCrc() < 0)
      curEntry.setCrc(crc.getValue());
    else if (curEntry.getCrc() != crc.getValue())
      throw new ZipException("crc was " + Long.toHexString(crc.getValue())
			     + ", but I expected " 
			     + Long.toHexString(curEntry.getCrc()));

    offset += csize;

    /* Now write the data descriptor entry if needed. */
    if (curMethod == DEFLATED && (curEntry.flags & 8) != 0)
      {
	writeLeInt(EXTSIG);
	writeLeInt((int)curEntry.getCrc());
	writeLeInt((int)curEntry.getCompressedSize());
	writeLeInt((int)curEntry.getSize());
	offset += EXTHDR;
      }

    entries.addElement(curEntry);
    curEntry = null;
  }

  /**
   * Writes the given buffer to the current entry.
   * @exception IOException if an I/O error occured.
   * @exception ZipException if no entry is active.
   */
  public void write(byte[] b, int off, int len) throws IOException
  {
    if (curEntry == null)
      throw new ZipException("No open entry.");

    switch (curMethod)
      {
      case DEFLATED:
	super.write(b, off, len);
	break;
	
      case STORED:
	out.write(b, off, len);
	break;
      }

    crc.update(b, off, len);
    size += len;
  }

  /**
   * Finishes the stream.  This will write the central directory at the
   * end of the zip file and flush the stream.
   * @exception IOException if an I/O error occured.
   */
  public void finish() throws IOException
  {
    if (entries == null)
      return;
    if (curEntry != null)
      closeEntry();

    int numEntries = 0;
    int sizeEntries = 0;
    
    Enumeration e = entries.elements();
    while (e.hasMoreElements())
      {
	ZipEntry entry = (ZipEntry) e.nextElement();
	
	int method = entry.getMethod();
	writeLeInt(CENSIG);
	writeLeShort(method == STORED
		     ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
	writeLeShort(method == STORED
		     ? ZIP_STORED_VERSION : ZIP_DEFLATED_VERSION);
	writeLeShort(entry.flags);
	writeLeShort(method);
	writeLeInt(entry.getDOSTime());
	writeLeInt((int)entry.getCrc());
	writeLeInt((int)entry.getCompressedSize());
	writeLeInt((int)entry.getSize());

	byte[] name;
	try
	  {
	    name = entry.getName().getBytes("UTF-8");
	  }
	catch (UnsupportedEncodingException uee)
	  {
	    throw new AssertionError(uee);
	  }
	if (name.length > 0xffff)
	  throw new ZipException("Name too long.");
	byte[] extra = entry.getExtra();
	if (extra == null)
	  extra = new byte[0];
	String str = entry.getComment();
	byte[] comment;
	try
	  {
	    comment = str != null ? str.getBytes("UTF-8") : new byte[0];
	  }
	catch (UnsupportedEncodingException uee)
	  {
	    throw new AssertionError(uee);
	  }
	if (comment.length > 0xffff)
	  throw new ZipException("Comment too long.");

	writeLeShort(name.length);
	writeLeShort(extra.length);
	writeLeShort(comment.length);
	writeLeShort(0); /* disk number */
	writeLeShort(0); /* internal file attr */
	writeLeInt(0);   /* external file attr */
	writeLeInt(entry.offset);

	out.write(name);
	out.write(extra);
	out.write(comment);
	numEntries++;
	sizeEntries += CENHDR + name.length + extra.length + comment.length;
      }

    writeLeInt(ENDSIG);
    writeLeShort(0); /* disk number */
    writeLeShort(0); /* disk with start of central dir */
    writeLeShort(numEntries);
    writeLeShort(numEntries);
    writeLeInt(sizeEntries);
    writeLeInt(offset);
    writeLeShort(zipComment.length);
    out.write(zipComment);
    out.flush();
    entries = null;
  }
}
