private void flushInputToStream(final OutputStream pStream) throws IOException { System.out.println("DeflateEncoder.flushInputToStream"); if (deflater.needsInput()) { System.out.println("Foo"); } while (!deflater.needsInput()) { int deflated = deflater.deflate(buffer, 0, buffer.length); pStream.write(buffer, 0, deflated); System.out.println("flushed " + deflated); } }
@Override public void encode(ChannelBuffer compressed) { while (!compressor.needsInput()) { int numBytes = compressor.deflate(out, 0, out.length, Deflater.SYNC_FLUSH); compressed.writeBytes(out, 0, numBytes); } }
@Override public void write(byte[] b, int off, int len) throws IOException { if (_def.finished()) throw new IOException("Stream already finished"); if ((off | len | (off + len) | (b.length - (off + len))) < 0) throw new IndexOutOfBoundsException(); if (len == 0) return; if (!_def.finished()) { _def.setInput(b, off, len); while (!_def.needsInput()) { deflate(); } } }
/** Writes bytes to ZIP entry. */ public void write(byte[] b, int offset, int length) throws IOException { if (entry.getMethod() == DEFLATED) { if (length > 0) { if (!def.finished()) { def.setInput(b, offset, length); while (!def.needsInput()) { deflate(); } } } } else { writeOut(b, offset, length); written += length; } crc.update(b, offset, length); }
/** * {@collect.stats} {@description.open} Writes an array of bytes to the compressed output stream. * This method will block until all the bytes are written. {@description.close} * * @param b the data to be written * @param off the start offset of the data * @param len the length of the data * @exception IOException if an I/O error has occurred */ public void write(byte[] b, int off, int len) throws IOException { if (def.finished()) { throw new IOException("write beyond end of stream"); } if ((off | len | (off + len) | (b.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } if (!def.finished()) { // Deflate no more than stride bytes at a time. This avoids // excess copying in deflateBytes (see Deflater.c) int stride = buf.length; for (int i = 0; i < len; i += stride) { def.setInput(b, off + i, Math.min(stride, len - i)); while (!def.needsInput()) { deflate(); } } } }
/** * Reads compressed data into a byte array. This method will block until some input can be read * and compressed. * * @param b buffer into which the data is read * @param off starting offset of the data within {@code b} * @param len maximum number of compressed bytes to read into {@code b} * @return the actual number of bytes read, or -1 if the end of the uncompressed input stream is * reached * @throws IndexOutOfBoundsException if {@code len} > {@code b.length - off} * @throws IOException if an I/O error occurs or if this input stream is already closed */ public int read(byte[] b, int off, int len) throws IOException { // Sanity checks ensureOpen(); if (b == null) { throw new NullPointerException("Null buffer for read"); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } // Read and compress (deflate) input data bytes int cnt = 0; while (len > 0 && !def.finished()) { int n; // Read data from the input stream if (def.needsInput()) { n = in.read(buf, 0, buf.length); if (n < 0) { // End of the input stream reached def.finish(); } else if (n > 0) { def.setInput(buf, 0, n); } } // Compress the input data, filling the read buffer n = def.deflate(b, off, len); cnt += n; off += n; len -= n; } if (cnt == 0 && def.finished()) { reachEOF = true; cnt = -1; } return cnt; }
private void deflateUntilInputIsNeeded() throws IOException { while (!def.needsInput()) { deflate(); } }
@Override public List<MessagePart> sendMessagePart(List<MessagePart> uncompressedParts) { List<MessagePart> allCompressedParts = new ArrayList<MessagePart>(); for (MessagePart uncompressedPart : uncompressedParts) { byte opCode = uncompressedPart.getOpCode(); if (Util.isControl(opCode)) { // Control messages can appear in the middle of other messages // and must not be compressed. Pass it straight through allCompressedParts.add(uncompressedPart); } else { List<MessagePart> compressedParts = new ArrayList<MessagePart>(); ByteBuffer uncompressedPayload = uncompressedPart.getPayload(); SendHandler uncompressedIntermediateHandler = uncompressedPart.getIntermediateHandler(); deflater.setInput( uncompressedPayload.array(), uncompressedPayload.arrayOffset() + uncompressedPayload.position(), uncompressedPayload.remaining()); int flush = (uncompressedPart.isFin() ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH); boolean deflateRequired = true; while (deflateRequired) { ByteBuffer compressedPayload = writeBuffer; int written = deflater.deflate( compressedPayload.array(), compressedPayload.arrayOffset() + compressedPayload.position(), compressedPayload.remaining(), flush); compressedPayload.position(compressedPayload.position() + written); if (!uncompressedPart.isFin() && compressedPayload.hasRemaining() && deflater.needsInput()) { // This message part has been fully processed by the // deflater. Fire the send handler for this message part // and move on to the next message part. break; } // If this point is reached, a new compressed message part // will be created... MessagePart compressedPart; // .. and a new writeBuffer will be required. writeBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE); // Flip the compressed payload ready for writing compressedPayload.flip(); boolean fin = uncompressedPart.isFin(); boolean full = compressedPayload.limit() == compressedPayload.capacity(); boolean needsInput = deflater.needsInput(); if (fin && !full && needsInput) { // End of compressed message. Drop EOM bytes and output. compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length); compressedPart = new MessagePart( true, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; startNewMessage(); } else if (full && !needsInput) { // Write buffer full and input message not fully read. // Output and start new compressed part. compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); } else if (!fin && full && needsInput) { // Write buffer full and input message not fully read. // Output and get more data. compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; } else if (fin && full && needsInput) { // Write buffer full. Input fully read. Deflater may be // in one of four states: // - output complete (just happened to align with end of // buffer // - in middle of EOM bytes // - about to write EOM bytes // - more data to write int eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, EOM_BUFFER.length, Deflater.SYNC_FLUSH); if (eomBufferWritten < EOM_BUFFER.length) { // EOM has just been completed compressedPayload.limit( compressedPayload.limit() - EOM_BYTES.length + eomBufferWritten); compressedPart = new MessagePart( true, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); deflateRequired = false; startNewMessage(); } else { // More data to write // Copy bytes to new write buffer writeBuffer.put(EOM_BUFFER, 0, eomBufferWritten); compressedPart = new MessagePart( false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler); } } else { throw new IllegalStateException("Should never happen"); } // Add the newly created compressed part to the set of parts // to pass on to the next transformation. compressedParts.add(compressedPart); } SendHandler uncompressedEndHandler = uncompressedPart.getEndHandler(); int size = compressedParts.size(); if (size > 0) { compressedParts.get(size - 1).setEndHandler(uncompressedEndHandler); } allCompressedParts.addAll(compressedParts); } } if (next == null) { return allCompressedParts; } else { return next.sendMessagePart(allCompressedParts); } }