gt:     if (! def.finished())
context: /*
   * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
   *
   * This file is part of Resin(R) Open Source
   *
   * Each copy or derived work must preserve the copyright notice and this
   * notice unmodified.
   *
   * Resin Open Source 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 of the License, or
   * (at your option) any later version.
   *
   * Resin Open Source 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, or any warranty
   * of NON-INFRINGEMENT.  See the GNU General Public License for more
   * details.
   *
   * You should have received a copy of the GNU General Public License
   * along with Resin Open Source; if not, write to the
   *
   *   Free Software Foundation, Inc.
   *   59 Temple Place, Suite 330
   *   Boston, MA 02111-1307  USA
   *
   * @author Nam Nguyen
   */
  
  package com.caucho.quercus.lib.zlib;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.util.zip.CRC32;
  import java.util.zip.Deflater;
  import java.util.zip.DeflaterOutputStream;
  
  /**
   * As opposed to java's GZIPOutputStream, this class allows for more control on
   * what is written to the underlying OutputStream. 
   *
   * @see java.util.zip.GZIPOutputStream
   */
  public class GZIPOutputStream extends DeflaterOutputStream {
    private CRC32 _crc32;
  
    private byte[] _header = {
      (byte) 0x1f, (byte) 0x8b,  // gzip file identifier (ID1, ID2)
      8,           // Deflate compression method (CM)
      0,           // optional flags (FLG)
      0, 0, 0, 0,  // modification time (MTIME)
      0,           // extra optional flags (XFL)
      0            // operating system (OS)
    };
  
    private int _encodingMode;
    private boolean _isGzip;
  
    /**
     * Writes gzip header to OutputStream upon construction.
     * XXX: set operating system (file architecure) header.
     *
     * @param out
     * @param def
     */
    private GZIPOutputStream(OutputStream out, Deflater def)
      throws IOException
    {
      super(out, def);
      
      out.write(_header, 0, _header.length);
    }
  
    /**
     * @param out
     * @param compressionLevel
     * @param strategy Deflate compression strategy
     * @param encodingMode FORCE_GZIP to write gzwrite compatible output;
     *    FORCE_DEFLATE to write gzip header and zlib header,
     *    but do not write crc32 trailer
     */
    public GZIPOutputStream(OutputStream out,
                            int compressionLevel,
                            int strategy,
                            int encodingMode)
      throws IOException
    {
      this(out, createDeflater(compressionLevel, strategy, encodingMode));
  
      _isGzip = (encodingMode == ZlibModule.FORCE_GZIP);
  
      if (_isGzip)
        _crc32 = new CRC32();
  
      _encodingMode = encodingMode;
    }
  
    /**
     * Creates a deflater based on the Zlib arguments.
     */
    private static Deflater createDeflater(int compressionLevel,
                                           int strategy,
                                           int encodingMode)
    {
      Deflater defl;
  
      if (encodingMode == ZlibModule.FORCE_GZIP)
        defl = new Deflater(compressionLevel, true);
      else
        defl = new Deflater(compressionLevel, false);
  
      defl.setStrategy(strategy);
  
      return defl;
    }
  
    /**
     * @param out
     * @param compressionLevel
     * @param strategy Deflate compression strategy
     */
    public GZIPOutputStream(OutputStream out, int compressionLevel, int strategy)
      throws IOException
    {
      this(out, compressionLevel, strategy, ZlibModule.FORCE_GZIP);
    }
  
    /**
     * @param out
     */
    public GZIPOutputStream(OutputStream out)
      throws IOException
    {
      this(out, Deflater.DEFAULT_COMPRESSION, Deflater.DEFAULT_STRATEGY);
    }
  
    /**
     * Writes a byte.
     *
     * @param input
     */
    public void write(int v)
      throws IOException
    {
      super.write(v);
  
      if (_isGzip)
        _crc32.update(v);
    }
  
    /**
     * @param input
     * @param offset
     * @param length
     */
    public void write(byte[] buffer, int offset, int length)
      throws IOException
    {
      super.write(buffer, offset, length);
      
      if (_isGzip)
        _crc32.update(buffer, offset, length);
    }
  
    public void finish()
      throws IOException
    {
      super.finish();
  
      if (_isGzip) {
        long crcValue = _crc32.getValue();
        
        byte[] trailerCRC = new byte[4];
        
        trailerCRC[0] = (byte) crcValue;
        trailerCRC[1] = (byte) (crcValue >> 8);
        trailerCRC[2] = (byte) (crcValue >> 16);
        trailerCRC[3] = (byte) (crcValue >> 24);
        
        out.write(trailerCRC, 0, trailerCRC.length);
      }
  
      long inputSize = def.getBytesRead();
      
      byte[] trailerInputSize = new byte[4];
  
      trailerInputSize[0] = (byte) inputSize;
      trailerInputSize[1] = (byte) (inputSize >> 8);
      trailerInputSize[2] = (byte) (inputSize >> 16);
      trailerInputSize[3] = (byte) (inputSize >> 24);
      
      out.write(trailerInputSize, 0, trailerInputSize.length);
  
      out.flush();
    }
  
    /**
     * Calls super function, which in turn closes the underlying 'in' stream
     */
    public void close()
      throws IOException
    {
  