com.xorcode.andtweet.net.ConnectionBasicAuth.java Source code

Java tutorial

Introduction

Here is the source code for com.xorcode.andtweet.net.ConnectionBasicAuth.java

Source

/* 
 * 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;
    }
}