/**
*
*/
package com.emc.vipr.transform.compression;
import com.emc.vipr.transform.TransformConstants;
import com.emc.vipr.transform.encryption.KeyUtils;
import com.emc.vipr.transform.util.CountingOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
/**
* @author cwikj
*
*/
public class DeflateOutputStream extends OutputStream implements CompressionStream {
private CountingOutputStream uncompressedCounter;
private CountingOutputStream compressedCounter;
private DigestOutputStream digester;
private boolean closed;
private byte[] uncompressedDigest;
/**
* @throws IOException
*/
public DeflateOutputStream(OutputStream streamToCompress, int level) throws IOException {
Deflater def = new Deflater(level);
compressedCounter = new CountingOutputStream(streamToCompress);
DeflaterOutputStream dos = new DeflaterOutputStream(compressedCounter, def);
uncompressedCounter = new CountingOutputStream(dos);
try {
digester = new DigestOutputStream(uncompressedCounter, MessageDigest.getInstance("SHA1"));
} catch (NoSuchAlgorithmException e) {
throw new IOException("Unable to initialize digest", e);
}
closed = false;
}
@Override
public Map<String, String> getStreamMetadata() {
if(!closed) {
throw new IllegalStateException("Stream must be closed before getting metadata");
}
Map<String,String> metadata = new HashMap<String, String>();
long compSize = compressedCounter.getByteCount();
long uncompSize = uncompressedCounter.getByteCount();
String compRatioString = String.format("%.1f%%", 100.0 - (compSize*100.0/uncompSize));
metadata.put(TransformConstants.META_COMPRESSION_UNCOMP_SIZE, ""+uncompSize);
metadata.put(TransformConstants.META_COMPRESSION_COMP_SIZE, ""+compSize);
metadata.put(TransformConstants.META_COMPRESSION_COMP_RATIO, ""+compRatioString);
metadata.put(TransformConstants.META_COMPRESSION_UNCOMP_SHA1, KeyUtils.toHexPadded(uncompressedDigest));
return metadata;
}
@Override
public void write(int b) throws IOException {
digester.write(b);
}
@Override
public void close() throws IOException {
if(closed) { return; }
closed = true;
digester.close();
uncompressedDigest = digester.getMessageDigest().digest();
}
@Override
public void flush() throws IOException {
digester.flush();
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
digester.write(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
digester.write(b);
}
}