package com.apigee.sdkexplorer;
import android.os.AsyncTask;
import com.apigee.sdk.apm.android.AppMonNet;
import com.apigee.sdk.apm.android.Log;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import javax.net.ssl.HttpsURLConnection;
public class HttpRequestTask extends AsyncTask<String, String, String> implements HttpURLConnectionTimeoutListener
{
private NetworkResponseListener listener;
private boolean responseIsSuccess;
private Exception exception;
private boolean useHttpURLConnection;
private int timeoutMillis;
private HttpClient httpClient;
private HttpURLConnection httpURLConnection;
private HttpsURLConnection httpsURLConnection;
private HttpGet httpGet;
private boolean connectionTimedOut;
private String url;
public HttpRequestTask(String connectionType, int timeoutMillis)
{
useHttpURLConnection = true;
if( connectionType != null ) {
if( connectionType.equalsIgnoreCase("HttpClient") ) {
useHttpURLConnection = false;
} else if( connectionType.equalsIgnoreCase("HttpURLConnection") ) {
useHttpURLConnection = true;
}
}
this.timeoutMillis = timeoutMillis;
connectionTimedOut = false;
httpURLConnection = null;
httpsURLConnection = null;
}
public void setNetworkResponseListener(NetworkResponseListener listener)
{
this.listener = listener;
}
public String callUsingHttpClient(String uri)
{
url = uri;
responseIsSuccess = false;
exception = null;
//DOCSNIPPET_START
// Ask the Apigee Mobile Analytics mobile agent for an http client
// (that has the instrumentation hooks in it) instead of creating
// a typical DefaultHttpClient instance
// typical code would do this:
//this.httpClient = new org.apache.http.impl.client.DefaultHttpClient();
// to get network performance metrics, do this instead:
this.httpClient = AppMonNet.getHttpClient();
//DOCSNIPPET_END
HttpResponse response;
String responseString = null;
try {
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = timeoutMillis;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = timeoutMillis;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpGet getOperation = new HttpGet(uri);
getOperation.setParams(httpParameters);
httpGet = getOperation;
response = httpClient.execute(getOperation);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
responseIsSuccess = true;
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else {
//Closes the connection.
HttpEntity entity = response.getEntity();
if( entity != null )
{
InputStream contentStream = entity.getContent();
if( contentStream != null )
{
contentStream.close();
}
}
throw new IOException(statusLine.getReasonPhrase());
}
} catch (java.net.SocketTimeoutException e) {
exception = e;
responseString = null;
}
catch (IOException e) {
exception = e;
responseString = null;
}
finally
{
this.httpClient = null;
}
return responseString;
}
@Override
public void notifyOnConnectionTimeout()
{
connectionTimedOut = true;
Log.d("DemoApp", "Connection timed out: " + url);
}
public String callUsingHttpURLConnection(String uri)
{
url = uri;
responseIsSuccess = false;
exception = null;
String responseString = null;
InputStream inputStream = null;
this.httpURLConnection = null;
this.httpsURLConnection = null;
try {
//DOCSNIPPET_START
//If using, HttpURLConnection, you would normally do this:
//java.net.URL url = new java.net.URL(uri);
// To have network performance metrics collected, do this instead:
com.apigee.sdk.apm.android.URLWrapper url = AppMonNet.urlForUri(uri);
//The InstaOpsURL class wraps an instance of java.net.URL. The
//InstaOpsURL does not extend java.net.URL because that class
//is a 'final' class (cannot be extended). If you need access
//to the real (wrapped) URL object, you can call the following
//method on InstaOpsURL:
// public java.net.URL getRealURL()
//DOCSNIPPET_END
URLConnection connection = url.openConnection();
if( connection != null ) {
if( connection instanceof HttpsURLConnection ) {
httpURLConnection = null;
httpsURLConnection = (HttpsURLConnection) connection;
httpsURLConnection.setRequestMethod("GET");
httpsURLConnection.setConnectTimeout(timeoutMillis);
httpsURLConnection.setReadTimeout(timeoutMillis);
} else if( connection instanceof HttpURLConnection ) {
httpsURLConnection = null;
httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(timeoutMillis);
httpURLConnection.setReadTimeout(timeoutMillis);
}
// one last check to see if someone's tried to cancel us
if( ! this.isCancelled() ) {
ConnectionTimeoutThread timeoutThread = null;
if( httpURLConnection != null ) {
timeoutThread = new ConnectionTimeoutThread(httpURLConnection,timeoutMillis,this);
} else if( httpsURLConnection != null ) {
timeoutThread = new ConnectionTimeoutThread(httpsURLConnection,timeoutMillis,this);
}
if( timeoutThread != null ) {
timeoutThread.start();
}
if( httpURLConnection != null ) {
httpURLConnection.connect();
} else {
httpsURLConnection.connect();
}
int responseCode;
if( httpURLConnection != null ) {
responseCode = httpURLConnection.getResponseCode();
} else {
responseCode = httpsURLConnection.getResponseCode();
}
if( responseCode == HttpStatus.SC_OK )
{
responseIsSuccess = true;
if( httpURLConnection != null ) {
inputStream = httpURLConnection.getInputStream();
} else {
inputStream = httpsURLConnection.getInputStream();
}
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
int bytesAvailable = inputStream.available();
if( bytesAvailable < 16 ) {
bytesAvailable = 16;
}
StringBuilder sb = new StringBuilder(bytesAvailable);
String line;
if( timeoutThread != null ) {
timeoutThread.cancel();
}
while ((line = reader.readLine()) != null)
{
sb.append(line + '\n');
}
responseString = sb.toString();
} else {
//Closes the connection.
if( connectionTimedOut ) {
responseString = "Connection timed out";
} else {
if( httpURLConnection != null ) {
throw new IOException(httpURLConnection.getResponseMessage());
} else {
throw new IOException(httpsURLConnection.getResponseMessage());
}
}
}
}
}
} catch (IOException e) {
if( connectionTimedOut ) {
responseString = "Connection timed out";
} else {
exception = e;
responseString = null;
}
}
finally
{
if( inputStream != null )
{
try {
inputStream.close();
}
catch (IOException ignored)
{
}
}
if( httpURLConnection != null )
{
httpURLConnection.disconnect();
} else {
httpsURLConnection.disconnect();
}
httpURLConnection = null;
httpsURLConnection = null;
}
return responseString;
}
@Override
protected String doInBackground(String... uri)
{
String uriToCall = uri[0];
// if we still have any connection lingering, try to get rid of it
if( (this.httpClient != null) && (httpGet != null) )
{
httpGet.abort();
httpGet = null;
this.httpClient = null;
}
if( this.httpURLConnection != null )
{
this.httpURLConnection.disconnect();
this.httpURLConnection = null;
}
String httpResponse = null;
if( useHttpURLConnection )
{
httpResponse = callUsingHttpURLConnection(uriToCall);
}
else
{
httpResponse = callUsingHttpClient(uriToCall);
}
return httpResponse;
}
@Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
if( (listener != null) && ! this.isCancelled() )
{
if( responseIsSuccess )
{
listener.notifyNetworkResponseSuccess(result);
}
else
{
listener.notifyNetworkResponseFailure(exception,result);
}
}
}
}