153 lines
4.7 KiB
Java
153 lines
4.7 KiB
Java
/*
|
|
* Copyright (c) 2003,2009 Declarative Engineering LLC.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Declarative Engineering LLC
|
|
* verson 1 which accompanies this distribution, and is available at
|
|
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
|
*/
|
|
package com.common.io;
|
|
|
|
import java.io.OutputStream;
|
|
import java.io.IOException;
|
|
import java.util.zip.*;
|
|
|
|
public class CompressionOutputStream extends OutputStream implements IOutputStream {
|
|
public static final int DEFAULT_BUFFER_SIZE = 301;
|
|
public static final int MAX_BUFFER_SIZE = 65535;
|
|
|
|
protected OutputStream stream = null;
|
|
protected Deflater deflater = null;
|
|
protected byte[] outputBuffer = null;
|
|
/**
|
|
* CompressionOutputStream constructor.
|
|
* @param stream The stream that will handle all output from this stream.
|
|
*/
|
|
public CompressionOutputStream(OutputStream stream) {
|
|
this(stream, null, DEFAULT_BUFFER_SIZE);
|
|
}//CompressionOutputStream()//
|
|
/**
|
|
* CompressionOutputStream constructor.
|
|
* @param stream The stream that will handle all output from this stream.
|
|
* @param deflater The deflater to be used.
|
|
*/
|
|
public CompressionOutputStream(OutputStream stream, Deflater deflater) {
|
|
this(stream, deflater, DEFAULT_BUFFER_SIZE);
|
|
}//CompressionOutputStream()//
|
|
/**
|
|
* CompressionOutputStream constructor.
|
|
* @param stream The stream that will handle all output from this stream.
|
|
* @param deflater The deflater to be used.
|
|
* @param bufferSize The size of the buffer used to read from the deflater.
|
|
*/
|
|
public CompressionOutputStream(OutputStream stream, Deflater deflater, int bufferSize) {
|
|
//Validate the inputs.//
|
|
if(bufferSize < 1) {
|
|
throw new IllegalArgumentException("Buffer size must be greater than zero.");
|
|
}//if//
|
|
else if(bufferSize > MAX_BUFFER_SIZE) {
|
|
throw new IllegalArgumentException("Buffer size must be less than " + MAX_BUFFER_SIZE + ".");
|
|
}//else if//
|
|
else if(stream == null) {
|
|
throw new IllegalArgumentException("A non-null output stream must be provided.");
|
|
}//else if//
|
|
else if(deflater == null) {
|
|
deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
|
|
}//else if//
|
|
|
|
this.stream = stream;
|
|
this.deflater = deflater;
|
|
this.outputBuffer = new byte[bufferSize];
|
|
}//CompressionOutputStream()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.IOutputStream#canEncrypt()
|
|
*/
|
|
public boolean canEncrypt() {
|
|
return (stream instanceof IOutputStream) && (((IOutputStream) stream).canEncrypt());
|
|
}//canEncrypt()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.OutputStream#close()
|
|
*/
|
|
public void close() throws IOException {
|
|
deflater.finish();
|
|
deflate();
|
|
|
|
super.close();
|
|
}//close()//
|
|
/**
|
|
* Deflates the cached data.
|
|
*/
|
|
private void deflate() throws IOException {
|
|
int count = 0;
|
|
|
|
while((count = deflater.deflate(outputBuffer, 2, outputBuffer.length - 2)) > 0) {
|
|
StreamSupport.writeShort((short) count, outputBuffer, 0); //Note: count should never exceed the buffer length and thus should stay within two bytes in size.//
|
|
stream.write(outputBuffer, 0, count + 2);
|
|
}//while//
|
|
|
|
/* Another way of doing the same thing I think.
|
|
while(!deflater.needsInput()) {
|
|
int count = deflater.deflate(outputBuffer);
|
|
|
|
if(count > 0) {
|
|
stream.write(outputBuffer, 0, count);
|
|
}//if//
|
|
}//while//
|
|
*/
|
|
}//deflate()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.IOutputStream#encrypt(boolean)
|
|
*/
|
|
public void encrypt(boolean encrypt) throws IOException {
|
|
if(stream instanceof IOutputStream) {
|
|
if(((IOutputStream) stream).canEncrypt()) {
|
|
flush();
|
|
((IOutputStream) stream).encrypt(encrypt);
|
|
}//if//
|
|
else {
|
|
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
|
}//else//
|
|
}//if//
|
|
else {
|
|
throw new IOException(ERROR_ENCRYPTION_NOT_SUPPORTED);
|
|
}//else//
|
|
}//encrypt()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.OutputStream#flush()
|
|
*/
|
|
public void flush() throws IOException {
|
|
if(deflater.getTotalIn() > 0) {
|
|
deflater.finish();
|
|
deflate();
|
|
deflater.reset();
|
|
}//if//
|
|
|
|
stream.flush();
|
|
}//flush()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.IOutputStream#isEncrypting()
|
|
*/
|
|
public boolean isEncrypting() {
|
|
return (stream instanceof IOutputStream) && (((IOutputStream) stream).isEncrypting());
|
|
}//isEncrypting()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.OutputStream#write(byte[])
|
|
*/
|
|
public void write(byte[] buffer) throws IOException {
|
|
write(buffer, 0, buffer.length);
|
|
}//write()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.OutputStream#write(byte[], int, int)
|
|
*/
|
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
|
deflater.setInput(buffer, offset, length);
|
|
deflate();
|
|
}//write()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.OutputStream#write(int)
|
|
*/
|
|
public void write(int b) throws IOException {
|
|
outputBuffer[0] = (byte) (b & 0xFF);
|
|
write(outputBuffer, 0, 1);
|
|
}//write()//
|
|
}//CompressionOutputStream//
|