package com.nowellpoint.oauth.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import com.fasterxml.jackson.databind.ObjectMapper;
public class HttpRequestBuilder {
private String target;
private String path;
private String bearerToken;
private List<NameValuePair> header;
private List<NameValuePair> queryParameters;
public HttpRequestBuilder() {
header = new ArrayList<NameValuePair>();
queryParameters = new ArrayList<NameValuePair>();
}
public HttpRequestBuilder target(String target) {
this.target = target;
return this;
}
public HttpRequestBuilder path(String path) {
this.path = path;
return this;
}
public HttpRequestBuilder bearerToken(String bearerToken) {
this.bearerToken = bearerToken;
return this;
}
public HttpRequestBuilder header(String name, String value) {
header.add(new NameValuePair(name, value));
return this;
}
public HttpRequestBuilder queryParameter(String name, String value) {
queryParameters.add(new NameValuePair(name, value));
return this;
}
public HttpRequest build() throws IOException {
return new HttpRequestImpl(this);
}
private class HttpRequestImpl implements HttpRequest {
private String target;
private String path;
private String bearerToken;
private List<NameValuePair> header = new ArrayList<NameValuePair>();
private List<NameValuePair> queryParameters = new ArrayList<NameValuePair>();
private HttpsURLConnection connection = null;
private HttpRequestImpl(HttpRequestBuilder builder) throws IOException {
this.target = builder.target;
this.path = builder.path;
this.bearerToken = builder.bearerToken;
this.header = builder.header;
this.queryParameters = builder.queryParameters;
this.connection = openConnection();
}
@Override
public <T> HttpResponse<T> get(Class<T> type) throws HttpException {
HttpResponse<T> response = null;
try {
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Authorization", "Bearer " + bearerToken);
connection.setRequestProperty("Accept", "application/json");
response = new HttpResponseImpl<T>(type, connection);
} catch (IOException e) {
throw new HttpException(e.getMessage());
} finally {
connection.disconnect();
}
return response;
}
@Override
public <T> HttpResponse<T> post() throws HttpException {
HttpResponse<T> response = null;
try {
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setDoOutput(true);
for (NameValuePair nameValuePair : header) {
connection.setRequestProperty(nameValuePair.getName(), nameValuePair.getValue());
}
response = new HttpResponseImpl<T>(connection);
} catch (IOException e) {
throw new HttpException(e.getMessage());
} finally {
connection.disconnect();
}
return response;
}
@Override
public <T> HttpResponse<T> post(Class<T> type) throws HttpException {
HttpResponse<T> response = null;
try {
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setDoOutput(true);
for (NameValuePair nameValuePair : header) {
connection.setRequestProperty(nameValuePair.getName(), nameValuePair.getValue());
}
response = new HttpResponseImpl<T>(type, connection);
} catch (IOException e) {
throw new HttpException(e.getMessage());
} finally {
connection.disconnect();
}
return response;
}
@Override
public void clear() {
target = null;
path = null;
bearerToken = null;
header = new ArrayList<NameValuePair>();
queryParameters = new ArrayList<NameValuePair>();
connection = null;
}
@Override
public URL getUrl() {
return connection.getURL();
}
private HttpsURLConnection openConnection() throws IOException {
StringBuilder sb = new StringBuilder().append(target);
if (path != null) {
sb.append("/");
sb.append(path);
}
if (! queryParameters.isEmpty()) {
sb.append("?");
sb.append(getQueryParameters());
}
URL url = new URL(sb.toString());
return (HttpsURLConnection) url.openConnection();
}
private String getQueryParameters() throws UnsupportedEncodingException {
StringBuilder sb = new StringBuilder();
for (NameValuePair nameValuePair : queryParameters) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(nameValuePair.getName()).append("=").append(nameValuePair.getValue());
}
return sb.toString();
}
}
private class HttpResponseImpl<T> implements HttpResponse<T> {
private int responseCode;
private String responseMessage;
private T entity;
private HttpResponseImpl(HttpsURLConnection connection) throws IOException {
this.responseCode = connection.getResponseCode();
this.responseMessage = connection.getResponseMessage();
}
private HttpResponseImpl(Class<T> type, HttpsURLConnection connection) throws IOException, HttpException {
responseCode = connection.getResponseCode();
responseMessage = connection.getResponseMessage();
if (getResponseCode() < 400) {
entity = new ObjectMapper().readValue(readResponse(connection.getInputStream()), type);
} else {
throw new HttpException(readResponse(connection.getErrorStream()));
}
}
@Override
public int getResponseCode() {
return responseCode;
}
@Override
public String getResponseMessage() {
return responseMessage;
}
@Override
public T getEntity() {
return entity;
}
private String readResponse(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
String nextLine = null;
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
while ((nextLine = br.readLine()) != null) {
sb.append(nextLine);
}
return sb.toString();
}
}
}