/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.nio; import java.io.*; import java.nio.ByteBuffer; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; import static com.hazelcast.nio.IOUtil.closeResource; public final class PipedZipBufferFactory { public static DeflatingPipedBuffer createDeflatingBuffer(int compressedDataSize) { return createDeflatingBuffer(compressedDataSize, Deflater.DEFAULT_COMPRESSION); } public static DeflatingPipedBuffer createDeflatingBuffer(int compressedDataSize, int compressionLevel) { return new DeflatingPipedBufferImpl(compressedDataSize, compressionLevel); } public static InflatingPipedBuffer createInflatingBuffer(int compressedDataSize) { return new InflatingPipedBufferImpl(compressedDataSize); } public interface DeflatingPipedBuffer extends PipedZipBufferCommons { DataOutput getDataOutput(); int deflate(); } public interface InflatingPipedBuffer extends PipedZipBufferCommons { DataInput getDataInput(); int inflate() throws DataFormatException; int inflate(int length) throws DataFormatException; } private interface PipedZipBufferCommons { ByteBuffer getInputBuffer(); ByteBuffer getOutputBuffer(); OutputStream getOutputStream(); InputStream getInputStream(); void reset(); void destroy(); } private static class DeflatingPipedBufferImpl extends PipedZipBufferSupport implements DeflatingPipedBuffer { private final Deflater deflater; private DataOutputStream dataOutput; private DeflatingPipedBufferImpl(int compressedDataSize, int compressionLevel) { super(compressedDataSize); deflater = new Deflater(compressionLevel); dataOutput = new DataOutputStream(getOutputStream()); } public int deflate() { try { deflater.setInput(uncompressedBuffer.array(), 0, uncompressedBuffer.position()); deflater.finish(); final int count = deflater.deflate(compressedBuffer.array()); return count; } finally { deflater.reset(); } } @Override public void reset() { super.reset(); deflater.reset(); } public ByteBuffer getInputBuffer() { return uncompressedBuffer; } public ByteBuffer getOutputBuffer() { return compressedBuffer; } public DataOutput getDataOutput() { return dataOutput; } public void destroy() { closeResource(dataOutput); dataOutput = null; deflater.end(); super.destroy(); } } private static class InflatingPipedBufferImpl extends PipedZipBufferSupport implements InflatingPipedBuffer { private final Inflater inflater = new Inflater(); private DataInputStream dataInput; private InflatingPipedBufferImpl(int compressedDataSize) { super(compressedDataSize); dataInput = new DataInputStream(getInputStream()); } public int inflate() throws DataFormatException { return inflate(compressedBuffer.capacity()); } public int inflate(int length) throws DataFormatException { try { inflater.setInput(compressedBuffer.array(), 0, length); final int count = inflater.inflate(uncompressedBuffer.array()); uncompressedBuffer.limit(count); uncompressedBuffer.position(0); return count; } finally { inflater.reset(); } } @Override public void reset() { inflater.reset(); super.reset(); } public ByteBuffer getInputBuffer() { return compressedBuffer; } public ByteBuffer getOutputBuffer() { return uncompressedBuffer; } public DataInput getDataInput() { return dataInput; } public void destroy() { closeResource(dataInput); dataInput = null; inflater.end(); super.destroy(); } } private static abstract class PipedZipBufferSupport implements PipedZipBufferCommons { protected ByteBuffer compressedBuffer; protected ByteBuffer uncompressedBuffer; protected InputStream inputStream; protected OutputStream outputStream; private PipedZipBufferSupport(int compressedDataSize) { super(); compressedBuffer = ByteBuffer.allocate(compressedDataSize); uncompressedBuffer = ByteBuffer.allocate(compressedDataSize * 10); outputStream = IOUtil.newOutputStream(getInputBuffer()); inputStream = IOUtil.newInputStream(getOutputBuffer()); } public final OutputStream getOutputStream() { return outputStream; } public final InputStream getInputStream() { return inputStream; } public void reset() { uncompressedBuffer.clear(); compressedBuffer.clear(); } public void destroy() { closeResource(inputStream); closeResource(outputStream); compressedBuffer = null; uncompressedBuffer = null; inputStream = null; outputStream = null; } } }