io.induct.http.ning.NingResponse Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of http-ning Show documentation
Show all versions of http-ning Show documentation
Uploads all artifacts belonging to configuration ':http-ning:archives'
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();
}
}