/*
Swisscom Safe Connect
Copyright (C) 2014 Swisscom
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.swisscom.safeconnect.backend;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.swisscom.safeconnect.BuildConfig;
import com.swisscom.safeconnect.model.RawResponse;
import com.swisscom.safeconnect.utils.Config;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ClientConnectionManager;
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.SSLSocketFactory;
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.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.security.KeyStore;
public class PlumberTask extends AsyncTask<InternalCallback, Void, InternalCallback> {
private WeakReference<Context> context;
private int httpTimeout = 10000;
private static KeyStore keyStore;
private static SSLSocketFactory sslSocketFactory;
private static SchemeRegistry schemeRegistry;
private static final Object mKeystoreLock = new Object();
public PlumberTask(Context context) {
this.context = new WeakReference<Context>(context);
}
public PlumberTask() {
this.context = null;
}
/**
* Used to run the AsyncTasks in a ThreadPool. Otherwise all AsyncTasks will be exectued sequentially,
* this sometimes resulted in problems when a previous task did not finish (in time).
*
* @param taskCallback
*/
public void execute(InternalCallback taskCallback){
super.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, taskCallback);
}
@Override
protected InternalCallback doInBackground(InternalCallback... params) {
if (params.length > 0) {
HttpRequestBase request = params[0].getHttpRequest();
RawResponse response = doSyncRequest(request);
params[0].setResponse(response);
return params[0];
} else {
return null;
}
}
@Override
protected void onPostExecute(InternalCallback callbackResult) {
if (callbackResult != null) {
callbackResult.onRequestComplete();
}
}
private static String inputStreamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader rd = new BufferedReader(isr);
try {
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
} finally {
rd.close();
isr.close();
is.close();
}
return sb.toString();
}
public void setHttpTimeout(int ms){
httpTimeout = ms;
}
public static HttpClient getNewHttpClient(Context context, HttpParams params) {
InputStream is = null;
try {
synchronized (mKeystoreLock) {
if (keyStore == null) {
is = context.getAssets().open("swisscom.bks");
keyStore = KeyStore.getInstance("BKS");
keyStore.load(is, "sw1ssc0m".toCharArray());
}
if (sslSocketFactory == null) {
sslSocketFactory = new SwisscomSslSocketFactory(keyStore);
sslSocketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
}
if (schemeRegistry == null) {
schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
}
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "UTF-8");
}
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, schemeRegistry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
if (BuildConfig.DEBUG) Log.e(Config.TAG, "error", e);
return new DefaultHttpClient();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
if (BuildConfig.DEBUG) Log.e(Config.TAG, "error", e);
}
}
}
}
public RawResponse doSyncRequest(HttpRequestBase request) {
HttpParams httpParams = new BasicHttpParams();
if (httpTimeout > 0) {
HttpConnectionParams.setConnectionTimeout(httpParams, httpTimeout);
HttpConnectionParams.setSoTimeout(httpParams, httpTimeout);
}
HttpClient client = null;
if (context != null) {
Context ctx = context.get();
if (ctx != null) {
client = getNewHttpClient(ctx, httpParams);
}
}
if (client == null) {
client = new DefaultHttpClient();
}
RawResponse response = new RawResponse();
try {
HttpResponse httpResponse = client.execute(request);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (BuildConfig.DEBUG) Log.d(Config.TAG, "Request to " + request.getURI().toString() +
" --> " + httpResponse.getStatusLine());
// get the body
String json = inputStreamToString(httpResponse.getEntity().getContent());
response.status = statusCode;
response.body = json;
} catch (IOException e) {
if (BuildConfig.DEBUG) Log.e(Config.TAG, "Request to " + request.getURI().toString() +
" --> FAIL", e);
response.status = 0;
response.body = null;
}
return response;
}
}