KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > zlib > ZlibOutputStream


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Nam Nguyen
28  */

29
30 package com.caucho.quercus.lib.zlib;
31
32 import com.caucho.quercus.QuercusModuleException;
33 import com.caucho.quercus.lib.file.AbstractBinaryOutput;
34
35 import java.io.IOException JavaDoc;
36 import java.io.OutputStream JavaDoc;
37 import java.util.zip.CRC32 JavaDoc;
38 import java.util.zip.Deflater JavaDoc;
39 import java.util.zip.DeflaterOutputStream JavaDoc;
40
41 /**
42  * As opposed to java's GZIPOutputStream, this class allows for more control on
43  * what is written to the underlying OutputStream.
44  *
45  * @see java.util.zip.GZIPOutputStream
46  */

47 public class ZlibOutputStream extends AbstractBinaryOutput {
48   private OutputStream JavaDoc _os;
49   private DeflaterOutputStream JavaDoc _out;
50   private CRC32 JavaDoc _crc32;
51
52   private byte[] _header = {
53     (byte) 0x1f, (byte) 0x8b, // gzip file identifier (ID1, ID2)
54
8, // Deflate compression method (CM)
55
0, // optional flags (FLG)
56
0, 0, 0, 0, // modification time (MTIME)
57
0, // extra optional flags (XFL)
58
0x3 // operating system (OS)
59
};
60
61   private int _encodingMode;
62   private boolean _isGzip;
63   private long _inputSize;
64
65   /**
66    * Writes gzip header to OutputStream upon construction.
67    * XXX: set operating system (file architecure) header.
68    *
69    * @param out
70    * @param def
71    */

72   private ZlibOutputStream(OutputStream JavaDoc os, Deflater JavaDoc def)
73     throws IOException JavaDoc
74   {
75     _os = os;
76     _out = new DeflaterOutputStream JavaDoc(_os, def);
77     
78     _os.write(_header, 0, _header.length);
79   }
80
81   /**
82    * @param out
83    * @param compressionLevel
84    * @param strategy Deflate compression strategy
85    * @param encodingMode FORCE_GZIP to write gzwrite compatible output;
86    * FORCE_DEFLATE to write gzip header and zlib header, but do not
87    * write crc32 trailer
88    */

89   public ZlibOutputStream(OutputStream JavaDoc os,
90               int compressionLevel,
91               int strategy,
92               int encodingMode)
93     throws IOException JavaDoc
94   {
95     this(os, createDeflater(compressionLevel, strategy, encodingMode));
96
97     _isGzip = (encodingMode == ZlibModule.FORCE_GZIP);
98
99     if (_isGzip)
100       _crc32 = new CRC32 JavaDoc();
101   }
102
103   /**
104    * @param out
105    * @param compressionLevel
106    * @param strategy Deflate compression strategy
107    */

108   public ZlibOutputStream(OutputStream JavaDoc os, int compressionLevel, int strategy)
109     throws IOException JavaDoc
110   {
111     this(os, compressionLevel, strategy, ZlibModule.FORCE_GZIP);
112   }
113
114   /**
115    * @param out
116    */

117   public ZlibOutputStream(OutputStream JavaDoc os)
118     throws IOException JavaDoc
119   {
120     this(os,
121      Deflater.DEFAULT_COMPRESSION,
122      Deflater.DEFAULT_STRATEGY,
123      ZlibModule.FORCE_GZIP);
124   }
125
126   /**
127    * Creates a deflater based on the Zlib arguments.
128    */

129   private static Deflater JavaDoc createDeflater(int compressionLevel,
130                      int strategy,
131                      int encodingMode)
132   {
133     Deflater JavaDoc def;
134
135     if (encodingMode == ZlibModule.FORCE_GZIP)
136       def = new Deflater JavaDoc(compressionLevel, true);
137     else
138       def = new Deflater JavaDoc(compressionLevel, false);
139
140     def.setStrategy(strategy);
141
142     return def;
143   }
144
145   /**
146    * Writes a byte.
147    *
148    * @param input
149    */

150   public void write(int v)
151     throws IOException JavaDoc
152   {
153     _out.write(v);
154
155     _inputSize++;
156     
157     if (_isGzip)
158       _crc32.update(v);
159   }
160
161   /**
162    * @param input
163    * @param offset
164    * @param length
165    */

166   public void write(byte[] buffer, int offset, int length)
167     throws IOException JavaDoc
168   {
169     _out.write(buffer, offset, length);
170     
171     _inputSize += length;
172     
173     if (_isGzip)
174       _crc32.update(buffer, offset, length);
175   }
176
177   private void finish(DeflaterOutputStream JavaDoc out)
178     throws IOException JavaDoc
179   {
180     out.finish();
181
182     OutputStream JavaDoc os = _os;
183
184     if (_isGzip) {
185       long crcValue = _crc32.getValue();
186       
187       byte[] trailerCRC = new byte[4];
188       
189       trailerCRC[0] = (byte) crcValue;
190       trailerCRC[1] = (byte) (crcValue >> 8);
191       trailerCRC[2] = (byte) (crcValue >> 16);
192       trailerCRC[3] = (byte) (crcValue >> 24);
193       
194       _os.write(trailerCRC, 0, trailerCRC.length);
195     }
196
197     _os.write((byte) _inputSize);
198     _os.write((byte) (_inputSize >> 8));
199     _os.write((byte) (_inputSize >> 16));
200     _os.write((byte) (_inputSize >> 24));
201
202     _os.flush();
203   }
204
205   public void flush()
206   {
207   }
208
209   public void closeWrite()
210   {
211     close();
212   }
213   
214   public void close()
215   {
216     try {
217       DeflaterOutputStream JavaDoc out = _out;
218       _out = null;
219
220       if (out != null) {
221     finish(out);
222
223     out.close();
224       }
225
226       _os.close();
227     } catch (IOException JavaDoc e) {
228       throw new RuntimeException JavaDoc(e);
229     }
230   }
231
232   /**
233    * Returns false always for an write stream.
234    */

235   public boolean isEOF()
236   {
237     return false;
238   }
239
240   /**
241    * Tells the position in the gzip stream
242    */

243   public long getPosition()
244   {
245     return _inputSize;
246   }
247
248   /**
249    * Sets the position.
250    */

251   public boolean setPosition(long offset)
252   {
253     if (offset < _inputSize)
254       return false;
255
256     offset -= _inputSize;
257     byte[] buffer = new byte[128];
258
259     try {
260       while (offset > 0) {
261         int sublen = (int)Math.min(offset, buffer.length);
262         write(buffer, 0, sublen);
263         offset -= sublen;
264       }
265
266       return true;
267     } catch (IOException JavaDoc e) {
268       throw new QuercusModuleException(e);
269     }
270   }
271
272   public String JavaDoc toString()
273   {
274     return "ZlibOutputStream[]";
275   }
276 }
277
Popular Tags