Java tutorial
/* * 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("config/testing.json"); * Authenticator auth = new Authenticator(config); * String url = auth * .retrieveRequestToken("http://mysite.com/theyaredone?blah=blah"); * // bounce them to the URL * auth.retrieveAccessToken(""); * 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(); } }