com.dropbox.client.DropboxClient.java Source code

Java tutorial

Introduction

Here is the source code for com.dropbox.client.DropboxClient.java

Source

/*
 * Copyright (c) 2009 Evenflow, Inc.
 * 
 * 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.
 */

package com.dropbox.client;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;

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.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.InputStreamBody;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

/**
 * The DropboxClient is the core of the Java API, and is designed to be both
 * instructive and easy to use. If you find yourself needing to do more than
 * what's provided, use the code here as a guide to implement your own
 * alternatives.
 * 
 * Before you can work with DropboxClient you'll need to configure an
 * Authenticator with a working OAuth access token. Typically this is done like
 * this:
 * 
 * <pre>
 * Map config = Authenticator.loadConfig(&quot;config/testing.json&quot;);
 * Authenticator auth = new Authenticator(config);
 * String url = auth
 *       .retrieveRequestToken(&quot;http://mysite.com/theyaredone?blah=blah&quot;);
 * // bounce them to the URL
 * auth.retrieveAccessToken(&quot;&quot;);
 * String access_key = auth.getTokenKey();
 * String access_secret = auth.getTokenSecret();
 * // store those so that you can put them in config and not have to do the above again
 * </pre>
 * 
 * Once you've done the above, or configured a config Map with
 * "access_token_key" and "access_token_secret" parameters, then you can create
 * a DropboxClient object to work with:
 * 
 * <pre>
 * DropboxClient client = new DropboxClient(config, auth);
 * </pre>
 * 
 * And that should be it. For every operation you need to catch the
 * DropboxException, but that's the only additional complexity.
 */
public class DropboxClient extends RESTUtility {

    private CommonsHttpOAuthConsumer consumer = null;
    public String api_host = "api.getdropbox.com"; // server
    public String content_host = "api-content.getdropbox.com"; // content server
    public int port = 80;

    /**
     * This is set by Dropbox to indicate what version of the API you are using.
     */
    final static public int API_VERSION = 0;

    /**
     * Config needs to have settings for "server", "content_server", and "port"
     * (which should be a Long), and auth should be ready to work with an access
     * key.
     */
    public DropboxClient(CommonsHttpOAuthConsumer consumer) {
        this.consumer = consumer;
    }

    /**
     * The account/info API call to Dropbox for getting info about an account
     * attached to the access token.
     */
    public JSONObject accountInfo(boolean status_in_response, String callback) throws DropboxException {
        Object[] params = { "status_in_response", "" + status_in_response, "callback", callback };

        return request("GET", defaultProtocol, api_host, port, "/account/info", API_VERSION, params, consumer);
    }

    /**
     * Copy a file from one path to another, with root being either "sandbox" or
     * "dropbox".
     */
    public JSONObject fileCopy(String root, String from_path, String to_path, String callback)
            throws DropboxException {
        Object[] params = { "root", root, "from_path", from_path, "to_path", to_path, "callback", callback };
        return request("POST", defaultProtocol, api_host, port, "/fileops/copy", API_VERSION, params, consumer);
    }

    /** Create a folder at the given path. */
    public JSONObject fileCreateFolder(String root, String path, String callback) throws DropboxException {
        Object[] params = { "root", root, "path", path, "callback", callback };

        return request("POST", defaultProtocol, api_host, port, "/fileops/create_folder", API_VERSION, params,
                consumer);
    }

    /** Delete a file. */
    public JSONObject fileDelete(String root, String path, String callback) throws DropboxException {
        Object[] params = { "root", root, "path", path, "callback", callback };
        return request("POST", defaultProtocol, api_host, port, "/fileops/delete", API_VERSION, params, consumer);
    }

    /** Move a file. */
    public JSONObject fileMove(String root, String from_path, String to_path, String callback)
            throws DropboxException {
        Object[] params = { "root", root, "from_path", from_path, "to_path", to_path, "callback", callback };
        return request("POST", defaultProtocol, api_host, port, "/fileops/move", API_VERSION, params, consumer);
    }

    /**
     * Get a file from the content server, returning the raw Apache HTTP
     * Components response object so you can stream it or work with it how you
     * need. You *must* call .getEntity().consumeContent() on the returned
     * HttpResponse object or you might leak connections.
     */
    public HttpResponse getFile(String root, String from_path) throws DropboxException {
        return getFileWithVersion(root, from_path, null);
    }

    /**
     * Get a file from the content server, returning the raw Apache HTTP
     * Components response object so you can stream it or work with it how you
     * need. You *must* call .getEntity().consumeContent() on the returned
     * HttpResponse object or you might leak connections.
     */
    public HttpResponse getFileWithVersion(String root, String from_path, String etag) throws DropboxException {
        String path = "/files/" + root + from_path;
        HttpClient client = getClient();

        try {
            String target = buildFullURL(secureProtocol, content_host, port, buildURL(path, API_VERSION, null));
            HttpGet req = new HttpGet(target);
            if (etag != null) {
                req.addHeader("If-None-Match", etag);
            }
            consumer.sign(req);
            return client.execute(req);
        } catch (Exception e) {
            throw new DropboxException(e);
        }
    }

    /**
     * Does not actually talk to Dropbox, but instead crafts a properly
     * formatted URL that you can put into your UI which will link a user to
     * that file in their own account. They will need to login to their Dropbox
     * account on the website to access the file.
     */
    public String links(String root, String path) throws DropboxException {
        String url_path = "/links/" + root + path;

        return buildFullURL(defaultProtocol, api_host, port, buildURL(url_path, API_VERSION, null));
    }

    /**
     * Get metadata about directories and files, such as file listings and such.
     */
    public JSONObject metadata(String root, String path, int file_limit, String hash, boolean list,
            boolean status_in_response, String callback) throws DropboxException {
        Object[] params = { "file_limit", "" + file_limit, "hash", hash, "list", "" + list, "status_in_response",
                "" + status_in_response, "callback", callback };

        String url_path = "/files/" + root + path;

        return request("GET", defaultProtocol, api_host, port, url_path, API_VERSION, params, consumer);
    }

    public JSONObject eventMetadata(String root, JSONObject target_events) throws DropboxException {
        String jsonText = target_events.toString();

        Object[] params = { "root", root, "target_events", jsonText, };

        return request("POST", defaultProtocol, api_host, port, "/event_metadata", API_VERSION, params, consumer);
    }

    /**
     * You *must* call .getEntity().consumeContent() on the returned
     * HttpResponse object or you might leak connections.
     */
    public HttpResponse eventContent(String root, int user_id, int namespace_id, int journal_id)
            throws DropboxException {
        String path = "/event_content";
        HttpClient client = getClient();
        Object[] params = { "root", root, "target_event", "" + user_id + ":" + namespace_id + ":" + journal_id };

        try {
            String target = buildFullURL(defaultProtocol, content_host, this.port,
                    buildURL(path, API_VERSION, params));
            HttpGet req = new HttpGet(target);
            consumer.sign(req);
            return client.execute(req);
        } catch (Exception e) {
            throw new DropboxException(e);
        }
    }

    // public boolean eventContentAvailable(Map md) {
    // return md.get("error") == null &&
    // ((Boolean)md.get("latest")).booleanValue() == true &&
    // ((Integer)md.get("size")).intValue() != -1 &&
    // ((Boolean)md.get("is_dir")).booleanValue() == false;
    // }

    /**
     * Put a file in the user's Dropbox.
     */
    public HttpResponse putFile(String root, String to_path, File file_obj) throws DropboxException {
        String path = "/files/" + root + to_path;

        HttpClient client = getClient();

        try {
            String target = buildFullURL(secureProtocol, content_host, this.port,
                    buildURL(path, API_VERSION, null));
            HttpPost req = new HttpPost(target);
            // this has to be done this way because of how oauth signs params
            // first we add a "fake" param of file=path of *uploaded* file
            // THEN we sign that.
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("file", file_obj.getName()));
            req.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            consumer.sign(req);

            // now we can add the real file multipart and we're good
            MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
            FileBody bin = new FileBody(file_obj);
            entity.addPart("file", bin);
            // this resets it to the new entity with the real file
            req.setEntity(entity);

            HttpResponse resp = client.execute(req);

            resp.getEntity().consumeContent();
            return resp;
        } catch (Exception e) {
            throw new DropboxException(e);
        }
    }

    /**
     * Put a file in the user's Dropbox.
     */
    public HttpResponse putFileStream(String root, String to_path, String name, InputStream stream, long length)
            throws DropboxException {
        String path = "/files/" + root + to_path;

        HttpClient client = getClient();

        try {
            String target = buildFullURL(secureProtocol, content_host, this.port,
                    buildURL(path, API_VERSION, null));
            HttpPost req = new HttpPost(target);
            // this has to be done this way because of how oauth signs params
            // first we add a "fake" param of file=path of *uploaded* file
            // THEN we sign that.
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("file", name));
            req.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            consumer.sign(req);

            // now we can add the real file multipart and we're good
            MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
            FileStreamBody bin = new FileStreamBody(stream, name, length);
            entity.addPart("file", bin);
            // this resets it to the new entity with the real file
            req.setEntity(entity);

            HttpResponse resp = client.execute(req);

            resp.getEntity().consumeContent();
            return resp;
        } catch (Exception e) {
            throw new DropboxException(e);
        }
    }

    class FileStreamBody extends InputStreamBody {

        private long length;

        public FileStreamBody(InputStream in, String filename, long length) {
            super(in, filename);
            this.length = length;
        }

        @Override
        public long getContentLength() {
            return length;
        }
    }

    public String getAccessToken() {
        return consumer.getToken();
    }

    public String getAccessTokenSecret() {
        return consumer.getTokenSecret();
    }

}