@Override
 public void setUndertowOptions(OptionMap undertowOptions) {
   if (undertowOptions == null) {
     throw UndertowMessages.MESSAGES.argumentCannotBeNull("undertowOptions");
   }
   this.undertowOptions = undertowOptions;
 }
Ejemplo n.º 2
0
  /**
   * Initiate a low-copy transfer between two stream channels. The pool should be a direct buffer
   * pool for best performance.
   *
   * @param source the source channel
   * @param sink the target channel
   * @param sourceListener the source listener to set and call when the transfer is complete, or
   *     {@code null} to clear the listener at that time
   * @param sinkListener the target listener to set and call when the transfer is complete, or
   *     {@code null} to clear the listener at that time
   * @param readExceptionHandler the read exception handler to call if an error occurs during a read
   *     operation
   * @param writeExceptionHandler the write exception handler to call if an error occurs during a
   *     write operation
   * @param pool the pool from which the transfer buffer should be allocated
   */
  public static <I extends StreamSourceChannel, O extends StreamSinkChannel> void initiateTransfer(
      final I source,
      final O sink,
      final ChannelListener<? super I> sourceListener,
      final ChannelListener<? super O> sinkListener,
      final ChannelExceptionHandler<? super I> readExceptionHandler,
      final ChannelExceptionHandler<? super O> writeExceptionHandler,
      Pool<ByteBuffer> pool) {
    if (pool == null) {
      throw UndertowMessages.MESSAGES.argumentCannotBeNull("pool");
    }
    final Pooled<ByteBuffer> allocated = pool.allocate();
    boolean free = true;
    try {
      final ByteBuffer buffer = allocated.getResource();
      long read;
      for (; ; ) {
        try {
          read = source.read(buffer);
          buffer.flip();
        } catch (IOException e) {
          ChannelListeners.invokeChannelExceptionHandler(source, readExceptionHandler, e);
          return;
        }
        if (read == 0 && !buffer.hasRemaining()) {
          break;
        }
        if (read == -1 && !buffer.hasRemaining()) {
          done(source, sink, sourceListener, sinkListener);
          return;
        }
        while (buffer.hasRemaining()) {
          final int res;
          try {
            res = sink.write(buffer);
          } catch (IOException e) {
            ChannelListeners.invokeChannelExceptionHandler(sink, writeExceptionHandler, e);
            return;
          }
          if (res == 0) {
            break;
          }
        }
        if (buffer.hasRemaining()) {
          break;
        }
        buffer.clear();
      }
      Pooled<ByteBuffer> current = null;
      if (buffer.hasRemaining()) {
        current = allocated;
        free = false;
      }

      final TransferListener<I, O> listener =
          new TransferListener<I, O>(
              pool,
              current,
              source,
              sink,
              sourceListener,
              sinkListener,
              writeExceptionHandler,
              readExceptionHandler,
              read == -1);
      sink.getWriteSetter().set(listener);
      source.getReadSetter().set(listener);
      // we resume both reads and writes, as we want to keep trying to fill the buffer
      if (current == null || buffer.capacity() != buffer.remaining()) {
        // we don't resume if the buffer is 100% full
        source.resumeReads();
      }
      if (current != null) {
        // we don't resume writes if we have nothing to write
        sink.resumeWrites();
      }
    } finally {
      if (free) {
        allocated.free();
      }
    }
  }