Java tutorial
/* * Copyright (C) 2013-2014 Tan Jung * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package illab.nabal.proxy; import illab.nabal.exception.AuthException; import illab.nabal.exception.NetworkException; import illab.nabal.exception.SystemException; import illab.nabal.proxy.AbstractProxy.SessionListener; import illab.nabal.settings.SnsProperties; import illab.nabal.settings.SocialNetwork; import illab.nabal.settings.SystemProperties; import illab.nabal.util.ParameterHelper; import illab.nabal.util.StorageHelper; import illab.nabal.util.StringHelper; import java.io.File; import java.io.InputStream; import java.net.URI; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.StatusLine; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpOptions; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpTrace; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.json.JSONObject; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.http.AndroidHttpClient; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Window; import android.webkit.WebViewClient; /** * Helper for network contexts / OAuth consumers. * * @version 1.0, 02/10/14 * @author <a href="mailto:tanito.jung@gmail.com">Tan Jung</a> */ abstract class AbstractContext { final static String TAG = "AbstractContext"; /** * Web view control for OAuth. * * @version 1.0, 02/10/14 * @author <a href="mailto:tanito.jung@gmail.com">Tan Jung</a> */ protected abstract class AbstractNetworkWebViewClient extends WebViewClient { /** * Color for web view title. */ private String mWebViewTitleColor; /** * Returns web view title color. * * @return String */ protected String getWebViewTitleColor() { return mWebViewTitleColor; } /** * Get SNS UID. * * @return SNS UID */ protected SocialNetwork getSnsUid() { return mSnsUid; } /** * Progress dialog for web view loading time. */ private ProgressDialog mSpinner; /** * Constructor to set up progress dialog. */ protected AbstractNetworkWebViewClient(String webViewTitleColor) { mWebViewTitleColor = webViewTitleColor; } /** * Show progress dialog. */ protected void showSpinner() { // instantiate ProgressDialog here, NOT in constructor // because the constructor will be called on non-UI thread if (mSpinner == null) { mSpinner = new ProgressDialog(mContext); mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE); mSpinner.setMessage(mSystemProperties.getLocalizedLodingMessage()); } // show spinner if (mSpinner != null && mSpinner.isShowing() == false) { mSpinner.show(); } } /** * Dismiss progress dialog. */ protected void dismissSpinner() { // dismiss spinner if (mSpinner != null && mSpinner.isShowing() == true) { mSpinner.dismiss(); } } /** * Cancel OAuth dialog. */ protected abstract void onCancel(); } /** * Constant for http. */ protected final static String HTTP = "http"; /** * Constant for https. */ protected final static String HTTPS = "https"; /** * Constant for scheme http. */ protected final static String SCHEME_HTTP = "http://"; /** * Constant for scheme https. */ protected final static String SCHEME_HTTPS = "https://"; /** * Constant for method GET. */ protected final static String GET = "GET"; /** * Constant for method POST. */ protected final static String POST = "POST"; /** * Constant for question mark. * */ protected final static String INTERROGATION_MARK = "?"; /** * Constant for ampersend delimeter. */ protected final static String AMPERSEND = "&"; /** * Constant for equal mark. */ protected final static String EQUAL_MARK = "="; /** * Constant for comma. */ protected final static String COMMA = ", "; /** * Constant for comma. */ protected final static String UNDERBAR = "_"; /** * Constant for string OAuth in camel case. */ protected final static String OAUTH_CAMEL_CASE = "OAuth"; /** * Constant for string HMAC-SHA1 in camel case. */ protected final static String HMAC_SHA1_CAMEL_CASE = "HmacSHA1"; /** * Constant for signature method. */ protected final static String HMAC_SHA1 = "HMAC-SHA1"; /** * Constant for UTF-8; */ protected final static String UTF_8 = "UTF-8"; /** * Constant for OAuth callback - out of band. */ protected final static String OUT_OF_BAND = "oob"; /** * Constant for Authorization. */ protected final static String AUTHORIZATION = "Authorization"; /** * Constant for accepted. */ protected final static String ACCEPTED = "accepted"; /** * Constant for denied. */ protected final static String DENIED = "denied"; /** * Constant for code. */ protected final static String CODE = "code"; /** * Constant for token. */ protected final static String TOKEN = "token"; /** * Constant for OAuth Consumer Key. */ protected final static String OAUTH_CONSUMER_KEY = "oauth_consumer_key"; /** * Constant for OAuth Consumer Secret. */ protected final static String OAUTH_CONSUMER_SECRET = "oauth_consumer_secret"; /** * Constant for OAuth signature method. */ protected final static String OAUTH_SIGNATURE_METHOD = "oauth_signature_method"; /** * Constant for OAuth signature. */ protected final static String OAUTH_SIGNATURE = "oauth_signature"; /** * Constant for OAuth timestamp. */ protected final static String OAUTH_TIMESTAMP = "oauth_timestamp"; /** * Constant for OAuth nonce. */ protected final static String OAUTH_NONCE = "oauth_nonce"; /** * Constant for OAuth version. */ protected final static String OAUTH_VERSION = "oauth_version"; /** * Constant for OAuth callback. */ protected final static String OAUTH_CALLBACK = "oauth_callback"; /** * Constant for OAuth callback confirmed. */ protected final static String OAUTH_CALLBACK_CONFIRMED = "oauth_callback_confirmed"; /** * Constant for OAuth verifier. */ protected final static String OAUTH_VERIFIER = "oauth_verifier"; /** * Constant for OAuth token. */ protected final static String OAUTH_TOKEN = "oauth_token"; /** * Constant for OAuth token secret. */ protected final static String OAUTH_TOKEN_SECRET = "oauth_token_secret"; /** * Constant for Client ID. */ protected final static String CLIENT_ID = "client_id"; /** * Constant for Client Secret. */ protected final static String CLIENT_SECRET = "client_secret"; /** * Constant for Redirect URI. */ protected final static String REDIRECT_URI = "redirect_uri"; /** * Constant for Resonse Type. */ protected final static String RESPONSE_TYPE = "response_type"; /** * Constant for error. */ protected final static String ERROR = "error"; /** * Constant for error description. */ protected final static String ERROR_DESCRIPTION = "error_description"; /** * Constant for Access Token. */ protected final static String ACCESS_TOKEN = "access_token"; /** * Constant for Access Token Expiry. */ protected final static String EXPIRES_IN = "expires_in"; /** * Constant for User ID. */ protected final static String USER_ID = "user_id"; /** * Constant for Oauth version - 1.0. */ protected final static String OAUTH_VESION_1_0 = "1.0"; /** * Constant for Oauth version - 2.0. */ protected final static String OAUTH_VESION_2_0 = "2.0"; /** * System properties. */ private SystemProperties mSystemProperties; /** * Social network properties. */ protected SnsProperties mSnsProperties; /** * SNS UID. */ private final SocialNetwork mSnsUid; /** * Op agent's alias to be used as prefix for session preservation * entries in shared preferences file. */ protected String mAlias = ""; /** * Android context. */ protected final Context mContext; /** * Android HTTP client. */ private AndroidHttpClient mHttpClient; /** * Handler for UI thread. * <p><b> * Note that his handler must be instantiated on UI thread. * Otherwise an error will occur when accessing UI components. * </b></p> */ protected final Handler mHandler = new Handler(); /** * Persistent storage. */ private final StorageHelper mStorageHelper; /** * Dialog for OAuth Web. */ protected Dialog mAuthWebDialog; /** * OAuth session listener. */ protected final SessionListener mSessionListener; /** * Flag indicating if OAuth session is under process. */ private boolean isFetchingSession = false; /** * Check if session is currently being fetched. * * @return boolean - if session is currently being fetched */ protected synchronized boolean isFetchingSession() { synchronized (mAccessToken) { return isFetchingSession; } } /** * Check if session is already established and ready to use. * * @return boolean - if session is already established */ protected boolean isSessionEstablished() { synchronized (mAccessToken) { return !StringHelper.isEmpty(mAccessToken); } } /** * Callback when session is established. */ protected void onSessionEstablished() { boolean isSessionStored = false; // store fetched session data try { isSessionStored = storeSession(); } // if failed to store session data catch (Exception e) { Log.e(TAG, e.getMessage()); Log.e(TAG, "failed to write session data to persistent storage"); } // if session data is successfully stored in persistent storage if (isSessionStored == true) { // notify the success mSessionListener.onSessionEstablished(); // set the flag off isFetchingSession = false; } // notify an error when failed to write to storage else { onSessionInvalid(new AuthException("Failed to write session data to persistent storage.")); } } /** * Callback when error occurrs while establishing session. * * @param e */ protected void onSessionInvalid(NetworkException e) { // notify the error mSessionListener.onSessionInvalid(e); // set the flag off since fetching session info has failed isFetchingSession = false; } /** * Fetch session key/access token. */ protected synchronized void fetchSession() { // set the flag on isFetchingSession = true; // try restoring session data from persistent storage boolean isSessionRestored = false; try { isSessionRestored = restoreSession(); } catch (Exception e) { Log.e(TAG, e.getMessage()); Log.e(TAG, "failed to restore session from storage"); } // if session data is successfully restored from persistent storage if (isSessionRestored == true) { // no need to start OAuth session onSessionEstablished(); } // if no session data restored, start a new OAuth session else { // create a new thread for HTTP connections (which is forbidden on UI thread) new Thread() { public void run() { try { // Request Token Secret and Access Token Secret should be empty // when fetching Request Token mRequestTokenSecret = ""; mAccessTokenSecret = ""; // fetch Request Token first getRequestToken(); // grant user authorization getUserAuthorization(); } catch (Exception e) { Log.e(TAG, e.getMessage()); // notify the error onSessionInvalid(new NetworkException(e.getMessage())); } } }.start(); } } /** * Display OAuth web dialog. * * @param networkWebViewClient * @param url */ protected void displayWebDialog(final String url, final AbstractNetworkWebViewClient networkWebViewClient) { // post web view thread to UI thread mHandler.post(new Runnable() { public void run() { // cookie must be deleted so that multiple sessions can be established StorageHelper.clearCookies(mContext); // bring a dialog to display authorization web page. mAuthWebDialog = new AuthWebDialog( // Android context mContext // URL to redirect to authoriaztion web page , url // client control for OAuth web view , networkWebViewClient // system properties , mSystemProperties); mAuthWebDialog.show(); } }); } /** * Remove session key/access token. * * @return if session is purged from both memory and storage successfully */ protected synchronized boolean purgeSession() { synchronized (mAccessToken) { boolean isSessionPurged = false; mAccessToken = ""; mAccessTokenSecret = ""; try { isSessionPurged = clearSharedPreferences(); } catch (Exception e) { Log.e(TAG, e.getMessage()); Log.e(TAG, "Error occurred while purging " + "session data stored in persistent storage"); } return isSessionPurged; } } /** * Fetch Request Token from Service Provider. * * @throws Exception */ protected abstract void getRequestToken() throws Exception; /** * Prompts user to provide authorization via OAuth web dialog. */ protected abstract void getUserAuthorization(); /** * Called when user authorizes app request on OAuth web dialog. * * @param bundle */ protected abstract void onAuthComplete(Bundle bundle); /** * Called when an error occured on OAuth web dialog. * * @param errMsg */ protected abstract void onAuthError(String errMsg); /** * Called if user canceled OAuth authorization. */ protected abstract void onAuthCancel(); /** * Fetch Access Token from Service Provider. * * @throws Exception */ protected abstract void getAccessToken(Bundle bundle) throws Exception; /** * Store session data to persistent storage. * <p><b> * Make sure you use {@link AbstractContext#commitPrefString(String, String)} * to store session data synchronously. * </b></p> * * @return true if successfully stored to persistent storage * @throws Exception */ protected abstract boolean storeSession() throws Exception; /** * Restore session data from persistent storage. * <p><b> * Make sure you use {@link AbstractContext#getPrefMap()} * to get a map from shared prefences file. * </b></p> * * @return true if successfully restored from persistent storage * @throws Exception */ protected abstract boolean restoreSession() throws Exception; /** * Cosumer Key provided by Service Provider. */ protected final String mConsumerKey; /** * Cosumer Secret provided by Service Provider to be used * as a part of HMAC-SHA1 secret key. */ protected final String mConsumerSecret; /** * Request Token fetched from Service Provider. */ protected String mRequestToken = ""; /** * Request Token Secret to be used as a part of HMAC-SHA1 secret key. */ protected String mRequestTokenSecret = ""; /** * OAuth Verifier fetched from Service Provider. */ protected String mOauthVerifier = ""; /** * Secret Key for HMAC-SHA1. */ protected String mSecretKey = ""; /** * Access Token fetched from Service Provider. */ protected String mAccessToken = ""; /** * Access Token Secret fetched from Service Provider. */ protected String mAccessTokenSecret = ""; /** * Get Access Token. * * @return access token */ protected String getAccessToken() { return mAccessToken; } /** * Get Access Token Secret. * * @return access token secret */ protected String getAccessTokenSecret() { return mAccessTokenSecret; } /** * Constructor for network context. * * @param context * @param sessionListener * @param systemProperties * @param snsProperties */ protected AbstractContext(Context context, SessionListener sessionListener, SystemProperties systemProperties, SnsProperties snsProperties) { mContext = context; mSessionListener = sessionListener; mSystemProperties = systemProperties; mSnsProperties = snsProperties; mSnsUid = SocialNetwork.getSnsUid(this.getClass().getSimpleName()); mConsumerKey = mSnsProperties.getConsumerKey(mSnsUid); mConsumerSecret = mSnsProperties.getConsumerSecret(mSnsUid); mStorageHelper = StorageHelper.newInstance(mContext); } /** * Constructor for network context. * * @param alias * @param context * @param sessionListener * @param systemProperties * @param snsProperties */ protected AbstractContext(String alias, Context context, SessionListener sessionListener, SystemProperties systemProperties, SnsProperties snsProperties) { mAlias = alias; mContext = context; mSessionListener = sessionListener; mSystemProperties = systemProperties; mSnsProperties = snsProperties; mSnsUid = SocialNetwork.getSnsUid(this.getClass().getSimpleName()); mConsumerKey = mSnsProperties.getConsumerKey(mSnsUid); mConsumerSecret = mSnsProperties.getConsumerSecret(mSnsUid); mStorageHelper = StorageHelper.newInstance(mContext); } /** * Returns a long timestamp value. * * @return current time in sec */ protected String getTimestamp() { return (System.currentTimeMillis() / 1000) + ""; } /** * Returns a long nonce value. * * @return a nonce value composed of 8 random digits */ protected String getLongNonce() { return ((long) Math.floor(Math.random() * 90000000L) + 10000000L) + ""; } /** * Returns a super unique nonce. * * @return UUID */ protected String getSuperNonce() { // well this seems a bit too much /* String nonce = UUID.nameUUIDFromBytes( new UUID( System.currentTimeMillis() , new Random( System.currentTimeMillis() ).nextLong() ).toString().getBytes() ).toString().replaceAll("-", ""); return nonce; */ // this will get the job done return UUID.randomUUID().toString().replaceAll("-", ""); } /** * Get HMAC-SHA1 secret key. * * @return secretKey */ protected String getSecretKey() { if (StringHelper.isEmpty(mAccessTokenSecret) == true) { mSecretKey = mConsumerSecret + AMPERSEND + StringHelper.nvl(mRequestTokenSecret); } else { mSecretKey = mConsumerSecret + AMPERSEND + mAccessTokenSecret; } return mSecretKey; } /* START OF [RESERVED] (2013-09-02) */ /* protected String getBaseString(String httpMethod, String baseUri, List<NameValuePair> sortedQueryParams) throws Exception { String baseString = null; if (StringHelper.isEmpty(httpMethod) == false && sortedQueryParams != null && sortedQueryParams.size() > 0) { // sort parameters using lexicographical byte value ordering sortedQueryParams = ParameterHelper.sortParams(sortedQueryParams); // compose a base string corresponding to method, host and URI path baseString = new StringHelper().appendAllToString( httpMethod , AMPERSEND , URLEncoder.encode(baseUri, UTF_8) , AMPERSEND , URLEncoder.encode( URLEncodedUtils.format(sortedQueryParams, UTF_8), UTF_8) ); } return baseString; } */ /* END OF [RESERVED] (2013-09-02) */ /** * Get base string for HMAC-SHA1 encoding. * * @param httpMethod * @param baseUri * @param queryParams * @return baseString - composed baseString by OAuth 1.0a specification * @throws Exception */ protected String getBaseString(String httpMethod, String baseUri, List<NameValuePair> queryParams) throws Exception { /* *################################################# * This algorithm(for OAuth 1.0a) is simply expressed in the pseudo-code : *################################################# * * httpMethod + "&" + * url_encode( base_uri ) + "&" + * sorted_query_params.each { | k, v | * url_encode ( k ) + "%3D" + * url_encode ( v ) * }.join("%26") * *################################################# */ String baseString = null; List<NameValuePair> sortedQueryParams = queryParams; if (StringHelper.isEmpty(httpMethod) == false && sortedQueryParams != null && sortedQueryParams.size() > 0) { // sort parameters using lexicographical byte value ordering sortedQueryParams = ParameterHelper.sortParams(sortedQueryParams); String paramQueryString = URLEncodedUtils.format(sortedQueryParams, UTF_8); //Log.d(TAG, "## BEFORE :: paramQueryString :\n" + paramQueryString); // replace '+' with '%20' to process POST parameter values with spaces paramQueryString = paramQueryString.replaceAll("\\+", "%20"); // TODO error still occurs even though asterisks are all URL-encoded (2014-01-06) /* * Unauthorized {"errors":[{"message":"Could not authenticate you","code":32}]} */ // replace '*' with '%2A' to process POST parameter values with asterisks paramQueryString = paramQueryString.replaceAll("\\*", "%2A"); //Log.d(TAG, "## AFTER :: paramQueryString :\n" + paramQueryString); // compose a base string corresponding to method, host and URI path baseString = new StringHelper().appendAllToString(httpMethod, AMPERSEND, URLEncoder.encode(baseUri, UTF_8), AMPERSEND, URLEncoder.encode(paramQueryString, UTF_8)); } return baseString; } /** * Get base string for HMAC-SHA1 encoding. * * @deprecated * @param request * @return signatureBaseString * @throws Exception */ protected String getSignatureBaseString(HttpUriRequest request) throws Exception { String signatureBaseString = ""; URI uri = request.getURI(); StringHelper strings = new StringHelper(); strings.appendAllAtOnce(request.getMethod(), AMPERSEND, URLEncoder.encode(uri.getPath(), UTF_8), AMPERSEND); List<NameValuePair> oauthParams = new ArrayList<NameValuePair>(); if (request instanceof HttpEntityEnclosingRequest) { HttpEntity entry = ((HttpEntityEnclosingRequest) request).getEntity(); if (entry instanceof UrlEncodedFormEntity) { List<NameValuePair> params = URLEncodedUtils.parse(entry); if (params != null) { oauthParams.addAll(params); } } } List<NameValuePair> params = URLEncodedUtils.parse(uri, UTF_8); if (params != null) { oauthParams.addAll(params); if (oauthParams.size() > 0) { StringHelper paramStrings = new StringHelper(); NameValuePair[] sortedParams = oauthParams.toArray(new NameValuePair[params.size()]); Arrays.sort(sortedParams, ParameterHelper.paramComparator); int paramCnt = 0; for (NameValuePair param : sortedParams) { if (paramCnt > 0) { paramStrings.append(AMPERSEND); } paramStrings.append(param.getName()); paramStrings.append(EQUAL_MARK); if (StringHelper.isEmpty(param.getName()) == false && OAUTH_CALLBACK.equals(param.getName())) { paramStrings.append(URLEncoder.encode(param.getValue(), UTF_8)); } else { paramStrings.append(StringHelper.nvl(param.getValue())); } paramCnt++; } strings.append(URLEncoder.encode(paramStrings.toString(), UTF_8)); paramStrings = null; sortedParams = null; params = null; oauthParams = null; } } signatureBaseString = strings.toString(); strings = null; return signatureBaseString; } /** * Extracts authorization header string from parameter list. * * @param params * @return headerString * @throws Exception */ protected String getOAuthHeaderString(List<NameValuePair> params) throws Exception { String headerString = null; if (params != null && params.size() > 0) { StringHelper stringHelper = new StringHelper().append(OAUTH_CAMEL_CASE + " "); int paramCount = 1; for (NameValuePair param : params) { if (StringHelper.isEmpty(param.getName()) == false) { if (paramCount > 1) { stringHelper.append(COMMA); } stringHelper.appendAllAtOnce(param.getName(), EQUAL_MARK, StringHelper.doubleQuote(URLEncoder.encode(StringHelper.nvl(param.getValue()), UTF_8))); paramCount++; } } headerString = stringHelper.toString(); stringHelper = null; } return headerString; } /** * Get a singleton object of AndroidHttpClient. * * @return AndroidHttpClient */ protected AndroidHttpClient getHttpClient() { if (mHttpClient == null) { mHttpClient = AndroidHttpClient.newInstance(SystemProperties.USER_AGENT_ANDROID, mContext); ClientConnectionManager conMgr = mHttpClient.getConnectionManager(); SchemeRegistry schReg = conMgr.getSchemeRegistry(); for (String scheme : schReg.getSchemeNames()) { Log.i(TAG, "Scheme: " + scheme + ", port: " + schReg.getScheme(scheme).getDefaultPort() + ", factory: " + schReg.getScheme(scheme).getSocketFactory().getClass().getName()); } } return mHttpClient; } /** * Close and nullify Android HTTP client object. */ protected void closeHttpClient() { if (mHttpClient != null) { if (mHttpClient.getConnectionManager() != null) { mHttpClient.getConnectionManager().shutdown(); } mHttpClient.close(); mHttpClient = null; } } /** * Returns API host URL. * * @return API host URL */ protected abstract String getApiHost(); /** * Get HTTP GET object. * * @param uri * @return HttpGet */ protected synchronized HttpGet getHttpGet(URI uri) { return new HttpGet(uri); } /** * Get HTTP GET object. * * @param apiUri * @return HttpGet * @throws Exception */ protected synchronized HttpGet getHttpGet(String apiUri) throws Exception { return new HttpGet(new URI(getApiHost() + apiUri)); } /** * Get HTTP GET object. * * @param apiUri * @param nvPairs * @return HttpGet * @throws Exception */ protected HttpGet getHttpGet(String apiUri, NameValuePair... nvPairs) throws Exception { List<NameValuePair> params = null; if (nvPairs != null && nvPairs.length > 0) { params = Arrays.asList(nvPairs); } return getHttpGet(apiUri, params); } /** * Get HTTP GET object. * * @param apiUri * @param params * @return HttpGet * @throws Exception */ protected synchronized HttpGet getHttpGet(String apiUri, List<NameValuePair> params) throws Exception { // URL-encode GET parameters String paramString = ""; if (params != null && params.size() > 0) { paramString = "?" + URLEncodedUtils.format(params, UTF_8); } return new HttpGet(new URI(getApiHost() + apiUri + paramString)); } /** * Get HTTP POST object. * * @param uri * @return HttpPost */ protected synchronized HttpPost getHttpPost(URI uri) { return new HttpPost(uri); } /** * Get HTTP POST object. * * @param apiUri * @return HttpPost * @throws Exception */ protected synchronized HttpPost getHttpPost(String apiUri) throws Exception { return new HttpPost(new URI(getApiHost() + apiUri)); } /** * Get HTTP POST object. * * @param apiUri * @param nvPairs * @return HttpPost * @throws Exception */ protected HttpPost getHttpPost(String apiUri, NameValuePair... nvPairs) throws Exception { List<NameValuePair> params = null; if (nvPairs != null && nvPairs.length > 0) { params = Arrays.asList(nvPairs); } return getHttpPost(apiUri, params); } /** * Get HTTP POST object. * * @param apiUri * @param params * @return HttpPost * @throws Exception */ protected synchronized HttpPost getHttpPost(String apiUri, List<NameValuePair> params) throws Exception { HttpPost httpPost = new HttpPost(new URI(getApiHost() + apiUri)); if (params != null && params.size() > 0) { httpPost.setEntity(new UrlEncodedFormEntity(params, UTF_8)); } return httpPost; } /** * Get multipart HTTP POST object. * * @param apiUri * @param params * @param paramNameForFile * @param absoultePathOfFile * @return HttpPost * @throws Exception */ protected HttpPost getMultipartHttpPost(String apiUri, List<NameValuePair> params, String paramNameForFile, String absoultePathOfFile) throws Exception { return getMultipartHttpPost(apiUri, params, paramNameForFile, new File(absoultePathOfFile)); } /** * Get multipart HTTP POST object. * * @param apiUri * @param params * @param paramNameForFile * @param file * @return HttpPost * @throws Exception */ protected HttpPost getMultipartHttpPost(String apiUri, List<NameValuePair> params, String paramNameForFile, File file) throws Exception { HttpPost httpPost = new HttpPost(new URI(getApiHost() + apiUri)); return getMultipartHttpPost(httpPost, params, paramNameForFile, file); } /** * Add multipart data to given HTTP POST object. * * @param httpPost * @param params * @param paramNameForFile * @param file * @return HttpPost * @throws Exception */ protected synchronized HttpPost getMultipartHttpPost(HttpPost httpPost, List<NameValuePair> params, String paramNameForFile, File file) throws Exception { MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); if (params != null && params.size() > 0) { for (NameValuePair nvPair : params) { entity.addPart(nvPair.getName(), new StringBody(StringHelper.nvl(nvPair.getValue()))); } } // check if given File is an actual file if (file == null || file.isFile() == false) { throw new Exception("File is invalid. check file path."); } else { entity.addPart(paramNameForFile, new FileBody(file)); } httpPost.setEntity(entity); return httpPost; } /** * Get HTTP PUT object. * * @param uri * @return HttpPut */ protected synchronized HttpPut getHttpPut(URI uri) { return new HttpPut(uri); } /** * Get HTTP PUT object. * * @param apiUri * @return HttpPut * @throws Exception */ protected synchronized HttpPut getHttpPut(String apiUri) throws Exception { return new HttpPut(new URI(getApiHost() + apiUri)); } /** * Get HTTP DELETE object. * * @param uri * @return HttpDelete */ protected synchronized HttpDelete getHttpDelete(URI uri) { return new HttpDelete(uri); } /** * Get HTTP DELETE object. * * @param apiUri * @return HttpDelete * @throws Exception */ protected synchronized HttpDelete getHttpDelete(String apiUri) throws Exception { return new HttpDelete(new URI(getApiHost() + apiUri)); } /** * Get HTTP HEAD object. * * @param uri * @return HttpHead */ protected synchronized HttpHead getHttpHead(URI uri) { return new HttpHead(uri); } /** * Get HTTP HEAD object. * * @param apiUri * @return HttpHead * @throws Exception */ protected synchronized HttpHead getHttpHead(String apiUri) throws Exception { return new HttpHead(new URI(getApiHost() + apiUri)); } /** * Get HTTP OPTIONS object. * * @param uri * @return HttpOptions */ protected synchronized HttpOptions getHttpOptions(URI uri) { return new HttpOptions(uri); } /** * Get HTTP OPTIONS object. * * @param apiUri * @return HttpOptions * @throws Exception */ protected synchronized HttpOptions getHttpOptions(String apiUri) throws Exception { return new HttpOptions(new URI(getApiHost() + apiUri)); } /** * Get HTTP TRACE object. * * @param uri * @return HttpTrace */ protected synchronized HttpTrace getHttpTrace(URI uri) { return new HttpTrace(uri); } /** * Get HTTP TRACE object. * * @param apiUri * @return HttpTrace * @throws Exception */ protected synchronized HttpTrace getHttpTrace(String apiUri) throws Exception { return new HttpTrace(new URI(getApiHost() + apiUri)); } /** * Execute a request and retrieve a response as a JSON object. * * @param request * @return JSONObject * @throws Exception */ protected JSONObject getResponseJson(HttpUriRequest request) throws Exception { return new JSONObject(getResponseString(request, false)); } /** * Execute a request and retrieve a response as a string value. * * @param request * @return responseString * @throws Exception */ protected String getResponseString(HttpUriRequest request) throws Exception { return getResponseString(request, true); } /** * Execute a request and retrieve a response as a string value. * * @param request * @param isEmptyAllowed * @return responseString * @throws Exception */ protected synchronized String getResponseString(HttpUriRequest request, boolean isEmptyAllowed) throws Exception { String responseString = null; if (request != null) { AndroidHttpClient client = AndroidHttpClient.newInstance(SystemProperties.USER_AGENT_ANDROID, mContext); try { HttpResponse response = client.execute(request); HttpEntity entity = response.getEntity(); if (entity != null) { StringHelper strings = new StringHelper(); InputStream instream = entity.getContent(); int len; byte[] tmp = new byte[2048]; while ((len = instream.read(tmp)) != -1) { strings.append(new String(tmp, 0, len, UTF_8)); } responseString = strings.toString().trim(); Log.v(TAG, " ## HTTP response for " + request.getURI() + " : \n" + responseString); strings = null; entity.consumeContent(); } else { Log.w(TAG, "entity IS NULL"); } StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode > HttpStatus.SC_MULTIPLE_CHOICES) { Log.e(TAG, "HTTP status : " + statusCode + " - " + statusLine.getReasonPhrase()); JSONObject responseJson = null; try { responseJson = new JSONObject(responseString); } catch (Exception e) { // DO NOTHING } // if response came in JSON format if (responseJson != null) { Log.e(TAG, "responseJson.toString() : " + responseJson.toString()); NetworkException ne = new NetworkException(statusCode, statusLine.getReasonPhrase(), responseJson.toString()); ne.setResponseJson(responseJson); throw ne; } // if response didn't came in JSON format else { Log.e(TAG, "responseString : " + responseString); NetworkException ne = new NetworkException(statusCode, statusLine.getReasonPhrase(), responseString); ne.setResponseString(responseString); throw ne; } } } catch (Exception e) { request.abort(); Log.e(TAG, e.getMessage()); throw e; } finally { if (client != null) { client.close(); } } } // throw an exception if empty reponse is not allowed if (isEmptyAllowed == false && StringHelper.isEmpty(responseString) == true) { Log.e(TAG, "HTTP response is empty"); throw new NetworkException("HTTP response is empty."); } return responseString; } /* START OF [RESERVED] (2013-01-21) */ /* protected synchronized String getResponseString( HttpUriRequest request) throws Exception { String responseString = ""; if (request != null) { HttpResponse response = new DefaultHttpClient().execute(request); HttpEntity entity = response.getEntity(); if (entity != null) { StringHelper strings = new StringHelper(); InputStream instream = entity.getContent(); int len; byte[] tmp = new byte[2048]; while ((len = instream.read(tmp)) != -1) { strings.append(new String(tmp, 0, len, UTF_8)); } responseString = strings.toString().trim(); strings = null; } StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode > HttpStatus.SC_MULTIPLE_CHOICES) { Log.e(TAG, "HTTP status code : " + statusCode + " - " + statusLine.getReasonPhrase()); throw new NetworkException(statusCode, statusLine.getReasonPhrase(), responseString); } } return responseString; } */ /* END OF [RESERVED] (2013-01-21) */ /** * Download a bitmap from a given URL. * * @param photoUrl * @return Bitmap * @throws Exception */ protected synchronized Bitmap getResponseBitmap(String photoUrl) throws Exception { Bitmap bitmap = null; if (StringHelper.isEmpty(photoUrl) == false) { AndroidHttpClient client = AndroidHttpClient.newInstance(SystemProperties.USER_AGENT_ANDROID, mContext); HttpGet request = new HttpGet(photoUrl); try { HttpResponse response = client.execute(request); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode > HttpStatus.SC_MULTIPLE_CHOICES) { Log.e(TAG, "HTTP status code : " + statusCode + " - " + statusLine.getReasonPhrase()); throw new NetworkException(statusCode, statusLine.getReasonPhrase(), "Failed to fetch BitMap from URL - " + photoUrl); } HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (Exception e) { request.abort(); throw new NetworkException("Error occurred while retrieving bitmap from " + photoUrl, e.toString(), e); } finally { if (client != null) { client.close(); } } } // if given url is empty else { throw new SystemException("Photo URL is invalid."); } return bitmap; } /** * Get system shared preferences and store deciphered keys and values in Map object. * * @return Map<String, String> * @throws Exception */ protected Map<String, String> getPrefMap() throws Exception { return mStorageHelper.getPrefMap(mAlias, mSnsUid); } /** * Read and decipher a string value from shared preferences file. * * @param key * @return String * @throws Exception */ protected String getPrefString(String key) throws Exception { return mStorageHelper.getPrefString(mAlias, mSnsUid, key); } /** * Write a ciphered string value to shared preferences file. * Note that actual data will be written to storage ASYNCHRNOUSLY. * * @param key * @param value * @throws Exception */ protected void applyPrefString(String key, String value) throws Exception { mStorageHelper.applyPrefString(mAlias, mSnsUid, key, value); } /** * Write a ciphered string value to shared preferences file. * Note that actual data will be written to storage IMMEDIATELY. * * @param key * @param value * @return true if written successfully * @throws Exception */ protected boolean commitPrefString(String key, String value) throws Exception { return mStorageHelper.commitPrefString(mAlias, mSnsUid, key, value); } /** * Clear all values from shared preferences. * * @return if session is purged from storage successfully * @throws Exception */ private boolean clearSharedPreferences() throws Exception { return mStorageHelper.clearSharedPreferences(mAlias, mSnsUid); } }