// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jdisc.handler; import com.google.common.util.concurrent.ForwardingListenableFuture; import com.google.common.util.concurrent.ListenableFuture; import com.yahoo.jdisc.Response; import com.yahoo.jdisc.SharedResource; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.Future; /** *
This class provides a convenient way of safely dispatching a {@link Response}. It is similar in use to {@link * RequestDispatch}, where you need to subclass and implement and override the appropriate methods. Because a Response * is not a {@link SharedResource}, its construction is less strenuous, and this class is able to provide a handful of * convenient factory methods to dispatch the simplest of Responses.
*The following is a simple example on how to use this class without the factories:
** public void signalInternalError(ResponseHandler handler) { * new ResponseDispatch() { * @Override * protected Response newResponse() { * return new Response(Response.Status.INTERNAL_SERVER_ERROR); * } * @Override * protected Iterable<ByteBuffer> responseContent() { * return Collections.singleton(ByteBuffer.wrap(new byte[] { 6, 9 })); * } * }.dispatch(handler); * } ** * @author Simon Thoresen Hult */ public abstract class ResponseDispatch extends ForwardingListenableFuture
Creates and returns the {@link Response} to dispatch.
* * @return The Response to dispatch. */ protected abstract Response newResponse(); /** *Returns an Iterable for the ByteBuffers that the {@link #dispatch(ResponseHandler)} method should write to the * {@link Response} once it has {@link ResponseHandler#handleResponse(Response) connected}. The default * implementation returns an empty list. Because this method uses the Iterable interface, you can provide the * ByteBuffers lazily, or as they become available.
* * @return The ByteBuffers to write to the Response's ContentChannel. */ protected IterableThis methods calls {@link #newResponse()} to create a new {@link Response}, and then calls {@link * ResponseHandler#handleResponse(Response)} with that.
* * @param responseHandler The ResponseHandler to connect to. * @return The ContentChannel to write the Response's content to. */ public final ContentChannel connect(ResponseHandler responseHandler) { return responseHandler.handleResponse(newResponse()); } /** *Convenience method for constructing a {@link FastContentWriter} over the {@link ContentChannel} returned by * calling {@link #connect(ResponseHandler)}.
* * @param responseHandler The ResponseHandler to connect to. * @return The FastContentWriter for the connected Response. */ public final FastContentWriter connectFastWriter(ResponseHandler responseHandler) { return new FastContentWriter(connect(responseHandler)); } /** *This method calls {@link #connect(ResponseHandler)} to establish a {@link ContentChannel} for the {@link
* Response}, and then iterates through all the ByteBuffers returned by {@link #responseContent()} and writes them
* to that ContentChannel. This method uses a finally
block to make sure that the ContentChannel is always
* {@link ContentChannel#close(CompletionHandler) closed}.
The returned Future will wait for all CompletionHandlers associated with the Response have been * completed.
* * @param responseHandler The ResponseHandler to dispatch to. * @return A Future that can be waited for. */ public final ListenableFutureFactory method for creating a ResponseDispatch with a {@link Response} that has the given status code, and * ByteBuffer content.
* * @param responseStatus The status code of the Response to dispatch. * @param content The ByteBuffer content of the Response, may be empty. * @return The created ResponseDispatch. */ public static ResponseDispatch newInstance(int responseStatus, ByteBuffer... content) { return newInstance(new Response(responseStatus), Arrays.asList(content)); } /** *Factory method for creating a ResponseDispatch with a {@link Response} that has the given status code, and * collection of ByteBuffer content. * Because this method uses the Iterable interface, you can create the ByteBuffers lazily, or * provide them as they become available.
* * @param responseStatus The status code of the Response to dispatch. * @param content The provider of the Response's ByteBuffer content. * @return The created ResponseDispatch. */ public static ResponseDispatch newInstance(int responseStatus, IterableFactory method for creating a ResponseDispatch over a given {@link Response} and ByteBuffer content.
* * @param response The Response to dispatch. * @param content The ByteBuffer content of the Response, may be empty. * @return The created ResponseDispatch. */ public static ResponseDispatch newInstance(Response response, ByteBuffer... content) { return newInstance(response, Arrays.asList(content)); } /** *Factory method for creating a ResponseDispatch over a given {@link Response} and ByteBuffer content. * Because this method uses the Iterable interface, you can create the ByteBuffers lazily, or provide them as they * become available.
* * @param response The Response to dispatch. * @param content The provider of the Response's ByteBuffer content. * @return The created ResponseDispatch. */ public static ResponseDispatch newInstance(Response response, Iterable