com.pandoroid.pandora.RPC.java Source code

Java tutorial

Introduction

Here is the source code for com.pandoroid.pandora.RPC.java

Source

/* This file is part of Pandoroid
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.pandoroid.pandora;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Map;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * Description: This is the RPC client implementation for interfacing with 
 *    Pandora's servers. At the moment it uses Pandora's JSON API, but will
 *  hopefully be useful for whatever Pandora throws at us in the future.
 */
public class RPC {
    private HttpClient client;
    private String entity_type;
    private String request_url;
    private String user_agent;

    /**
     * Description: Our constructor class. This will set our default parameters
     *    for subsequent http requests, along with the MIME type for our entity
     *  (i.e. 'text/plain' for the current JSON protocol), and the partial URL 
     *  for the server (i.e. 'tuner.pandora.com/path/to/request/').
     */
    public RPC(String default_url, String default_entity_type, String default_user_agent) {
        client = new DefaultHttpClient();
        request_url = default_url;
        entity_type = default_entity_type;
        user_agent = default_user_agent;
    }

    /**
     * Description: This function contacts the remote server with a string
     *    type data package (could be JSON), and returns the remote server's 
     *    response in a string.
     * @throws Exception if url_params or entity_data is empty/null.
     * @throws HttpResponseException if response is not equal HttpStatus.SC_OK
     * @throws IOException if a connection to the remote server can't be made.
     */
    public String call(Map<String, String> url_params, String entity_data, boolean require_secure)
            throws Exception, HttpResponseException, IOException {

        if (url_params == null || url_params.size() == 0) {
            throw new Exception("Missing URL paramaters");
        }
        if (entity_data == null) {
            throw new Exception("Missing data for HTTP entity.");
        }

        String full_url;

        if (require_secure) {
            full_url = "https://" + request_url;
        } else {
            full_url = "http://" + request_url;
        }

        HttpPost request = new HttpPost();
        if (user_agent != null) {
            request.addHeader("User-Agent", user_agent);
        }

        URI uri = new URI(full_url.concat(makeUrlParamString(url_params)));
        request.setURI(uri);
        StringEntity entity = null;

        try {
            entity = new StringEntity(entity_data);
            if (entity_type != null) {
                entity.setContentType(entity_type);
            }
        } catch (Exception e) {
            throw new Exception("Pandora RPC Http entity creation error");
        }

        request.setEntity(entity);

        //Send to the server and get our response 
        HttpResponse response = client.execute(request);
        int status_code = response.getStatusLine().getStatusCode();
        if (status_code != HttpStatus.SC_OK) {
            throw new HttpResponseException(status_code,
                    "HTTP status code: " + status_code + " != " + HttpStatus.SC_OK);
        }

        //Read the response returned and turn it from a byte stream to a string.
        HttpEntity response_entity = response.getEntity();
        int BUFFER_BYTE_SIZE = 512;
        String ret_data = new String();
        byte[] bytes = new byte[BUFFER_BYTE_SIZE];

        //Check the entity type (usually 'text/plain'). Probably doesn't need
        //to be checked.
        if (response_entity.getContentType().getValue().equals(entity_type)) {
            InputStream content = response_entity.getContent();
            int bytes_read = BUFFER_BYTE_SIZE;

            //Rather than read an arbitrary amount of bytes, lets be sure to get
            //it all.
            while ((bytes_read = content.read(bytes, 0, BUFFER_BYTE_SIZE)) != -1) {
                ret_data += new String(bytes, 0, bytes_read);
            }
        } else {
            throw new Exception(
                    "Improper server response entity type: " + response_entity.getContentType().getValue());
        }

        return ret_data;
    }

    /**
     * Description: Here we create a URL method string with the parameters
     *    given. It automatically applies the '?' character to the beginning
     *  of strings, so multiple calls to this function will create an invalid 
     *  URL request string.
     */
    private String makeUrlParamString(Map<String, String> mapped_url_params) {
        String url_string = "?";
        boolean first_loop = true;
        for (Map.Entry<String, String> entry : mapped_url_params.entrySet()) {
            if (!first_loop) {
                url_string += "&";
            } else {
                first_loop = false;
            }
            url_string += URLEncoder.encode(entry.getKey()) + "=" + URLEncoder.encode(entry.getValue());
        }

        return url_string;
    }
}