Java tutorial
/* * Copyright (C) 2008 Torgny Bjers * * 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 com.xorcode.andtweet.net; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; 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 android.content.SharedPreferences; import android.util.Log; import com.xorcode.andtweet.util.Base64; /** * Handles connection to the Twitter REST API using Basic Authentication * * @author torgny.bjers */ public class ConnectionBasicAuth extends Connection { private static final String USER_AGENT = "AndTweet/1.0"; private static final String TAG = ConnectionBasicAuth.class.getSimpleName(); /** * Creates a new ConnectionBasicAuth instance. */ protected ConnectionBasicAuth(SharedPreferences sp) { super(sp); } @Override public JSONArray getFriendsTimeline(long sinceId, int limit) throws ConnectionException { setSinceId(sinceId); setLimit(limit); String url = STATUSES_FRIENDS_TIMELINE_URL; url += "?count=" + mLimit; if (mSinceId > 0) { url += "&since_id=" + mSinceId; } JSONArray jArr = null; String request = getRequest(url); try { jArr = new JSONArray(request); } catch (JSONException e) { try { JSONObject jObj = new JSONObject(request); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e1) { throw new ConnectionException(e); } } return jArr; } @Override public JSONArray getMentionsTimeline(long sinceId, int limit) throws ConnectionException { setSinceId(sinceId); setLimit(limit); String url = STATUSES_MENTIONS_TIMELINE_URL; url += "?count=" + mLimit; if (mSinceId > 0) { url += "&since_id=" + mSinceId; } JSONArray jArr = null; String request = getRequest(url); try { jArr = new JSONArray(request); } catch (JSONException e) { try { JSONObject jObj = new JSONObject(request); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e1) { throw new ConnectionException(e); } } return jArr; } @Override public JSONArray getDirectMessages(long sinceId, int limit) throws ConnectionException { setSinceId(sinceId); setLimit(limit); String url = DIRECT_MESSAGES_URL; url += "?count=" + mLimit; if (mSinceId > 0) { url += "&since_id=" + mSinceId; } JSONArray jArr = null; String request = getRequest(url); try { jArr = new JSONArray(request); } catch (JSONException e) { try { JSONObject jObj = new JSONObject(request); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e1) { throw new ConnectionException(e); } } return jArr; } @Override public JSONObject updateStatus(String message, long inReplyToId) throws ConnectionException { String url = STATUSES_UPDATE_URL; List<NameValuePair> formParams = new ArrayList<NameValuePair>(); formParams.add(new BasicNameValuePair("status", message)); // This parameter was removed from API: // formParams.add(new BasicNameValuePair("source", SOURCE_PARAMETER)); if (inReplyToId > 0) { formParams.add(new BasicNameValuePair("in_reply_to_status_id", String.valueOf(inReplyToId))); } JSONObject jObj = null; try { jObj = new JSONObject(postRequest(url, new UrlEncodedFormEntity(formParams, HTTP.UTF_8))); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (UnsupportedEncodingException e) { Log.e(TAG, e.toString()); } catch (JSONException e) { throw new ConnectionException(e); } return jObj; } @Override public JSONObject destroyStatus(long statusId) throws ConnectionException { StringBuilder url = new StringBuilder(STATUSES_DESTROY_URL); url.append(String.valueOf(statusId)); url.append(EXTENSION); JSONObject jObj = null; try { jObj = new JSONObject(postRequest(url.toString())); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e) { throw new ConnectionException(e); } return jObj; } @Override public JSONObject createFavorite(long statusId) throws ConnectionException { StringBuilder url = new StringBuilder(FAVORITES_CREATE_BASE_URL); url.append(String.valueOf(statusId)); url.append(EXTENSION); JSONObject jObj = null; try { jObj = new JSONObject(postRequest(url.toString())); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e) { throw new ConnectionException(e); } return jObj; } @Override public JSONObject destroyFavorite(long statusId) throws ConnectionException { StringBuilder url = new StringBuilder(FAVORITES_DESTROY_BASE_URL); url.append(String.valueOf(statusId)); url.append(EXTENSION); JSONObject jObj = null; try { jObj = new JSONObject(postRequest(url.toString())); String error = jObj.optString("error"); if ("Could not authenticate you.".equals(error)) { throw new ConnectionException(error); } } catch (JSONException e) { throw new ConnectionException(e); } return jObj; } @Override public boolean getCredentialsPresent(SharedPreferences sp) { boolean yes = false; if (mUsername != null && mPassword != null && mUsername.length() > 0 && mPassword.length() > 0) { yes = true; } return yes; } @Override public JSONObject verifyCredentials() throws ConnectionException { /** * Returns an HTTP 200 OK response code and a representation of the * requesting user if authentication was successful; returns a 401 * status code and an error message if not. * * @see <a * href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-account%C2%A0verify_credentials">Twitter * REST API Method: account verify_credentials</a> */ JSONObject jo = null; try { jo = new JSONObject( getRequest(ACCOUNT_VERIFY_CREDENTIALS_URL, new DefaultHttpClient(new BasicHttpParams()))); } catch (JSONException e) { Log.e(TAG, "verifyCredentials: " + e.toString()); } return jo; } @Override public JSONObject rateLimitStatus() throws ConnectionException { JSONObject jo = null; try { jo = new JSONObject( getRequest(ACCOUNT_RATE_LIMIT_STATUS_URL, new DefaultHttpClient(new BasicHttpParams()))); } catch (JSONException e) { e.printStackTrace(); } return jo; } @Override public void clearAuthInformation(SharedPreferences sp) { setPassword(sp, ""); } /** * Execute a GET request against the Twitter REST API. * * @param url * @return String * @throws ConnectionException */ private String getRequest(String url) throws ConnectionException { return getRequest(url, new DefaultHttpClient(new BasicHttpParams())); } /** * Execute a GET request against the Twitter REST API. * * @param url * @param client * @return String * @throws ConnectionException */ private String getRequest(String url, HttpClient client) throws ConnectionException { String result = null; int statusCode = 0; HttpGet getMethod = new HttpGet(url); try { getMethod.setHeader("User-Agent", USER_AGENT); getMethod.addHeader("Authorization", "Basic " + getCredentials()); client.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, DEFAULT_GET_REQUEST_TIMEOUT); client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT, DEFAULT_GET_REQUEST_TIMEOUT); HttpResponse httpResponse = client.execute(getMethod); statusCode = httpResponse.getStatusLine().getStatusCode(); result = retrieveInputStream(httpResponse.getEntity()); } catch (Exception e) { Log.e(TAG, "getRequest: " + e.toString()); throw new ConnectionException(e); } finally { getMethod.abort(); } parseStatusCode(statusCode, url); return result; } /** * Execute a POST request against the Twitter REST API. * * @param url * @return String * @throws ConnectionException */ private String postRequest(String url) throws ConnectionException { return postRequest(url, new DefaultHttpClient(new BasicHttpParams()), null); } /** * Execute a POST request against the Twitter REST API. * * @param url * @return String * @throws ConnectionException */ private String postRequest(String url, UrlEncodedFormEntity formParams) throws ConnectionException { return postRequest(url, new DefaultHttpClient(new BasicHttpParams()), formParams); } /** * Execute a POST request against the Twitter REST API. * * @param url * @param client * @return String * @throws ConnectionException */ private String postRequest(String url, HttpClient client, UrlEncodedFormEntity formParams) throws ConnectionException { String result = null; int statusCode = 0; HttpPost postMethod = new HttpPost(url); try { postMethod.setHeader("User-Agent", USER_AGENT); postMethod.addHeader("Authorization", "Basic " + getCredentials()); if (formParams != null) { postMethod.setEntity(formParams); } client.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, DEFAULT_POST_REQUEST_TIMEOUT); client.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT, DEFAULT_POST_REQUEST_TIMEOUT); HttpResponse httpResponse = client.execute(postMethod); statusCode = httpResponse.getStatusLine().getStatusCode(); result = retrieveInputStream(httpResponse.getEntity()); } catch (Exception e) { Log.e(TAG, "postRequest: " + e.toString()); throw new ConnectionException(e); } finally { postMethod.abort(); } parseStatusCode(statusCode, url); return result; } /** * Retrieve the input stream from the HTTP connection. * * @param httpEntity * @return String */ private String retrieveInputStream(HttpEntity httpEntity) { int length = (int) httpEntity.getContentLength(); StringBuffer stringBuffer = new StringBuffer(length); try { InputStreamReader inputStreamReader = new InputStreamReader(httpEntity.getContent(), HTTP.UTF_8); char buffer[] = new char[length]; int count; while ((count = inputStreamReader.read(buffer, 0, length - 1)) > 0) { stringBuffer.append(buffer, 0, count); } } catch (UnsupportedEncodingException e) { Log.e(TAG, e.toString()); } catch (IllegalStateException e) { Log.e(TAG, e.toString()); } catch (IOException e) { Log.e(TAG, e.toString()); } return stringBuffer.toString(); } /** * Get the HTTP digest authentication. Uses Base64 to encode credentials. * * @return String */ private String getCredentials() { return new String(Base64.encodeBytes((mUsername + ":" + mPassword).getBytes())); } /** * Parse the status code and throw appropriate exceptions when necessary. * * @param code * @param path * @throws ConnectionException */ private void parseStatusCode(int code, String path) throws ConnectionException { switch (code) { case 200: case 304: break; case 401: throw new ConnectionException(String.valueOf(code)); case 400: case 403: case 404: throw new ConnectionException(String.valueOf(code)); case 500: case 502: case 503: throw new ConnectionException(String.valueOf(code)); } } @Override public boolean isPasswordNeeded() { return true; } }