@Override public void setUndertowOptions(OptionMap undertowOptions) { if (undertowOptions == null) { throw UndertowMessages.MESSAGES.argumentCannotBeNull("undertowOptions"); } this.undertowOptions = undertowOptions; }
/** * 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(); } } }