package com.jdroid.java.http;
import com.jdroid.java.collections.Lists;
import com.jdroid.java.collections.Maps;
import com.jdroid.java.exception.UnexpectedException;
import com.jdroid.java.http.parser.Parser;
import com.jdroid.java.utils.EncodingUtils;
import com.jdroid.java.utils.FileUtils;
import com.jdroid.java.utils.LoggerUtils;
import com.jdroid.java.utils.StringUtils;
import org.slf4j.Logger;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public abstract class AbstractHttpService implements HttpService {
protected static final Logger LOGGER = LoggerUtils.getLogger(AbstractHttpService.class);
private Boolean ssl = false;
/** Connection timeout in milliseconds. 10 seconds as default */
private Integer connectionTimeout = 10000;
/** Read timeout in milliseconds. 60 seconds as default */
private Integer readTimeout = 60000;
/** Write timeout in milliseconds. 60 seconds as default */
private Integer writeTimeout = 60000;
private String userAgent;
private Server server;
private List<Object> urlSegments;
/** Query Parameter values of the request. */
private Map<String, String> queryParameters = Maps.newLinkedHashMap();
/** Header values of the request. */
private Map<String, String> headers = Maps.newHashMap();
private List<HttpServiceProcessor> httpServiceProcessors = Lists.newArrayList();
private HttpResponseWrapper httpResponseWrapper;
/**
* @param httpServiceProcessors
* @param urlSegments
* @param server The {@link Server} where execute the request
*/
public AbstractHttpService(Server server, List<Object> urlSegments,
List<HttpServiceProcessor> httpServiceProcessors) {
this.urlSegments = Lists.newArrayList();
if (urlSegments != null) {
for (Object segment : urlSegments) {
addUrlSegment(segment);
}
}
this.server = server;
if (httpServiceProcessors != null) {
for (HttpServiceProcessor each : httpServiceProcessors) {
addHttpServiceProcessor(each);
}
}
}
@SuppressWarnings("unchecked")
@Override
public final void execute() {
execute(null);
}
@Override
public <T> T execute(Parser parser) {
InputStream inputStream = null;
try {
for (HttpServiceProcessor each : httpServiceProcessors) {
each.beforeExecute(this);
}
String url = getUrl();
// Log request
LOGGER.debug(getHttpMethod() + ": " + url);
if (!queryParameters.isEmpty()) {
LOGGER.debug("Query Parameters: " + queryParameters.toString());
}
if (!headers.isEmpty()) {
LOGGER.debug("Headers: " + headers.toString());
}
httpResponseWrapper = doExecute(url);
for (HttpServiceProcessor each : httpServiceProcessors) {
each.afterExecute(this, httpResponseWrapper);
}
// parse and return response.
if (parser != null) {
inputStream = httpResponseWrapper.getInputStream();
if (inputStream != null) {
return parse(parser, inputStream);
} else {
throw new UnexpectedException("The http service was expecting a response, but it was null");
}
}
return null;
} finally {
FileUtils.safeClose(inputStream);
doFinally();
}
}
protected void doFinally() {
// Do Nothing
}
public abstract HttpMethod getHttpMethod();
protected abstract HttpResponseWrapper doExecute(String url);
@SuppressWarnings("unchecked")
protected <T> T parse(Parser parser, InputStream inputStream) {
return (T)parser.parse(inputStream);
}
@Override
public void setSsl(Boolean ssl) {
this.ssl = ssl;
}
public Boolean isSsl() {
return ssl;
}
@Override
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
@Override
public void setConnectionTimeout(Integer connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
public Integer getConnectionTimeout() {
return connectionTimeout;
}
public Integer getReadTimeout() {
return readTimeout;
}
@Override
public void setReadTimeout(Integer readTimeout) {
this.readTimeout = readTimeout;
}
public Integer getWriteTimeout() {
return writeTimeout;
}
@Override
public void setWriteTimeout(Integer writeTimeout) {
this.writeTimeout = writeTimeout;
}
public String getUserAgent() {
return userAgent;
}
@Override
public String getUrl() {
StringBuilder builder = new StringBuilder();
builder.append(isSsl() && getServer().supportsSsl() ? HTTPS_PROTOCOL : HTTP_PROTOCOL);
builder.append("://");
builder.append(getServer().getBaseUrl());
builder.append(getUrlSuffix());
return builder.toString();
}
@Override
public String getUrlSuffix() {
StringBuilder builder = new StringBuilder();
builder.append(getUrlSegments());
builder.append(makeStringParameters());
return builder.toString();
}
protected String makeStringParameters() {
StringBuilder params = new StringBuilder();
boolean isFirst = true;
for (Map.Entry<String, String> entry : getQueryParameters().entrySet()) {
if (isFirst) {
params.append(QUESTION_MARK);
isFirst = false;
} else {
params.append(AMPERSAND);
}
params.append(entry.getKey());
params.append(EQUALS);
params.append(entry.getValue());
}
return params.toString();
}
@Override
public void addQueryParameter(String name, Collection<?> values) {
addQueryParameter(name, StringUtils.join(values));
}
@Override
public void addQueryParameter(String name, Object value) {
if (value != null) {
queryParameters.put(name, EncodingUtils.encodeURL(value.toString()));
}
}
/**
* @return the Query parameters
*/
public Map<String, String> getQueryParameters() {
return queryParameters;
}
public Server getServer() {
return server;
}
@Override
public void addUrlSegment(Object segment) {
String segmentString = segment.toString();
if (StringUtils.isNotEmpty(segmentString)) {
urlSegments.add(EncodingUtils.encodeURL(segmentString));
}
}
public String getUrlSegments() {
return urlSegments.isEmpty() ? StringUtils.EMPTY : StringUtils.SLASH
+ StringUtils.join(urlSegments, StringUtils.SLASH);
}
public Map<String, String> getHeaders() {
return headers;
}
@Override
public String getHeaderValue(String key) {
return headers.get(key);
}
@Override
public void addHeader(String name, String value) {
if (value != null) {
headers.put(name, value);
}
}
@Override
public String toString() {
return getClass().getSimpleName() + " - " + server.getBaseUrl();
}
@Override
public void addHttpServiceProcessor(HttpServiceProcessor httpServiceProcessor) {
httpServiceProcessors.add(httpServiceProcessor);
httpServiceProcessor.onInit(this);
}
@Override
public HttpResponseWrapper getHttpResponseWrapper() {
return httpResponseWrapper;
}
}