package uc.protocols; import helpers.FDeflaterOutputStream; import helpers.FInflaterInputStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.Map; import org.apache.tools.bzip2.CBZip2InputStream; import org.apache.tools.bzip2.CBZip2OutputStream; /** * wrapper of all possible compressions supported. * * * @author Quicksilver * */ public enum Compression { NONE(""), BZ2(" BZ2"), ZLIB_FAST(" ZL1"), ZLIB_BEST(" ZL1"); private final String nmdcString; Compression(String nmdcidentifier) { nmdcString = nmdcidentifier; } /** * wraps a decompressing channel around rbc */ public CompressionWrapper wrapIncoming(ReadableByteChannel rbc) throws IOException { switch(this){ case NONE: return new CompressionWrapper(rbc); case ZLIB_FAST: case ZLIB_BEST: FInflaterInputStream zis = new FInflaterInputStream( new BufferedInputStream( Channels.newInputStream(rbc))); return new CompressionWrapper(Channels.newChannel(zis),zis); case BZ2: return new CompressionWrapper(Channels.newChannel(new CBZip2InputStream( new BufferedInputStream( Channels.newInputStream(rbc)) ))); } throw new IllegalStateException(); } /** * wraps a decompressing stream around in * */ public InputStream wrapIncoming(InputStream in) throws IOException { switch(this){ case NONE: return in; case ZLIB_FAST: case ZLIB_BEST: return new FInflaterInputStream(in); case BZ2: return new CBZip2InputStream(in); } throw new IllegalStateException(); } /** * wrap a stream so * * @param wbc - writable bytechannel that should be wrapped usually a socketchannel * @return a writable bytechannel that writes compressed info to the provided one * @throws IOException - if an error happens on creation */ public FinishWrapper wrapOutgoing(WritableByteChannel wbc) throws IOException { FDeflaterOutputStream out = null; // Deflater def; switch(this){ case NONE: return new FinishWrapper(wbc); case ZLIB_FAST: OutputStream os = new BufferedOutputStream(Channels.newOutputStream(wbc)); //out = new DeflaterOutputStream(os); // def = new Deflater(Deflater.BEST_SPEED); out = new FDeflaterOutputStream(os,true); // new ZOutputStream( os ,JZlib.Z_BEST_SPEED) ; //new Deflater(Deflater.BEST_SPEED) ); //return Channels.newChannel(new GZIPOutputStream( new BufferedOutputStream(Channels.newOutputStream(wbc)))); return new FinishWrapper(Channels.newChannel(out),out); case ZLIB_BEST: // def = new Deflater(Deflater.BEST_COMPRESSION); out = new FDeflaterOutputStream( new BufferedOutputStream(Channels.newOutputStream(wbc)),false); //new Deflater(Deflater.BEST_COMPRESSION) ); return new FinishWrapper(Channels.newChannel(out),out); case BZ2: return new FinishWrapper(Channels.newChannel(new CBZip2OutputStream( new BufferedOutputStream(Channels.newOutputStream(wbc))))); } throw new IllegalStateException(); } /** * * @param toCompress what should be compressed.. * @return bytes in compressed form.. */ public byte[] compress(byte[] toCompress) throws IOException { if (this == NONE) { return toCompress; } else { ByteBuffer bytes = ByteBuffer.wrap(toCompress); ByteArrayOutputStream baos = new ByteArrayOutputStream(); FinishWrapper fw = wrapOutgoing(Channels.newChannel(baos)); WritableByteChannel wbc = fw.getChan(); while (bytes.hasRemaining()) { wbc.write(bytes); } fw.finnish(); byte[] compressed = baos.toByteArray(); return compressed; } } /** * * @param nmdc - a string either empty or "ZL1" or "ZL2" * @return the matching compression... will return NONE as defaultvalue */ public static Compression parseProtocolString(String nmdc) { nmdc = nmdc.trim(); if ( "ZL1".equals(nmdc)) { return ZLIB_FAST; } else if ("BZ2".equals(nmdc)) { return BZ2; } else { return NONE; } } public static Compression parseAttributeMap(Map<String,String> attributes) { if ("1".equals(attributes.get("ZL"))) { return Compression.ZLIB_FAST; } else if ("2".equals("BZ")) { return BZ2; } else { return NONE; } } public String toTransferViewString() { switch(this) { case NONE: return ""; case ZLIB_FAST: case ZLIB_BEST: return "[Z]"; case BZ2: return "[BZ2]"; } return null; } public String toString() { return nmdcString; } public static class FinishWrapper implements ICompIO { private final WritableByteChannel chan; private final FDeflaterOutputStream flush; // private final Deflater def; public FinishWrapper(WritableByteChannel chan) { this(chan,null); } public FinishWrapper(WritableByteChannel chan, FDeflaterOutputStream flush /*,Deflater def*/) { this.chan = chan; this.flush = flush; } public WritableByteChannel getChan() { return chan; } public void finnish() throws IOException { if (flush != null) { flush.finish(); } } public long getCompIO() { return flush== null? 1L : flush.getTotalOut(); // .getBytesWritten(); } public long getIO() { return flush == null? 1L : flush.getTotalIn(); //def.getBytesRead(); } } public static class CompressionWrapper implements ICompIO { private final FInflaterInputStream inf; private final ReadableByteChannel rbc; public CompressionWrapper(ReadableByteChannel rbc) { this(rbc,null); } /** * * @param rbc * @param inf * */ public CompressionWrapper(ReadableByteChannel rbc, FInflaterInputStream inf) { this.inf = inf; this.rbc = rbc; } public long getCompIO() { return inf != null? inf.getTotalIn(): 1L ; } public long getIO() { return inf != null? inf.getTotalOut(): 1L ; } public ReadableByteChannel getRbc() { return rbc; } } public static interface ICompIO { /** * * @return IO data read ... always 1 if no compression */ long getIO(); /** * * @return compressed IOData read... always 1 if no compression.. */ long getCompIO(); } }