package com.example.client; import android.util.Base64; import com.example.client.request.Request; import com.example.client.response.Response; import org.codehaus.jackson.JsonParseException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.ProtocolException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.UnknownHostException; import java.util.zip.GZIPInputStream; public class APICall { private Request mRequest = null; private APICallTask mAPICallTask = null; private Exception mException = null; private ResponseStatus mResponseStatus = new ResponseStatus(); private HttpURLConnection mConnection = null; //private HttpsURLConnection mConnection = null; // for SSL private OutputStream mRequestStream = null; private InputStream mResponseStream = null; public APICall(Request request) { mRequest = request; } public APICall(Request request, APICallTask task) { mRequest = request; mAPICallTask = task; } public Request getRequest() { return mRequest; } public Exception getException() { return mException; } public ResponseStatus getResponseStatus() { return mResponseStatus; } public void kill() { disconnect(); } public Response<?> execute() { try { // disables Keep-Alive for all connections if(mAPICallTask != null && mAPICallTask.isCancelled()) return null; System.setProperty("http.keepAlive", "false"); // new connection byte[] requestData = mRequest.getContent(); URL url = new URL(mRequest.getAddress()); mConnection = (HttpURLConnection) url.openConnection(); //mConnection = (HttpsURLConnection) url.openConnection(); // for SSL // ssl connection properties //SelfSignedSSLUtility.setupSSLConnection(mConnection, url); // for SSL using self signed certificate //CertificateAuthoritySSLUtility.setupSSLConnection(mConnection, url); // for SSL using certificate authority // connect setupConnection(requestData); mConnection.connect(); // send request if(mAPICallTask != null && mAPICallTask.isCancelled()) return null; sendRequest(requestData); // receive response if(mAPICallTask != null && mAPICallTask.isCancelled()) return null; mResponseStream = receiveResponse(); // response info //Logcat.d("connection.getURL() = " + mConnection.getURL()); //Logcat.d("connection.getContentType() = " + mConnection.getContentType()); //Logcat.d("connection.getContentEncoding() = " + mConnection.getContentEncoding()); //Logcat.d("connection.getResponseCode() = " + mConnection.getResponseCode()); //Logcat.d("connection.getResponseMessage() = " + mConnection.getResponseMessage()); // parse response if(mAPICallTask != null && mAPICallTask.isCancelled()) return null; Response<?> response = parseResponse(); if(mAPICallTask != null && mAPICallTask.isCancelled()) return null; return response; } catch(UnknownHostException e) { mException = e; e.printStackTrace(); return null; } catch(FileNotFoundException e) { mException = e; e.printStackTrace(); return null; } catch(SocketException e) { mException = e; e.printStackTrace(); return null; } catch(SocketTimeoutException e) { mException = e; e.printStackTrace(); return null; } catch(JsonParseException e) { mException = e; e.printStackTrace(); return null; } catch(IOException e) { mException = e; e.printStackTrace(); return null; } catch(Exception e) { mException = e; e.printStackTrace(); return null; } finally { disconnect(); } } private void disconnect() { try { if(mRequestStream != null) mRequestStream.close(); } catch(IOException e) {} try { if(mResponseStream != null) mResponseStream.close(); } catch(IOException e) {} try { // set status if(mConnection != null) { mResponseStatus.setStatusCode(mConnection.getResponseCode()); mResponseStatus.setStatusMessage(mConnection.getResponseMessage()); mConnection.disconnect(); } } catch(Throwable e) {} mRequestStream = null; mResponseStream = null; mConnection = null; } private void setupConnection(byte[] requestData) throws ProtocolException { if(mRequest.getRequestMethod() != null) { mConnection.setRequestMethod(mRequest.getRequestMethod()); // GET, POST, OPTIONS, HEAD, PUT, DELETE, TRACE } if(mRequest.getBasicAuthUsername() != null && mRequest.getBasicAuthPassword() != null) { mConnection.setRequestProperty("Authorization", getBasicAuthToken(mRequest.getBasicAuthUsername(), mRequest.getBasicAuthPassword())); } mConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //mConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + Request.BOUNDARY); // for multipart mConnection.setRequestProperty("Accept", "application/json"); mConnection.setRequestProperty("Accept-Encoding", "gzip"); mConnection.setRequestProperty("Accept-Charset", "UTF-8"); //mConnection.setRequestProperty("Content-Length", requestData == null ? "0" : String.valueOf(requestData.length)); //if(requestData!=null) mConnection.setChunkedStreamingMode(0); if(requestData != null) mConnection.setFixedLengthStreamingMode(requestData.length); mConnection.setConnectTimeout(30000); mConnection.setReadTimeout(30000); if(requestData != null) { // this call automatically sets request method to POST on Android 4 // if you don't want your app to POST, you must not call setDoOutput // http://webdiary.com/2011/12/14/ics-get-post/ mConnection.setDoOutput(true); } mConnection.setDoInput(true); mConnection.setUseCaches(false); } private void sendRequest(byte[] requestData) throws IOException { if(requestData != null) { mRequestStream = new BufferedOutputStream(mConnection.getOutputStream()); mRequestStream.write(requestData); mRequestStream.flush(); } } private InputStream receiveResponse() throws IOException { InputStream responseStream; String encoding = mConnection.getHeaderField("Content-Encoding"); boolean gzipped = encoding != null && encoding.toLowerCase().contains("gzip"); try { InputStream inputStream = mConnection.getInputStream(); if(gzipped) responseStream = new BufferedInputStream(new GZIPInputStream(inputStream)); else responseStream = new BufferedInputStream(inputStream); } catch(FileNotFoundException e) { // error stream InputStream errorStream = mConnection.getErrorStream(); if(gzipped) responseStream = new BufferedInputStream(new GZIPInputStream(errorStream)); else responseStream = new BufferedInputStream(errorStream); } return responseStream; } private Response<?> parseResponse() throws IOException { Response<?> response = mRequest.parseResponse(mResponseStream); if(response == null) throw new RuntimeException("Parser returned null response"); return response; } private String getBasicAuthToken(String username, String password) { // Base64.NO_WRAP because of Android <4 problem String base64 = Base64.encodeToString((username + ":" + password).getBytes(), Base64.NO_WRAP); return "Basic " + base64; } }