package pl.project13.janbanery.android.rest; import android.os.AsyncTask; import android.util.Log; import com.google.common.base.Charsets; import com.google.gson.Gson; import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.client.methods.*; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.AllowAllHostnameVerifier; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import pl.project13.janbanery.android.rest.response.ResponseFromHttpResponse; import pl.project13.janbanery.android.util.Strings; import pl.project13.janbanery.config.Configuration; import pl.project13.janbanery.config.auth.Header; import pl.project13.janbanery.core.rest.RestClient; import pl.project13.janbanery.core.rest.response.RestClientResponse; import pl.project13.janbanery.encoders.FormUrlEncodedBodyGenerator; import pl.project13.janbanery.exceptions.ServerCommunicationException; import pl.project13.janbanery.resources.KanbaneryResource; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * @author Konrad Malawski */ @SuppressWarnings("unchecked") public class AndroidCompatibleRestClient extends RestClient { public final String TAG = "AndroidRestClient"; private Configuration conf; private Gson gson; private DefaultHttpClient httpClient; private FormUrlEncodedBodyGenerator encodedBodyGenerator; private int callTimeoutSeconds = 30; public AndroidCompatibleRestClient() { this.httpClient = getClient(); } @Override public void init(Configuration configuration, Gson gson, FormUrlEncodedBodyGenerator bodyGenerator) { this.conf = configuration; this.gson = gson; this.encodedBodyGenerator = bodyGenerator; } public DefaultHttpClient getClient() { DefaultHttpClient ret; //sets up parameters HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, new ProtocolVersion("HTTP", 1, 1)); HttpProtocolParams.setContentCharset(params, "UTF-8"); params.setBooleanParameter("http.protocol.expect-continue", false); //registers schemes for both http and https SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory(); sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); registry.register(new Scheme("https", sslSocketFactory, 443)); ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry); ret = new DefaultHttpClient(manager, params); return ret; } private void authorize(HttpRequestBase request) { Header authHeader = conf.getAuthProvider().getAuthHeader(); request.addHeader(authHeader.getKey(), authHeader.getValue()); } @Override public RestClientResponse doPost(final String url, final KanbaneryResource resource) throws ServerCommunicationException { HttpPost request = new HttpPost(url); authorize(request); String requestBody = encodedBodyGenerator.asString(resource); Log.i(TAG, "Generated request body is: '" + requestBody + "'"); setFormUrlEncodedBody(request, requestBody); HttpResponse httpResponse = executeRequest(request); ResponseFromHttpResponse response = new ResponseFromHttpResponse(httpResponse); verifyResponseCode(response); return response; } @Override public <T> T doPost(String url, KanbaneryResource resource, Class<?> type) throws ServerCommunicationException { RestClientResponse response = doPost(url, resource); return (T) gson.fromJson(response.getResponseBody(), type); } @Override public RestClientResponse doGet(String url) throws ServerCommunicationException { HttpGet request = new HttpGet(url); authorize(request); HttpResponse httpResponse; httpResponse = executeRequest(request); ResponseFromHttpResponse response = new ResponseFromHttpResponse(httpResponse); verifyResponseCode(response); return response; } @Override public <T> T doGet(String url, Type type) throws ServerCommunicationException { RestClientResponse response = doGet(url); String responseBody = response.getResponseBody(); return (T) gson.fromJson(responseBody, type); } @Override public RestClientResponse doDelete(String url) throws ServerCommunicationException { HttpDelete request = new HttpDelete(url); authorize(request); HttpResponse httpResponse = executeRequest(request); ResponseFromHttpResponse response = new ResponseFromHttpResponse(httpResponse); verifyResponseCode(response); return response; } @Override public RestClientResponse doPut(String url, String requestBody) throws ServerCommunicationException { HttpPut request = new HttpPut(url); authorize(request); System.out.println(requestBody); Log.i(TAG, "Generated request body is: '" + requestBody + "'"); setFormUrlEncodedBody(request, requestBody); HttpResponse httpResponse = executeRequest(request); ResponseFromHttpResponse response = new ResponseFromHttpResponse(httpResponse); verifyResponseCode(response); return response; } @Override public <T> T doPut(String url, String requestBody, Class<?> type) throws ServerCommunicationException { RestClientResponse response = doPut(url, requestBody); return (T) gson.fromJson(response.getResponseBody(), type); } @Override public <T> T doPut(String url, String requestBody, Type type) throws ServerCommunicationException { RestClientResponse response = doPut(url, requestBody); return (T) gson.fromJson(response.getResponseBody(), type); } @Override public <T> T doPut(String url, KanbaneryResource resource, Class<?> type) throws ServerCommunicationException { RestClientResponse response = doPut(url, encodedBodyGenerator.asString(resource)); return (T) gson.fromJson(response.getResponseBody(), type); } private void setFormUrlEncodedBody(HttpEntityEnclosingRequestBase request, String requestBody) { BasicHttpEntity entity = new BasicHttpEntity(); try { byte[] contentBytes = requestBody.getBytes(Charsets.UTF_8.name()); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(contentBytes); System.out.println(">>>>>>>" + Strings.toString(byteArrayInputStream)); entity.setContent(new ByteArrayInputStream(contentBytes)); entity.setContentLength(contentBytes.length); entity.setContentEncoding(Charsets.UTF_8.name()); entity.setChunked(false); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unable to set request body.", e); } request.setEntity(entity); } private HttpResponse executeRequest(final HttpRequestBase request) { request.setHeader("Content-Type", "application/x-www-form-urlencoded"); HttpResponse httpResponse; try { httpResponse = new SimpleAsyncTask<HttpResponse>() { @Override protected HttpResponse execute() { HttpResponse response = null; try { response = httpClient.execute(request); } catch (Exception e) { throwLater(e); } return response; } }.get(callTimeoutSeconds); } catch (Exception e) { throw new ServerCommunicationException(e); } return httpResponse; } @Override public void close() { httpClient.clearRequestInterceptors(); httpClient.clearResponseInterceptors(); } public void setCallTimeoutSeconds(int callTimeoutSeconds) { this.callTimeoutSeconds = callTimeoutSeconds; } private abstract class SimpleAsyncTask<T> { private final String TAG = getClass().getSimpleName(); protected abstract T execute(); private Throwable throwLater; @SuppressWarnings("unchecked") public T get(int callTimeoutSeconds) { T result = null; try { result = new AsyncTask<Void, Void, T>() { @Override protected T doInBackground(Void... voids) { return SimpleAsyncTask.this.execute(); } @Override protected void onPostExecute(T t) { if (throwLater != null) { throw new RuntimeException("Exception was thrown while fetching resource.", throwLater); } } }.execute() .get(callTimeoutSeconds, TimeUnit.SECONDS); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException while SimpleAsyncTask get()...\n" + e.toString()); } catch (ExecutionException e) { Log.e(TAG, "ExecutionException while SimpleAsyncTask get()...\n" + e.toString()); } catch (TimeoutException e) { Log.e(TAG, "ExecutionException while SimpleAsyncTask get()...\n" + e.toString()); } return result; } protected void throwLater(Throwable throwable) { throwLater = throwable; } } }