1 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 ; 36 import java.io.OutputStream ; 37 import java.util.zip.CRC32 ; 38 import java.util.zip.Deflater ; 39 import java.util.zip.DeflaterOutputStream ; 40 41 47 public class ZlibOutputStream extends AbstractBinaryOutput { 48 private OutputStream _os; 49 private DeflaterOutputStream _out; 50 private CRC32 _crc32; 51 52 private byte[] _header = { 53 (byte) 0x1f, (byte) 0x8b, 8, 0, 0, 0, 0, 0, 0, 0x3 }; 60 61 private int _encodingMode; 62 private boolean _isGzip; 63 private long _inputSize; 64 65 72 private ZlibOutputStream(OutputStream os, Deflater def) 73 throws IOException 74 { 75 _os = os; 76 _out = new DeflaterOutputStream (_os, def); 77 78 _os.write(_header, 0, _header.length); 79 } 80 81 89 public ZlibOutputStream(OutputStream os, 90 int compressionLevel, 91 int strategy, 92 int encodingMode) 93 throws IOException 94 { 95 this(os, createDeflater(compressionLevel, strategy, encodingMode)); 96 97 _isGzip = (encodingMode == ZlibModule.FORCE_GZIP); 98 99 if (_isGzip) 100 _crc32 = new CRC32 (); 101 } 102 103 108 public ZlibOutputStream(OutputStream os, int compressionLevel, int strategy) 109 throws IOException 110 { 111 this(os, compressionLevel, strategy, ZlibModule.FORCE_GZIP); 112 } 113 114 117 public ZlibOutputStream(OutputStream os) 118 throws IOException 119 { 120 this(os, 121 Deflater.DEFAULT_COMPRESSION, 122 Deflater.DEFAULT_STRATEGY, 123 ZlibModule.FORCE_GZIP); 124 } 125 126 129 private static Deflater createDeflater(int compressionLevel, 130 int strategy, 131 int encodingMode) 132 { 133 Deflater def; 134 135 if (encodingMode == ZlibModule.FORCE_GZIP) 136 def = new Deflater (compressionLevel, true); 137 else 138 def = new Deflater (compressionLevel, false); 139 140 def.setStrategy(strategy); 141 142 return def; 143 } 144 145 150 public void write(int v) 151 throws IOException 152 { 153 _out.write(v); 154 155 _inputSize++; 156 157 if (_isGzip) 158 _crc32.update(v); 159 } 160 161 166 public void write(byte[] buffer, int offset, int length) 167 throws IOException 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 out) 178 throws IOException 179 { 180 out.finish(); 181 182 OutputStream 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 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 e) { 228 throw new RuntimeException (e); 229 } 230 } 231 232 235 public boolean isEOF() 236 { 237 return false; 238 } 239 240 243 public long getPosition() 244 { 245 return _inputSize; 246 } 247 248 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 e) { 268 throw new QuercusModuleException(e); 269 } 270 } 271 272 public String toString() 273 { 274 return "ZlibOutputStream[]"; 275 } 276 } 277 | Popular Tags |