diff --git a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/content/ContentSourceCompletableFuture.java b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/content/ContentSourceCompletableFuture.java index ff0ef9dc7e33..f44d92832618 100644 --- a/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/content/ContentSourceCompletableFuture.java +++ b/jetty-core/jetty-io/src/main/java/org/eclipse/jetty/io/content/ContentSourceCompletableFuture.java @@ -19,31 +19,36 @@ import org.eclipse.jetty.io.Content; /** - * A utility class to convert content from a {@link Content.Source} to an instance - * available via a {@link CompletableFuture}. - *
- * An example usage to asynchronously read UTF-8 content is: - *
+ *A utility class to convert content from a {@link Content.Source} to an instance + * available via a {@link CompletableFuture}.
+ *An example usage to asynchronously read UTF-8 content is:
*{@code - * public static class FutureUtf8String extends ContentSourceCompletableFuture*/ public abstract class ContentSourceCompletableFuture; + * public static class CompletableUTF8String extends ContentSourceCompletableFuture ; + * { + * private final Utf8StringBuilder builder = new Utf8StringBuilder(); + * + * public CompletableUTF8String(Content.Source content) + * { + * super(content); + * } + * + * @Override + * protected String parse(Content.Chunk chunk) throws Throwable * { - * Utf8StringBuilder builder = new Utf8StringBuilder(); + * // Accumulate the chunk bytes. + * if (chunk.hasRemaining()) + * builder.append(chunk.getByteBuffer()); * - * public FutureUtf8String(Content.Source content) - * { - * super(content); - * } + * // Not the last chunk, the result is not ready yet. + * if (!chunk.isLast()) + * return null; * - * @Override - * protected String parse(Content.Chunk chunk) throws Throwable - * { - * if (chunk.hasRemaining()) - * builder.append(chunk.getByteBuffer()); - * return chunk.isLast() ? builder.takeCompleteString(IllegalStateException::new) : null; - * } + * // The result is ready. + * return builder.takeCompleteString(IllegalStateException::new); * } - * ... - * new FutureUtf8String(source).thenAccept(System.err::println); + * } + * + * new CompletableUTF8String(source).thenAccept(System.err::println); * }
- * This method must be called once to initiate the reading and parsing, - * and is then called to progress parsing in response to any {@link Content.Source#demand(Runnable) demand} calls. - *
+ *Initiates the parsing of the {@link Content.Source}.
+ *For every valid chunk that is read, {@link #parse(Content.Chunk)} + * is called, until a result is produced that is used to + * complete this {@link CompletableFuture}.
+ *Internally, this method is called multiple times to progress + * the parsing in response to {@link Content.Source#demand(Runnable)} + * calls.
+ *Exceptions thrown during parsing result in this + * {@link CompletableFuture} to be completed exceptionally.
*/ public void parse() { @@ -109,21 +117,24 @@ public void parse() } /** - * Called to parse a {@link org.eclipse.jetty.io.Content.Chunk} - * @param chunk The chunk containing content to parse. The chunk will never be null nor a + *Called by {@link #parse()} to parse a {@link org.eclipse.jetty.io.Content.Chunk}.
+ * + * @param chunk The chunk containing content to parse. The chunk will never be {@code null} nor a * {@link org.eclipse.jetty.io.Content.Chunk#isFailure(Content.Chunk) failure chunk}. - * If references to the content of the chunk are to be held beyond the scope of this call, - * then implementations must call {@link Content.Chunk#retain()} and {@link Content.Chunk#release()} - * as appropriate. - * @return The parsed {@code X} instance or null if parsing is not yet complete - * @throws Throwable Thrown if there is an error parsing + * If the chunk is stored away to be used later beyond the scope of this call, + * then implementations must call {@link Content.Chunk#retain()} and + * {@link Content.Chunk#release()} as appropriate. + * @return The parsed {@code X} result instance or {@code null} if parsing is not yet complete + * @throws Throwable If there is an error parsing */ protected abstract X parse(Content.Chunk chunk) throws Throwable; /** - * @param cause A {@link Content.Chunk#isLast() non-last} + *Callback method that informs the parsing about how to handle transient failures.
+ * + * @param cause A transient failure obtained by reading a {@link Content.Chunk#isLast() non-last} * {@link org.eclipse.jetty.io.Content.Chunk#isFailure(Content.Chunk) failure chunk} - * @return True if the chunk can be ignored. + * @return {@code true} if the transient failure can be ignored, {@code false} otherwise */ protected boolean onTransientFailure(Throwable cause) {