co.cask.cdap.internal.app.runtime.service.http.AbstractHttpServiceResponder.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.internal.app.runtime.service.http.AbstractHttpServiceResponder.java

Source

/*
 * Copyright  2016 Cask Data, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package co.cask.cdap.internal.app.runtime.service.http;

import co.cask.cdap.api.service.http.HttpContentProducer;
import co.cask.cdap.api.service.http.HttpServiceResponder;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
import org.apache.twill.filesystem.Location;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * An abstract implementation of {@link HttpServiceResponder} to simplify
 * concrete implementation of {@link HttpServiceResponder}.
 */
public abstract class AbstractHttpServiceResponder implements HttpServiceResponder {

    @Override
    public final void sendJson(Object object) {
        sendJson(HttpResponseStatus.OK.getCode(), object);
    }

    @Override
    public final void sendJson(int status, Object object) {
        sendJson(status, object, object.getClass(), new Gson());
    }

    @Override
    public final void sendJson(int status, Object object, Type type, Gson gson) {
        doSend(status, "application/json",
                ChannelBuffers.wrappedBuffer(Charsets.UTF_8.encode(gson.toJson(object, type))), null, null);
    }

    @Override
    public final void sendString(String data) {
        sendString(HttpResponseStatus.OK.getCode(), data, Charsets.UTF_8);
    }

    @Override
    public final void sendString(int status, String data, Charset charset) {
        doSend(status, "text/plain; charset=" + charset.name(), ChannelBuffers.wrappedBuffer(charset.encode(data)),
                null, null);
    }

    @Override
    public final void sendStatus(int status) {
        sendStatus(status, ImmutableMap.<String, String>of());
    }

    @Override
    public final void sendStatus(int status, Map<String, String> headers) {
        sendStatus(status, headers.entrySet());
    }

    @Override
    public final void sendStatus(int status, Iterable<? extends Map.Entry<String, String>> headers) {
        doSend(status, "text/plain", null, null, createMultimap(headers));
    }

    @Override
    public final void sendError(int status, String errorMessage) {
        sendString(status, errorMessage, Charsets.UTF_8);
    }

    @Override
    public final void send(int status, ByteBuffer content, String contentType, Map<String, String> headers) {
        send(status, content, contentType, headers.entrySet());
    }

    @Override
    public final void send(int status, ByteBuffer content, String contentType,
            Iterable<? extends Map.Entry<String, String>> headers) {
        doSend(status, contentType, ChannelBuffers.copiedBuffer(content), null, createMultimap(headers));
    }

    @Override
    public final void send(int status, Location location, String contentType) throws IOException {
        send(status, location, contentType, ImmutableMap.<String, String>of());
    }

    @Override
    public final void send(int status, Location location, String contentType, Map<String, String> headers)
            throws IOException {
        send(status, location, contentType, headers.entrySet());
    }

    @Override
    public final void send(int status, Location location, String contentType,
            Iterable<? extends Map.Entry<String, String>> headers) throws IOException {
        send(status, new LocationHttpContentProducer(location), contentType, headers);
    }

    @Override
    public final void send(int status, HttpContentProducer producer, String contentType) {
        send(status, producer, contentType, ImmutableMap.<String, String>of());
    }

    @Override
    public final void send(int status, HttpContentProducer producer, String contentType,
            Map<String, String> headers) {
        send(status, producer, contentType, headers.entrySet());
    }

    @Override
    public final void send(int status, HttpContentProducer producer, String contentType,
            Iterable<? extends Map.Entry<String, String>> headers) {
        doSend(status, contentType, null, producer, createMultimap(headers));
    }

    /**
     * Sub-class to implement on how to send a response.
     *
     * @param status response status code
     * @param contentType response content type
     * @param content response body if not null
     * @param contentProducer {@link HttpContentProducer} for producing the response body if not null; if this
     *                        is non-null, content should be null.
     * @param headers response headers
     */
    protected abstract void doSend(int status, String contentType, @Nullable ChannelBuffer content,
            @Nullable HttpContentProducer contentProducer, @Nullable Multimap<String, String> headers);

    /**
     * Creates a {@link Multimap} from an {@link Iterable} of {@link Map.Entry}.
     */
    protected final <K, V> Multimap<K, V> createMultimap(Iterable<? extends Map.Entry<K, V>> entries) {
        ImmutableMultimap.Builder<K, V> builder = ImmutableMultimap.builder();
        for (Map.Entry<K, V> entry : entries) {
            builder.put(entry);
        }
        return builder.build();
    }
}