001/* GZIPOutputStream.java - Create a file in gzip format
002   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010 
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package java.util.zip;
039
040import java.io.IOException;
041import java.io.OutputStream;
042
043/**
044 * This filter stream is used to compress a stream into a "GZIP" stream. 
045 * The "GZIP" format is described in RFC 1952.
046 *
047 * @author John Leuner
048 * @author Tom Tromey
049 * @since JDK 1.1
050 */
051
052/* Written using on-line Java Platform 1.2 API Specification
053 * and JCL book.
054 * Believed complete and correct.
055 */
056
057public class GZIPOutputStream extends DeflaterOutputStream
058{
059  /**
060   * CRC-32 value for uncompressed data
061   */
062  protected CRC32 crc;
063
064  /**
065   * Creates a GZIPOutputStream with the default buffer size
066   *
067   * @param out The stream to read data (to be compressed) from 
068   * 
069   */
070  public GZIPOutputStream(OutputStream out) throws IOException
071  {
072    this(out, 4096);
073  }
074
075  /**
076   * Creates a GZIPOutputStream with the specified buffer size
077   *
078   * @param out The stream to read compressed data from 
079   * @param size Size of the buffer to use 
080   */
081  public GZIPOutputStream(OutputStream out, int size) throws IOException
082  {
083    super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
084    crc = new CRC32();
085    int mod_time = (int) (System.currentTimeMillis() / 1000L);
086    byte[] gzipHeader =
087      {
088        /* The two magic bytes */
089        (byte) GZIPInputStream.GZIP_MAGIC,
090        (byte) (GZIPInputStream.GZIP_MAGIC >> 8),
091          
092        /* The compression type */
093        (byte) Deflater.DEFLATED,
094        
095        /* The flags (not set) */
096        0,
097        
098        /* The modification time */
099        (byte) mod_time, (byte) (mod_time >> 8), 
100        (byte) (mod_time >> 16), (byte) (mod_time >> 24), 
101
102        /* The extra flags */
103        0,
104    
105        /* The OS type (unknown) */
106        (byte) 255
107      };
108
109    out.write(gzipHeader);
110    //    System.err.println("wrote GZIP header (" + gzipHeader.length + " bytes )");
111  }
112
113  public synchronized void write(byte[] buf, int off, int len)
114    throws IOException
115  {
116    super.write(buf, off, len);
117    crc.update(buf, off, len);
118  }
119
120  /**
121   * Writes remaining compressed output data to the output stream
122   * and closes it.
123   */
124  public void close() throws IOException
125  {
126    finish();
127    out.close();
128  }
129
130  public void finish() throws IOException
131  {
132    super.finish();
133
134    int totalin = def.getTotalIn();
135    int crcval = (int) (crc.getValue() & 0xffffffff);
136
137    //    System.err.println("CRC val is " + Integer.toHexString( crcval )                     + " and length " + Integer.toHexString(totalin));
138    
139    byte[] gzipFooter = 
140      {
141        (byte) crcval, (byte) (crcval >> 8),
142        (byte) (crcval >> 16), (byte) (crcval >> 24),
143
144        (byte) totalin, (byte) (totalin >> 8),
145        (byte) (totalin >> 16), (byte) (totalin >> 24)
146      };
147
148    out.write(gzipFooter);
149  //    System.err.println("wrote GZIP trailer (" + gzipFooter.length + " bytes )");    
150  }
151}