Example #1
0
  @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);
    }
  }