From f129239d8eeae6ac6e4041cb36863ae701984405 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sun, 16 Oct 2011 17:22:27 +0200 Subject: [PATCH 01/13] Updated README to reflect the latest changes. --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 10725ba..3a9150e 100644 --- a/README.md +++ b/README.md @@ -8,19 +8,19 @@ Usage Example CloudApi api = new CloudApiImpl("Your email here", "Your password here"); // Add a new bookmark - JSONObject json = api.createBookmark('Simon Gaeremynck's portfolio', 'gaeremynck.com'); + CloudAppItem bookmark = api.createBookmark('Simon Gaeremynck's portfolio', 'gaeremynck.com'); // Add file - JSONObject json = api.uploadFile(new File("/path/to/file")); + CloudAppItem file = api.uploadFile(new File("/path/to/file")); // Get the first 10 items, regardless of category who aren't in the trash. - JSONArray array = api.getItems(1, 10, null, false); + List = api.getItems(1, 10, null, false); - // Get a specific item (http://cl.ly/bD5) - JSONObject json = api.getItem('bD5'); + // Get a specific item (http://cl.ly/2wr4) + CloudAppItem item = api.getItem('http://cl.ly/2wr4'); - // Delete item (by 'href' value) - api.deleteItem("http://my.cl.ly/items/1058986"); + // Delete an item + api.delete(item); Requirements @@ -36,7 +36,11 @@ A jar can be compiled trough maven by running the following command. However, this will skip the unit tests. If you want to have the unit tests, you will need to fill -in your email and password in the CloudApiTestCase.java file. +in your email and password in src/test/resources/credentials.properties like so: +cred_mail=me@email.com +cred_password=mypassword + +Running a build can be done like so: `mvn clean install` From d319bb1173a1a7fbcceb6c03e06701db58759470 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sun, 16 Oct 2011 21:04:16 +0200 Subject: [PATCH 02/13] Fixed formatting issues in README. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a9150e..3d9c29e 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,8 @@ Usage Example Requirements ------------ -Java -Maven (only for building) +* Java +* Maven (only for building) Building @@ -37,8 +37,8 @@ A jar can be compiled trough maven by running the following command. However, this will skip the unit tests. If you want to have the unit tests, you will need to fill in your email and password in src/test/resources/credentials.properties like so: -cred_mail=me@email.com -cred_password=mypassword + cred_mail=me@email.com + cred_password=mypassword Running a build can be done like so: `mvn clean install` From ce1cf8bf80b2ff7683a41c4a6a0b6b0ed2679ea3 Mon Sep 17 00:00:00 2001 From: Arnaud Frugier Date: Sat, 28 Jan 2012 19:55:59 +0000 Subject: [PATCH 03/13] Bugs corrected + Suggestions Bugs : - "uploaded_at" parameters does not exist. I replaced it with "updated_at" - The date format was not correct. Bug remaining : - The get method for getItems with "HttpParams params = new BasicHttpParams();" does not work. Here is my solution : http://cl.ly/1i1a0y040w3y0Q3V0i0x Suggestion : - There is a new parameter called "thumbnail_url" (getItems). You should implement it --- src/main/java/com/cloudapp/api/model/CloudAppItem.java | 2 +- src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java | 4 ++-- src/main/java/com/cloudapp/impl/model/CloudAppModel.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/cloudapp/api/model/CloudAppItem.java b/src/main/java/com/cloudapp/api/model/CloudAppItem.java index fe64d27..cf63e58 100644 --- a/src/main/java/com/cloudapp/api/model/CloudAppItem.java +++ b/src/main/java/com/cloudapp/api/model/CloudAppItem.java @@ -104,7 +104,7 @@ enum Type { * @return When this item was last updated. (or null if it has not been) * @throws CloudAppExtion */ - Date getUploadedAt() throws CloudAppException; + Date getUpdatedAt() throws CloudAppException; /** * @return When this item was deleted. (or null if it has not been) diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java index ad97329..ee69fc5 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java @@ -81,9 +81,9 @@ public Date getCreatedAt() throws CloudAppException { } } - public Date getUploadedAt() throws CloudAppException { + public Date getUpdatedAt() throws CloudAppException { try { - String d = getString("uploaded_at"); + String d = getString("updated_at"); return format.parse(d); } catch (ParseException e) { throw new CloudAppException(500, "Could not parse the date.", e); diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppModel.java b/src/main/java/com/cloudapp/impl/model/CloudAppModel.java index 37b2646..b969c2e 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppModel.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppModel.java @@ -11,7 +11,7 @@ public abstract class CloudAppModel { protected JSONObject json; protected static final DateFormat format = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ssz"); + "yyyy-MM-dd'T'HH:mm:ss'Z'"); protected String getString(String key) throws CloudAppException { try { From 48351c7e17b1c5012532c2010c8806c78e1e518b Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sat, 28 Jan 2012 21:38:15 +0100 Subject: [PATCH 04/13] Fixed failing delete test. Cause: assuming deleted_at was always there or had a valid value. --- src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java | 4 ++-- src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java index ee69fc5..9db61a8 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java @@ -31,8 +31,8 @@ public boolean isSubscribed() throws CloudAppException { } public boolean isTrashed() throws CloudAppException { - Date d = getDeletedAt(); - return d != null; + String d = getString("deleted_at"); + return (d == null || d == "null"); } public String getUrl() throws CloudAppException { diff --git a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java index a369fc9..18a63d9 100644 --- a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java +++ b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java @@ -49,6 +49,8 @@ public void testDelete() throws JSONException, CloudAppException { @Test public void testUpload() throws CloudAppException, JSONException { CloudAppItem o = api.upload(file); + Assert.assertNotNull(o); assertEquals("test_file.txt", o.getName()); + Assert.assertNotNull(o.getCreatedAt()); } } From 50f5ac3a19d32e1589fce8abdc92893fdcf30f05 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sat, 28 Jan 2012 22:19:52 +0100 Subject: [PATCH 05/13] Huge bug in getItems. Spotted by @quanturium. --- pom.xml | 6 ++++ .../com/cloudapp/impl/CloudAppItemsImpl.java | 29 +++++++++++-------- .../cloudapp/impl/CloudAppItemsImplTest.java | 6 ++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index aa47a85..1fe616f 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,12 @@ 1.6.1 compile + + org.apache.commons + commons-lang3 + 3.1 + compile + diff --git a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java index 298368e..7a93ea5 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java +++ b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java @@ -6,6 +6,7 @@ import java.util.Iterator; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; @@ -108,21 +109,25 @@ public List getItems(int page, int perPage, CloudAppItem.Type type perPage = 5; if (page == 0) page = 1; - - HttpGet req = new HttpGet(ITEMS_URL); - req.addHeader("Accept", "application/json"); - HttpParams params = new BasicHttpParams(); - params.setIntParameter("page", page); - params.setIntParameter("per_page", perPage); - params.setBooleanParameter("deleted", showDeleted); - if (type != null) { - params.setParameter("type", type.toString().toLowerCase()); + + List params = new ArrayList(); + params.add("page="+page); + params.add("per_page="+perPage); + params.add("deleted="+ (showDeleted ? "true" : "false")); + + if (type != null) + { + params.add("type=" + type.toString().toLowerCase()); } - if (source != null) { - params.setParameter("source", source); + if (source != null) + { + params.add("source=" + source); } - req.setParams(params); + String queryString = StringUtils.join(params.iterator(), "&"); + HttpGet req = new HttpGet(ITEMS_URL + "?" + queryString); + req.addHeader("Accept", "application/json"); + HttpResponse response = client.execute(req); int status = response.getStatusLine().getStatusCode(); String responseBody = EntityUtils.toString(response.getEntity()); diff --git a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java index 18a63d9..3202075 100644 --- a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java +++ b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java @@ -53,4 +53,10 @@ public void testUpload() throws CloudAppException, JSONException { assertEquals("test_file.txt", o.getName()); Assert.assertNotNull(o.getCreatedAt()); } + + @Test + public void simpleGetItemsTesT() throws CloudAppException { + List l = api.getItems(1, 5, null, true, null); + Assert.assertNotNull(l); + } } From 68b13dfad55122370a4f9fef38069300b92b68e4 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sat, 28 Jan 2012 22:28:41 +0100 Subject: [PATCH 06/13] Added a getThumbnailUrl --- src/main/java/com/cloudapp/api/model/CloudAppItem.java | 7 +++++++ .../java/com/cloudapp/impl/model/CloudAppItemImpl.java | 9 +++++++++ .../java/com/cloudapp/impl/CloudAppItemsImplTest.java | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cloudapp/api/model/CloudAppItem.java b/src/main/java/com/cloudapp/api/model/CloudAppItem.java index cf63e58..fa9ab14 100644 --- a/src/main/java/com/cloudapp/api/model/CloudAppItem.java +++ b/src/main/java/com/cloudapp/api/model/CloudAppItem.java @@ -86,6 +86,13 @@ enum Type { * @throws CloudAppExtion */ String getRedirectUrl() throws CloudAppException; + + /** + * @return A url that points to a thumbnail of this item if one is available, + * null otherwise. ie: "http://thumbs.cl.ly/2wr4" + * @throws CloudAppException + */ + String getThumbnailUrl() throws CloudAppException; /** * @return Identifies the app that uploaded this item. ie: diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java index 9db61a8..6b991a9 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java @@ -67,6 +67,15 @@ public String getRemoteUrl() throws CloudAppException { public String getRedirectUrl() throws CloudAppException { return getString("redirect_url"); } + + public String getThumbnailUrl() throws CloudAppException { + if (json.has("thumbnail_url")) { + return getString("thumbnail_url"); + } + else { + return null; + } + } public String getSource() throws CloudAppException { return getString("source"); diff --git a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java index 3202075..b7af213 100644 --- a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java +++ b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java @@ -55,8 +55,8 @@ public void testUpload() throws CloudAppException, JSONException { } @Test - public void simpleGetItemsTesT() throws CloudAppException { - List l = api.getItems(1, 5, null, true, null); + public void simpleGetItemsTest() throws CloudAppException { + List l = api.getItems(1, 5, null, false, null); Assert.assertNotNull(l); } } From 81f32c931ec5ba82ff10a21c6cb6332f9a85234d Mon Sep 17 00:00:00 2001 From: John Morales Date: Sat, 11 Feb 2012 14:40:23 -0500 Subject: [PATCH 07/13] Adding support for an upload listener to track progress. --- src/main/java/com/cloudapp/api/CloudApp.java | 17 +++- .../api/model/CloudAppProgressListener.java | 12 +++ .../java/com/cloudapp/impl/CloudAppImpl.java | 11 +++ .../cloudapp/impl/CloudAppInputStream.java | 67 ++++++++++---- .../com/cloudapp/impl/CloudAppItemsImpl.java | 87 ++++++++++--------- .../cloudapp/impl/CloudAppItemsImplTest.java | 21 ++++- 6 files changed, 154 insertions(+), 61 deletions(-) create mode 100644 src/main/java/com/cloudapp/api/model/CloudAppProgressListener.java diff --git a/src/main/java/com/cloudapp/api/CloudApp.java b/src/main/java/com/cloudapp/api/CloudApp.java index a1995bb..620a2c6 100644 --- a/src/main/java/com/cloudapp/api/CloudApp.java +++ b/src/main/java/com/cloudapp/api/CloudApp.java @@ -6,6 +6,7 @@ import com.cloudapp.api.model.CloudAppAccount; import com.cloudapp.api.model.CloudAppAccountStats; import com.cloudapp.api.model.CloudAppItem; +import com.cloudapp.api.model.CloudAppProgressListener; public interface CloudApp { @@ -58,7 +59,7 @@ public CloudAppAccount setPassword(String newPassword, String currentPassword) throws CloudAppException; /** - * Dispatch an email containing a link to reset the accountÕs password. + * Dispatch an email containing a link to reset the account�s password. * * @see http://developer.getcloudapp.com/forgot-password * @param email @@ -94,7 +95,7 @@ public CloudAppAccount createAccount(String email, String password, boolean acce /** * Add or change the domain used for all links. Optionally, a URL may be provided to - * redirect visitors to the custom domainÕs root. Pro users only + * redirect visitors to the custom domain�s root. Pro users only * * @see http://developer.getcloudapp.com/set-custom-domain * @param domain @@ -209,6 +210,18 @@ public List getItems(int page, int perPage, CloudAppItem.Type type */ public CloudAppItem upload(File file) throws CloudAppException; + /** + * + * @see http://developer.getcloudapp.com/upload-file + * @param file + * The file you wish to upload. + * @param listener + * To receive progress updates during upload + * @throws CloudAppException + * @return + */ + public CloudAppItem upload(File file, CloudAppProgressListener listener) throws CloudAppException; + /** * Deletes an item * diff --git a/src/main/java/com/cloudapp/api/model/CloudAppProgressListener.java b/src/main/java/com/cloudapp/api/model/CloudAppProgressListener.java new file mode 100644 index 0000000..91b82c2 --- /dev/null +++ b/src/main/java/com/cloudapp/api/model/CloudAppProgressListener.java @@ -0,0 +1,12 @@ +package com.cloudapp.api.model; + +/** + * Listener to receive notification as data's written to the output stream during upload. + */ +public interface CloudAppProgressListener { + void transferred(long written, long length); + + public static CloudAppProgressListener NO_OP = new CloudAppProgressListener() { + public void transferred(long written, long length) {} + }; +} diff --git a/src/main/java/com/cloudapp/impl/CloudAppImpl.java b/src/main/java/com/cloudapp/impl/CloudAppImpl.java index ef8c5d5..13044b2 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppImpl.java +++ b/src/main/java/com/cloudapp/impl/CloudAppImpl.java @@ -3,6 +3,7 @@ import java.io.File; import java.util.List; +import com.cloudapp.api.model.CloudAppProgressListener; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.impl.DefaultConnectionReuseStrategy; @@ -186,6 +187,16 @@ public CloudAppItem upload(File file) throws CloudAppException { return items.upload(file); } + /** + * + * {@inheritDoc} + * + * @see com.cloudapp.api.CloudAppItems#upload(java.io.File, com.cloudapp.api.model.CloudAppProgressListener) + */ + public CloudAppItem upload(File file, CloudAppProgressListener listener) throws CloudAppException { + return items.upload(file, listener); + } + /** * * {@inheritDoc} diff --git a/src/main/java/com/cloudapp/impl/CloudAppInputStream.java b/src/main/java/com/cloudapp/impl/CloudAppInputStream.java index 6de8e12..8cee567 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppInputStream.java +++ b/src/main/java/com/cloudapp/impl/CloudAppInputStream.java @@ -23,29 +23,64 @@ package com.cloudapp.impl; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; +import java.io.*; +import com.cloudapp.api.model.CloudAppProgressListener; import org.apache.http.entity.mime.content.InputStreamBody; public class CloudAppInputStream extends InputStreamBody { - private long length; + private final long length; + private final CloudAppProgressListener listener; - public CloudAppInputStream(InputStream in, String filename, long length) { - super(in, filename); - this.length = length; - } + public CloudAppInputStream(InputStream in, String filename, long length, CloudAppProgressListener listener) { + super(in, filename); + this.length = length; + this.listener = (listener == null) ? CloudAppProgressListener.NO_OP : listener; + } - protected CloudAppInputStream(File file) throws FileNotFoundException { - this(new FileInputStream(file), file.getName(), file.length()); - } + protected CloudAppInputStream(File file, CloudAppProgressListener listener) throws FileNotFoundException { + this(new FileInputStream(file), file.getName(), file.length(), listener); + } - @Override - public long getContentLength() { - return length; - } + @Override + public void writeTo(OutputStream out) throws IOException { + super.writeTo( new ListeningOutputStream(out) ); + } + + @Override + public long getContentLength() { + return length; + } + + private class ListeningOutputStream extends FilterOutputStream { + + private long bytesWritten; + + public ListeningOutputStream(OutputStream out) { + super(out); + bytesWritten = 0L; + } + + @Override + public void write(int b) throws IOException { + out.write(b); + listener.transferred(++bytesWritten, length); + } + + @Override + public void write(byte[] b) throws IOException { + out.write(b); + bytesWritten += b.length; + listener.transferred(bytesWritten, length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + bytesWritten += (len - off); + listener.transferred(bytesWritten, length); + } + } } diff --git a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java index 7a93ea5..9e91b17 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java +++ b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import com.cloudapp.api.CloudAppException; +import com.cloudapp.api.model.CloudAppProgressListener; import com.cloudapp.api.model.CloudAppItem; import com.cloudapp.impl.model.CloudAppItemImpl; @@ -155,61 +156,67 @@ public List getItems(int page, int perPage, CloudAppItem.Type type } } - /** - * - * {@inheritDoc} - * - * @see com.cloudapp.api.CloudAppItems#upload(java.io.File) - */ - public CloudAppItem upload(File file) throws CloudAppException { - try { - // Do a GET request so we have the S3 endpoint - HttpGet req = new HttpGet(NEW_ITEM_URL); - req.addHeader("Accept", "application/json"); - HttpResponse response = client.execute(req); - int status = response.getStatusLine().getStatusCode(); - String responseBody = EntityUtils.toString(response.getEntity()); - if (status != 200) - throw new CloudAppException(status, responseBody, null); + /** + * + * {@inheritDoc} + * + * @see com.cloudapp.api.CloudAppItems#upload(java.io.File) + */ + public CloudAppItem upload(File file) throws CloudAppException { + return upload( file, CloudAppProgressListener.NO_OP ); + } - JSONObject json = new JSONObject(responseBody); - if (!json.has("params")) { - // Something went wrong, maybe we crossed the treshold? - if (json.getInt("uploads_remaining") == 0) { - throw new CloudAppException(200, "Uploads remaining is 0", null); - } - throw new CloudAppException(500, "Missing params object from the CloudApp API.", - null); - } + public CloudAppItem upload(File file, CloudAppProgressListener listener) throws CloudAppException { + try { + // Do a GET request so we have the S3 endpoint + HttpGet req = new HttpGet(NEW_ITEM_URL); + req.addHeader("Accept", "application/json"); + HttpResponse response = client.execute(req); + int status = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity()); + if (status != 200) + throw new CloudAppException(status, responseBody, null); - return uploadToAmazon(json, file); + JSONObject json = new JSONObject(responseBody); + if (!json.has("params")) { + // Something went wrong, maybe we crossed the treshold? + if (json.getInt("uploads_remaining") == 0) { + throw new CloudAppException(200, "Uploads remaining is 0", null); + } + throw new CloudAppException(500, "Missing params object from the CloudApp API.", + null); + } - } catch (ClientProtocolException e) { - LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); - throw new CloudAppException(500, - "Something went wrong trying to contact the CloudApp API", e); - } catch (IOException e) { - LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); - throw new CloudAppException(500, - "Something went wrong trying to contact the CloudApp API.", e); - } catch (JSONException e) { - LOGGER.error("Something went wrong trying to handle JSON.", e); - throw new CloudAppException(500, "Something went wrong trying to handle JSON.", e); + return uploadToAmazon(json, file, listener); + + } catch (ClientProtocolException e) { + LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); + throw new CloudAppException(500, + "Something went wrong trying to contact the CloudApp API", e); + } catch (IOException e) { + LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); + throw new CloudAppException(500, + "Something went wrong trying to contact the CloudApp API.", e); + } catch (JSONException e) { + LOGGER.error("Something went wrong trying to handle JSON.", e); + throw new CloudAppException(500, "Something went wrong trying to handle JSON.", e); + } } - } /** * Uploads a file to S3 * + * * @param json * @param file + * @param listener * @return * @throws JSONException * @throws CloudAppException * @throws ParseException * @throws IOException */ - private CloudAppItem uploadToAmazon(JSONObject json, File file) throws JSONException, + private CloudAppItem uploadToAmazon(JSONObject json, File file, CloudAppProgressListener listener) throws JSONException, CloudAppException, ParseException, IOException { JSONObject params = json.getJSONObject("params"); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); @@ -223,7 +230,7 @@ private CloudAppItem uploadToAmazon(JSONObject json, File file) throws JSONExcep // Add the actual file. // We have to use the 'file' parameter for the S3 storage. - InputStreamBody stream = new CloudAppInputStream(file); + InputStreamBody stream = new CloudAppInputStream(file, listener); entity.addPart("file", stream); HttpPost uploadRequest = new HttpPost(json.getString("url")); diff --git a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java index b7af213..91f046a 100644 --- a/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java +++ b/src/test/java/com/cloudapp/impl/CloudAppItemsImplTest.java @@ -5,7 +5,9 @@ import java.io.File; import java.net.URL; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import com.cloudapp.api.model.CloudAppProgressListener; import org.json.JSONException; import org.junit.Assert; import org.junit.Before; @@ -16,12 +18,13 @@ public class CloudAppItemsImplTest extends BaseTestCase { - private File file; + private static final String TEST_FILE_NAME = "test_file.txt"; + private File file; @Before public void setUp() { super.setUp(); - URL fileurl = getClass().getResource("/test_file.txt"); + URL fileurl = getClass().getResource( "/" + TEST_FILE_NAME ); file = new File(fileurl.getPath()); } @@ -50,7 +53,7 @@ public void testDelete() throws JSONException, CloudAppException { public void testUpload() throws CloudAppException, JSONException { CloudAppItem o = api.upload(file); Assert.assertNotNull(o); - assertEquals("test_file.txt", o.getName()); + assertEquals(TEST_FILE_NAME, o.getName()); Assert.assertNotNull(o.getCreatedAt()); } @@ -59,4 +62,16 @@ public void simpleGetItemsTest() throws CloudAppException { List l = api.getItems(1, 5, null, false, null); Assert.assertNotNull(l); } + + @Test + public void testUploadListener() throws CloudAppException, JSONException { + final AtomicLong calledCount = new AtomicLong(); + CloudAppItem o = api.upload(file, new CloudAppProgressListener() { + public void transferred(long written, long length) { + calledCount.incrementAndGet(); + } + }); + assertEquals( TEST_FILE_NAME, o.getName() ); + assertEquals( 1, calledCount.get() ); + } } From c328614b8923849ca7d616af9b40a18e48c43060 Mon Sep 17 00:00:00 2001 From: John Morales Date: Mon, 13 Feb 2012 20:34:25 -0500 Subject: [PATCH 08/13] Fixing formatting to match existing conventions. --- .../cloudapp/impl/CloudAppInputStream.java | 84 +++++++++---------- .../com/cloudapp/impl/CloudAppItemsImpl.java | 84 +++++++++---------- 2 files changed, 83 insertions(+), 85 deletions(-) diff --git a/src/main/java/com/cloudapp/impl/CloudAppInputStream.java b/src/main/java/com/cloudapp/impl/CloudAppInputStream.java index 8cee567..99f4c2a 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppInputStream.java +++ b/src/main/java/com/cloudapp/impl/CloudAppInputStream.java @@ -30,57 +30,57 @@ public class CloudAppInputStream extends InputStreamBody { - private final long length; - private final CloudAppProgressListener listener; + private final long length; + private final CloudAppProgressListener listener; - public CloudAppInputStream(InputStream in, String filename, long length, CloudAppProgressListener listener) { - super(in, filename); - this.length = length; - this.listener = (listener == null) ? CloudAppProgressListener.NO_OP : listener; - } + public CloudAppInputStream(InputStream in, String filename, long length, CloudAppProgressListener listener) { + super(in, filename); + this.length = length; + this.listener = (listener == null) ? CloudAppProgressListener.NO_OP : listener; + } + + protected CloudAppInputStream(File file, CloudAppProgressListener listener) throws FileNotFoundException { + this(new FileInputStream(file), file.getName(), file.length(), listener); + } + + @Override + public void writeTo(OutputStream out) throws IOException { + super.writeTo( new ListeningOutputStream(out) ); + } + + @Override + public long getContentLength() { + return length; + } - protected CloudAppInputStream(File file, CloudAppProgressListener listener) throws FileNotFoundException { - this(new FileInputStream(file), file.getName(), file.length(), listener); + private class ListeningOutputStream extends FilterOutputStream { + + private long bytesWritten; + + public ListeningOutputStream(OutputStream out) { + super(out); + bytesWritten = 0L; } @Override - public void writeTo(OutputStream out) throws IOException { - super.writeTo( new ListeningOutputStream(out) ); + public void write(int b) throws IOException { + out.write(b); + listener.transferred(++bytesWritten, length); } @Override - public long getContentLength() { - return length; + public void write(byte[] b) throws IOException { + out.write(b); + bytesWritten += b.length; + listener.transferred(bytesWritten, length); } - - private class ListeningOutputStream extends FilterOutputStream { - - private long bytesWritten; - - public ListeningOutputStream(OutputStream out) { - super(out); - bytesWritten = 0L; - } - - @Override - public void write(int b) throws IOException { - out.write(b); - listener.transferred(++bytesWritten, length); - } - - @Override - public void write(byte[] b) throws IOException { - out.write(b); - bytesWritten += b.length; - listener.transferred(bytesWritten, length); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - out.write(b, off, len); - bytesWritten += (len - off); - listener.transferred(bytesWritten, length); - } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + bytesWritten += (len - off); + listener.transferred(bytesWritten, length); } + } } diff --git a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java index 9e91b17..3896d9f 100644 --- a/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java +++ b/src/main/java/com/cloudapp/impl/CloudAppItemsImpl.java @@ -156,60 +156,58 @@ public List getItems(int page, int perPage, CloudAppItem.Type type } } - /** - * - * {@inheritDoc} - * - * @see com.cloudapp.api.CloudAppItems#upload(java.io.File) - */ - public CloudAppItem upload(File file) throws CloudAppException { - return upload( file, CloudAppProgressListener.NO_OP ); - } + /** + * + * {@inheritDoc} + * + * @see com.cloudapp.api.CloudAppItems#upload(java.io.File) + */ + public CloudAppItem upload(File file) throws CloudAppException { + return upload( file, CloudAppProgressListener.NO_OP ); + } - public CloudAppItem upload(File file, CloudAppProgressListener listener) throws CloudAppException { - try { - // Do a GET request so we have the S3 endpoint - HttpGet req = new HttpGet(NEW_ITEM_URL); - req.addHeader("Accept", "application/json"); - HttpResponse response = client.execute(req); - int status = response.getStatusLine().getStatusCode(); - String responseBody = EntityUtils.toString(response.getEntity()); - if (status != 200) - throw new CloudAppException(status, responseBody, null); + public CloudAppItem upload(File file, CloudAppProgressListener listener) throws CloudAppException { + try { + // Do a GET request so we have the S3 endpoint + HttpGet req = new HttpGet(NEW_ITEM_URL); + req.addHeader("Accept", "application/json"); + HttpResponse response = client.execute(req); + int status = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity()); + if (status != 200) + throw new CloudAppException(status, responseBody, null); - JSONObject json = new JSONObject(responseBody); - if (!json.has("params")) { - // Something went wrong, maybe we crossed the treshold? - if (json.getInt("uploads_remaining") == 0) { - throw new CloudAppException(200, "Uploads remaining is 0", null); - } - throw new CloudAppException(500, "Missing params object from the CloudApp API.", - null); - } + JSONObject json = new JSONObject(responseBody); + if (!json.has("params")) { + // Something went wrong, maybe we crossed the treshold? + if (json.getInt("uploads_remaining") == 0) { + throw new CloudAppException(200, "Uploads remaining is 0", null); + } + throw new CloudAppException(500, "Missing params object from the CloudApp API.", + null); + } - return uploadToAmazon(json, file, listener); + return uploadToAmazon(json, file, listener); - } catch (ClientProtocolException e) { - LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); - throw new CloudAppException(500, - "Something went wrong trying to contact the CloudApp API", e); - } catch (IOException e) { - LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); - throw new CloudAppException(500, - "Something went wrong trying to contact the CloudApp API.", e); - } catch (JSONException e) { - LOGGER.error("Something went wrong trying to handle JSON.", e); - throw new CloudAppException(500, "Something went wrong trying to handle JSON.", e); - } + } catch (ClientProtocolException e) { + LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); + throw new CloudAppException(500, + "Something went wrong trying to contact the CloudApp API", e); + } catch (IOException e) { + LOGGER.error("Something went wrong trying to contact the CloudApp API.", e); + throw new CloudAppException(500, + "Something went wrong trying to contact the CloudApp API.", e); + } catch (JSONException e) { + LOGGER.error("Something went wrong trying to handle JSON.", e); + throw new CloudAppException(500, "Something went wrong trying to handle JSON.", e); } + } /** * Uploads a file to S3 * - * * @param json * @param file - * @param listener * @return * @throws JSONException * @throws CloudAppException From fd0bd649237e517d69a8774d3b8e78943556b275 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Wed, 15 Feb 2012 16:27:44 +0100 Subject: [PATCH 09/13] Fixed 'trash' bug. --- src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java index 6b991a9..9d6739e 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppItemImpl.java @@ -32,7 +32,7 @@ public boolean isSubscribed() throws CloudAppException { public boolean isTrashed() throws CloudAppException { String d = getString("deleted_at"); - return (d == null || d == "null"); + return !(d == null || d == "null"); } public String getUrl() throws CloudAppException { From cd9bb13ebe318184012c1bcd00ddc3c1c2bac0d7 Mon Sep 17 00:00:00 2001 From: Josh Lee Date: Mon, 27 Feb 2012 15:41:12 -0600 Subject: [PATCH 10/13] Typo fix in CloudApp.java --- src/main/java/com/cloudapp/api/CloudApp.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cloudapp/api/CloudApp.java b/src/main/java/com/cloudapp/api/CloudApp.java index 620a2c6..fa5eb64 100644 --- a/src/main/java/com/cloudapp/api/CloudApp.java +++ b/src/main/java/com/cloudapp/api/CloudApp.java @@ -59,7 +59,7 @@ public CloudAppAccount setPassword(String newPassword, String currentPassword) throws CloudAppException; /** - * Dispatch an email containing a link to reset the account�s password. + * Dispatch an email containing a link to reset the account's password. * * @see http://developer.getcloudapp.com/forgot-password * @param email @@ -95,7 +95,7 @@ public CloudAppAccount createAccount(String email, String password, boolean acce /** * Add or change the domain used for all links. Optionally, a URL may be provided to - * redirect visitors to the custom domain�s root. Pro users only + * redirect visitors to the custom domain's root. Pro users only * * @see http://developer.getcloudapp.com/set-custom-domain * @param domain From 364f55530e3555e4c2b3198802e584344f8fa4ff Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Sat, 21 Jul 2012 19:01:27 +0200 Subject: [PATCH 11/13] Fixed a typo in the readme page. Spotted by Sn00py, thanks! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d9c29e..f5809a8 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ These set of Java classes allow you to easily talk to the CloudApp REST Apis. Usage Example ------------- - CloudApi api = new CloudApiImpl("Your email here", "Your password here"); + CloudApp api = new CloudAppImpl("Your email here", "Your password here"); // Add a new bookmark CloudAppItem bookmark = api.createBookmark('Simon Gaeremynck's portfolio', 'gaeremynck.com'); From 7588486c486661a25da7a621ece531da849d76e1 Mon Sep 17 00:00:00 2001 From: Arnaud Frugier Date: Sun, 24 Feb 2013 21:11:37 -0800 Subject: [PATCH 12/13] Added subscription_expires_at for the account details --- .../java/com/cloudapp/api/model/CloudAppAccount.java | 5 +++++ .../com/cloudapp/impl/model/CloudAppAccountImpl.java | 10 ++++++++++ .../java/com/cloudapp/impl/model/CloudAppModel.java | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/main/java/com/cloudapp/api/model/CloudAppAccount.java b/src/main/java/com/cloudapp/api/model/CloudAppAccount.java index 9723b60..f719759 100644 --- a/src/main/java/com/cloudapp/api/model/CloudAppAccount.java +++ b/src/main/java/com/cloudapp/api/model/CloudAppAccount.java @@ -57,4 +57,9 @@ enum DefaultSecurity { */ public Date ActivatedAt() throws CloudAppException; + /** + * @return The date you suscription expires if any + */ + public Date SubscriptionExpiresAt() throws CloudAppException; + } diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppAccountImpl.java b/src/main/java/com/cloudapp/impl/model/CloudAppAccountImpl.java index b0dfb80..e979e23 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppAccountImpl.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppAccountImpl.java @@ -74,4 +74,14 @@ public Date ActivatedAt() throws CloudAppException { } } + @Override + public Date SubscriptionExpiresAt() throws CloudAppException { + try { + String d = getString("subscription_expires_at"); + return formatBis.parse(d); + } catch (ParseException e) { + throw new CloudAppException(500, "Could not parse the date.", e); + } + } + } diff --git a/src/main/java/com/cloudapp/impl/model/CloudAppModel.java b/src/main/java/com/cloudapp/impl/model/CloudAppModel.java index b969c2e..22c66e7 100644 --- a/src/main/java/com/cloudapp/impl/model/CloudAppModel.java +++ b/src/main/java/com/cloudapp/impl/model/CloudAppModel.java @@ -12,6 +12,8 @@ public abstract class CloudAppModel { protected JSONObject json; protected static final DateFormat format = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss'Z'"); + protected static final DateFormat formatBis = new SimpleDateFormat( + "yyyy-MM-dd"); protected String getString(String key) throws CloudAppException { try { From 41fa929030b43bbc8dccbc2fe1dca825125829c0 Mon Sep 17 00:00:00 2001 From: Simon Gaeremynck Date: Thu, 14 Mar 2013 23:02:42 +0000 Subject: [PATCH 13/13] Markdown fixes in README.md --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f5809a8..f822523 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,15 @@ A jar can be compiled trough maven by running the following command. However, this will skip the unit tests. If you want to have the unit tests, you will need to fill in your email and password in src/test/resources/credentials.properties like so: - cred_mail=me@email.com - cred_password=mypassword - -Running a build can be done like so: -`mvn clean install` +``` +cred_mail=me@email.com +cred_password=mypassword +``` + +Running a build can be done by running: +``` +mvn clean install +``` License