// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2012 MIT, All rights reserved // Released under the Apache License, Version 2.0 // http://www.apache.org/licenses/LICENSE-2.0 package com.google.appinventor.components.runtime.util; import android.util.Log; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.params.ConnManagerParams; 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.BasicResponseHandler; 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.protocol.HTTP; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; /** * These commands post to the Web and get responses that are assumed * to be JSON structures: a string, a JSON array, or a JSON object. * It's up to the caller of these routines to decide which version * to use, and to decode the response. * * @author halabelson@google.com (Hal Abelson) */ public class WebServiceUtil { private static final WebServiceUtil INSTANCE = new WebServiceUtil(); private static final String LOG_TAG = "WebServiceUtil"; private static HttpClient httpClient = null; private static Object httpClientSynchronizer = new Object(); private WebServiceUtil(){ } /** * Returns the one <code>WebServiceUtil</code> instance * @return the one <code>WebServiceUtil</code> instance */ public static WebServiceUtil getInstance() { // This needs to be here instead of in the constructor because // it uses classes that are in the AndroidSDK and thus would // cause Stub! errors when running the component descriptor. synchronized(httpClientSynchronizer) { if (httpClient == null) { SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); BasicHttpParams params = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(params, 20 * 1000); HttpConnectionParams.setSoTimeout(params, 20 * 1000); ConnManagerParams.setMaxTotalConnections(params, 20); ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, schemeRegistry); WebServiceUtil.httpClient = new DefaultHttpClient(manager, params); } } return INSTANCE; } /** * Make a post command to serviceURL with params and return the * response String as a JSON array. * * @param serviceURL The URL of the server to post to. * @param commandName The path to the command. * @param params A List of NameValuePairs to send as parameters * with the post. * @param callback A callback function that accepts a JSON array * on success. */ public void postCommandReturningArray(String serviceURL, String commandName, List<NameValuePair> params, final AsyncCallbackPair<JSONArray> callback) { AsyncCallbackPair<String> thisCallback = new AsyncCallbackPair<String>() { public void onSuccess(String httpResponseString) { try { callback.onSuccess(new JSONArray(httpResponseString)); } catch (JSONException e) { callback.onFailure(e.getMessage()); } } public void onFailure(String failureMessage) { callback.onFailure(failureMessage); } }; postCommand(serviceURL, commandName, params, thisCallback); } /** * Make a post command to serviceURL with paramaterss and * return the response String as a JSON object. * * @param serviceURL The URL of the server to post to. * @param commandName The path to the command. * @param params A List of NameValuePairs to send as parameters * with the post. * @param callback A callback function that accepts a JSON object * on success. */ public void postCommandReturningObject(final String serviceURL,final String commandName, List<NameValuePair> params, final AsyncCallbackPair<JSONObject> callback) { AsyncCallbackPair<String> thisCallback = new AsyncCallbackPair<String>() { public void onSuccess(String httpResponseString) { try { callback.onSuccess(new JSONObject(httpResponseString)); } catch (JSONException e) { callback.onFailure(e.getMessage()); } } public void onFailure(String failureMessage) { callback.onFailure(failureMessage); } }; postCommand(serviceURL, commandName, params, thisCallback); } /** * Make a post command to serviceURL with params and return the * response String. * * @param serviceURL The URL of the server to post to. * @param commandName The path to the command. * @param params A List of NameValuePairs to send as parameters * with the post. * @param callback A callback function that accepts a String on * success. */ public void postCommand(final String serviceURL, final String commandName, List<NameValuePair> params, AsyncCallbackPair<String> callback) { Log.d(LOG_TAG, "Posting " + commandName + " to " + serviceURL + " with arguments " + params); if (serviceURL == null || serviceURL.equals("")) { callback.onFailure("No service url to post command to."); } final HttpPost httpPost = new HttpPost(serviceURL + "/" + commandName); if (params == null) { params = new ArrayList<NameValuePair>(); } try { String httpResponseString; ResponseHandler<String> responseHandler = new BasicResponseHandler(); httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); httpPost.setHeader("Accept", "application/json"); httpResponseString = httpClient.execute(httpPost, responseHandler); callback.onSuccess(httpResponseString); } catch (UnsupportedEncodingException e) { Log.w(LOG_TAG, e); callback.onFailure("Failed to encode params for web service call."); } catch (ClientProtocolException e) { Log.w(LOG_TAG, e); callback.onFailure("Communication with the web service encountered a protocol exception."); } catch (IOException e) { Log.w(LOG_TAG, e); callback.onFailure("Communication with the web service timed out."); } } }