All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.induct.http.ning.NingResponse Maven / Gradle / Ivy

The newest version!
package io.induct.http.ning;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterators;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.ning.http.client.AsyncHandler;
import com.ning.http.client.HttpResponseBodyPart;
import com.ning.http.client.HttpResponseHeaders;
import com.ning.http.client.HttpResponseStatus;
import com.stackoverflow.collections.ByteBufferBackedInputStream;
import com.stackoverflow.guava.CaseInsensitiveForwardingMap;
import io.induct.http.Response;
import io.induct.util.concurrent.SyncValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * @since 15.2.2015
 */
public class NingResponse implements Response, AsyncHandler {

    public static final int INVALID_STATUS_CODE = -1;
    private final Logger log = LoggerFactory.getLogger(NingResponse.class);

    private STATE state = STATE.CONTINUE;

    private List responseBody = new LinkedList<>();

    private final SyncValue statusCode;
    private final SyncValue> headers;
    private final SyncValue body;

    private final CountDownLatch readHeaders = new CountDownLatch(1);

    public NingResponse() {
        statusCode = new SyncValue<>();
        headers = new SyncValue<>();
        body = new SyncValue<>();
    }

    @Override
    public void onThrowable(Throwable t) {
        state = STATE.ABORT;

        if (!statusCode.isAssigned())
            statusCode.push(INVALID_STATUS_CODE);

        if (!headers.isAssigned())
            headers.push(HashMultimap.create());

        if (!body.isAssigned())
            body.push(null);
    }

    @Override
    public STATE onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
        if (state != STATE.ABORT) {
            statusCode.push(responseStatus.getStatusCode());
        }
        return state;
    }

    @Override
    public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
        readHeaders.await();
        if (state != STATE.ABORT) {
            Multimap convertedHeaders = newCaseInsensitiveMultiMap();
            for (Map.Entry> h : headers.getHeaders().entrySet()) {
                convertedHeaders.putAll(h.getKey(), h.getValue());
            }
            this.headers.push(convertedHeaders);
        }
        return state;
    }

    @Override
    public STATE onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
        if (state != STATE.ABORT) {
            ByteBuffer part = bodyPart.getBodyByteBuffer();
            responseBody.add(part);
            log.trace("Received response body part of {} bytes", part.capacity());
        }
        return state;
    }

    private ListMultimap newCaseInsensitiveMultiMap() {
        return Multimaps.newListMultimap(new CaseInsensitiveForwardingMap<>(Maps.newHashMap()), Lists::newLinkedList);
    }

    @Override
    public String onCompleted() throws Exception {
        if (state != STATE.ABORT) {

            Iterator responseIterators = FluentIterable.from(responseBody)
                    .transform(new Function() {
                        @Override
                        public InputStream apply(ByteBuffer input) {
                            return new ByteBufferBackedInputStream(input);
                        }
                    })
                    .iterator();
            Enumeration responseEnumeration = Iterators.asEnumeration(responseIterators);
            this.body.push(new BufferedInputStream(new SequenceInputStream(responseEnumeration)));
        }
        return ""; // we don't care
    }

    @Override
    public int getStatusCode() {
        return statusCode.get();
    }

    @Override
    public Multimap getResponseHeaders() {
        allowHeaderReading();
        return headers.get();
    }

    @Override
    public Optional getResponseBody() {
        allowHeaderReading();
        InputStream content = body.get();
        if (content == null) {
            return Optional.absent();
        } else {
            return Optional.of(content);
        }
    }

    @Override
    public void close() {
        state = STATE.ABORT;
    }

    private void allowHeaderReading() {
        if (readHeaders.getCount() > 0) readHeaders.countDown();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy