@Override public boolean feed(final ByteBuf buffer, final boolean isLast) throws Exception { boolean offered = offer(new BodyChunk(buffer, isLast)); if (offered && listener != null) { listener.onContentAdded(); } return offered; }
public StreamedBody(FeedableBodyGenerator bodyGenerator, long contentLength) { this.body = bodyGenerator.createBody(); this.subscriber = new SimpleSubscriber(bodyGenerator); this.contentLength = contentLength; }
/** * {@inheritDoc} */ @Override public Body createBody() { return new InputStreamBody(inputStream, contentLength); }
@Override public boolean feed(ByteBuf buffer, boolean isLast) throws Exception { return feedableBodyGenerator.feed(buffer, isLast); }
@BeforeMethod public void setUp() { feedableBodyGenerator = new UnboundedQueueFeedableBodyGenerator(); listener = new TestFeedListener(); feedableBodyGenerator.setListener(listener); }
@Test public void returnZeroToSuspendStreamWhenNothingIsInQueue() throws Exception { byte[] content = "Test123".getBytes(StandardCharsets.US_ASCII); ByteBuf source = Unpooled.wrappedBuffer(content); ByteBuf target = Unpooled.buffer(1); try { feedableBodyGenerator.feed(source, false); Body body = feedableBodyGenerator.createBody(); assertEquals(readFromBody(body), "Test123".getBytes(StandardCharsets.US_ASCII)); assertEquals(body.transferTo(target), BodyState.SUSPEND); } finally { source.release(); target.release(); } }
@Override public void setListener(FeedListener listener) { feedListener = listener; feedableBodyGenerator.setListener(listener); }
/** * {@inheritDoc} */ @Override public Body createBody() { return new ByteBody(); }
/** * Creates a Streamable Body which takes a Content-Length. * If the contentLength parameter is -1L a Http Header of Transfer-Encoding: chunked will be set. * Otherwise it will set the Content-Length header to the value provided * * @param publisher Body as a Publisher * @param contentLength Content-Length of the Body */ public ReactiveStreamsBodyGenerator(Publisher<ByteBuf> publisher, long contentLength) { this.publisher = publisher; this.feedableBodyGenerator = new UnboundedQueueFeedableBodyGenerator(); this.contentLength = contentLength; }
@Override public Body createBody() { return new StreamedBody(feedableBodyGenerator, contentLength); }
public T setBody(Publisher<ByteBuf> publisher, long contentLength) { return setBody(new ReactiveStreamsBodyGenerator(publisher, contentLength)); }
@Override public Body createBody() { return new PushBody(queue); }
@Override public BodyState transferTo(final ByteBuf target) { switch (state) { case CONTINUE: return readNextChunk(target); case STOP: return BodyState.STOP; default: throw new IllegalStateException("Illegal process state."); } }
@Override public void onError(Throwable t) { assertNotNull(t, "throwable"); LOGGER.debug("Error occurred while consuming body stream.", t); FeedListener listener = feedListener; if (listener != null) { listener.onError(t); } }
private BodyState readNextChunk(ByteBuf target) { BodyState res = BodyState.SUSPEND; while (target.isWritable() && state != BodyState.STOP) { BodyChunk nextChunk = queue.peek(); if (nextChunk == null) { // Nothing in the queue. suspend stream if nothing was read. (reads == 0) return res; } else if (!nextChunk.buffer.isReadable() && !nextChunk.last) { // skip empty buffers queue.remove(); } else { res = BodyState.CONTINUE; readChunk(target, nextChunk); } } return res; }
@Override public void onComplete() { try { feeder.feed(Unpooled.EMPTY_BUFFER, true); } catch (Exception e) { LOGGER.info("Ignoring exception occurred while completing stream processing.", e); this.subscription.cancel(); } } }
@Test public void readingBytesReturnsFedContentWithoutChunkBoundaries() throws Exception { byte[] content = "Test123".getBytes(StandardCharsets.US_ASCII); ByteBuf source = Unpooled.wrappedBuffer(content); ByteBuf target = Unpooled.buffer(1); try { feedableBodyGenerator.feed(source, true); Body body = feedableBodyGenerator.createBody(); assertEquals(readFromBody(body), "Test123".getBytes(StandardCharsets.US_ASCII)); assertEquals(body.transferTo(target), BodyState.STOP); } finally { source.release(); target.release(); } }
@Override public void onNext(ByteBuf b) { assertNotNull(b, "bytebuf"); try { feeder.feed(b, false); } catch (Exception e) { LOGGER.error("Exception occurred while processing element in stream.", e); subscription.cancel(); } }
private void feed(FeedableBodyGenerator feedableBodyGenerator, InputStream is) throws Exception { try (InputStream inputStream = is) { byte[] buffer = new byte[512]; for (int i; (i = inputStream.read(buffer)) > -1; ) { byte[] chunk = new byte[i]; System.arraycopy(buffer, 0, chunk, 0, i); feedableBodyGenerator.feed(Unpooled.wrappedBuffer(chunk), false); } } feedableBodyGenerator.feed(Unpooled.EMPTY_BUFFER, true); }