org.ryancutter.barcajolt.BarcaJolt.java Source code

Java tutorial

Introduction

Here is the source code for org.ryancutter.barcajolt.BarcaJolt.java

Source

package org.ryancutter.barcajolt;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

/**
 * Lightweight Java CouchDB library specifically built for interacting with
 * Cloudant databases on Android devices.<p>
 * 
 * http://github.com/ryancutter/BarcaJolt<p>
 * 
 * Copyright (C) 2011 by Ryan Cutter
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

public class BarcaJolt {
    private static final String TAG = "BarcaJolt";

    private String mHost; // username.cloudant.com
    private int mPort = 5984; // 5984 or 443 most likely
    private String mProtocol = "http"; // http or https
    private String mUsername;
    private String mPassword;

    /**
     * Constructor which assumes http connection. You should most likely use this.
     * 
     * @param host Database server host, e.g. 'username.cloudant.com'
     * @param username Username - strongly recommend generating API key rather than using master acct.
     * @param password Password - strongly recommend generating API key rather than using master acct
     */
    public BarcaJolt(String host, String username, String password) {
        mHost = host;
        mUsername = username;
        mPassword = password;
    }

    /**
     * Constructor which accepts all possible parameters
     * 
     * @param host Database server host, e.g. 'username.cloudant.com'
     * @param port Port, most likely 5984 or 443
     * @param protocol Protocol, "http" or "https"
     * @param username Username - strongly recommend generating API key rather than using master acct.
     * @param password Password - strongly recommend generating API key rather than using master acct
     */
    public BarcaJolt(String host, int port, String protocol, String username, String password) {
        mHost = host;
        mPort = port;
        mProtocol = protocol;
        mUsername = username;
        mPassword = password;
    }

    /**
     * GET details about account configuration
     * 
     * @return JSONObject Results of GET operation showing software version numbers
     */
    public JSONObject getAcctInfo() {
        return this.get("/");
    }

    /**
     * Find all databases user has access to. Username must have admin access to see this info.
     * 
     * @return JSONArray Results of GET operation showing array of database names. Returns null
     * for any HTTP status code other than 200.
     */
    public JSONArray getDBs() {
        JSONObject jObject = this.get("/_all_dbs", true);
        JSONArray jArray = null;

        // since Cloudant returns a JSONArray rather than JSONObject for /_all_dbs requests, this 
        // class temporarily wraps the array like {"dbs":["database1", "database2"]}
        if (jObject != null) {
            try {
                jArray = jObject.getJSONArray("dbs");
            } catch (JSONException e) {
                Log.e(TAG, "JSONException converting Object to Array", e);
            }
        } else {
            return null;
        }

        return jArray;
    }

    /**
     * Execute GET and collect response. This is the function users should call to run views.
     * 
     * @param getURL Requested GET operation. Will be appended to host. Will likely look like
     * "/databasename/_design/myapp/_view/all"
     * 
     * @return JSONObject Results of GET operation. Will retrun null for HTTP status codes other
     * than 200.
     */
    public JSONObject get(String getURL) {
        return get(getURL, false);
    }

    /**
     * Execute GET and collect response
     * 
     * @param getURL Requested GET operation. Will be appended to HOST.
     * 
     * @return JSONObject Results of GET operation. Will return null for HTTP status codes other
     * than 200.
     */
    private JSONObject get(String getURL, boolean arrayResult) {
        // set up DefaultHttpClient and other objects
        StringBuilder builder = new StringBuilder();
        DefaultHttpClient client = new DefaultHttpClient();

        HttpHost host = new HttpHost(mHost, mPort, mProtocol);
        HttpGet get = new HttpGet(getURL);

        client.getCredentialsProvider().setCredentials(new AuthScope(host.getHostName(), host.getPort()),
                new UsernamePasswordCredentials(mUsername, mPassword));

        JSONObject jObject = null;
        try {
            // execute GET and collect results if valid response
            HttpResponse response = client.execute(host, get);

            StatusLine status = response.getStatusLine();
            int statusCode = status.getStatusCode();
            if (statusCode == 200) {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
                for (String line = null; (line = reader.readLine()) != null;) {
                    builder.append(line);
                }

                try {
                    // check if this is the result of BarcaJolt.getDBs(). since Cloudant returns a JSONArray 
                    // rather than JSONObject for /_all_dbs requests, this class temporarily wraps the array
                    // like {"dbs":["database1", "database2"]}. unwrapped in BarcaJolt.getDBs()
                    if (arrayResult) {
                        builder.insert(0, "{'dbs' : ");
                        builder.append("}");
                    }

                    jObject = new JSONObject(builder.toString());
                } catch (JSONException e) {
                    Log.e(TAG, "JSONException converting StringBuilder to JSONObject", e);
                }
            } else {
                // we only want to process 200's
                // TODO process non-200's in a more clever way
                Log.e(TAG, "Bad HttoResponse status: " + new Integer(statusCode).toString());
                return null;
            }
        } catch (ClientProtocolException e) {
            Log.e(TAG, "ClientProtocolException", e);
        } catch (IOException e) {
            Log.e(TAG, "DefaultHttpClient IOException", e);
        }

        // let go of resources
        client.getConnectionManager().shutdown();

        return jObject;
    }

    /**
     * read "total_rows" from JSONObject returned by view request
     * 
     * @param jObject JSONObject returned by view request
     * 
     * @return int Value of "total_rows". Returns -1 if not found.
     */
    public static int getTotalRows(JSONObject jObject) {
        int totalRows = -1;

        try {
            totalRows = jObject.getInt("total_rows");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for 'total_rows'", e);
        }

        return totalRows;
    }

    /**
     * read "offset" from JSONObject returned by view request
     * 
     * @param jObject JSONObject returned by view request
     * 
     * @return int Value of "offset". Returns -1 if not found.
     */
    public static int getOffset(JSONObject jObject) {
        int offset = -1;

        try {
            offset = jObject.getInt("offset");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for 'offset'", e);
        }

        return offset;
    }

    /**
     * read "rows" array from JSONObject returned by view request
     * 
     * @param jObject JSONObject returned by view request
     * 
     * @return JSONArray Array stored in "rows". Returns null if not found.
     */
    public static JSONArray getRows(JSONObject jObject) {
        JSONArray rows = null;

        try {
            rows = jObject.getJSONArray("rows");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for 'rows'", e);
        }

        return rows;
    }

    /**
     * Extract "value" object from JSONArray
     * 
     * @param jArray Array of JSONObjects
     * @param index Index of array
     * 
     * @return JSONObject JSONObject in "value" at JArray[index]. Returns null if not found.
     */
    public static JSONObject getValueFromArray(JSONArray jArray, int index) {
        JSONObject value = null;

        try {
            value = jArray.getJSONObject(index).getJSONObject("value");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for value in array", e);
        }

        return value;
    }

    /**
     * Extract "key" from JSONArray
     * 
     * @param jArray Array of JSONObjects
     * @param index Index of array
     * 
     * @return String String in "key" at JArray[index]. Returns null if not found.
     */
    public static String getKeyFromArray(JSONArray jArray, int index) {
        String key = null;

        try {
            key = jArray.getJSONObject(index).getString("key");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for key in array", e);
        }

        return key;
    }

    /**
     * Extract "id" from JSONArray
     * 
     * @param jArray Array of JSONObjects
     * @param index Index of array
     * 
     * @return String String in "id" at JArray[index]. Returns null if not found.
     */
    public static String getIdFromArray(JSONArray jArray, int index) {
        String id = null;

        try {
            id = jArray.getJSONObject(index).getString("id");
        } catch (JSONException e) {
            Log.e(TAG, "JSONException while looking for id in array", e);
        }

        return id;
    }
}