diff --git a/pom.xml b/pom.xml
index 241653a..9800605 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,16 +4,16 @@
org.springframework.social
spring-social-dropbox
- 1.0
+ 1.0.0.M1
jar
spring-social-dropbox
http://maven.apache.org
1.6
- 1.0.0.RELEASE
- 3.1.0.M2
- 3.1.0.RC2
+ 1.0.1.RELEASE
+ 3.1.0.RELEASE
+ 3.1.0.RELEASE
1.6.1
UTF-8
@@ -25,6 +25,11 @@
3.8.1
test
+
+ org.springframework
+ spring-test
+ ${org.springframework-version}
+
org.springframework.social
spring-social-core
@@ -39,6 +44,12 @@
org.springframework.security
spring-security-core
${org.springframework.security-version}
+
+
+ org.springframework
+ spring-core
+
+
diff --git a/src/main/java/org/springframework/social/dropbox/api/Dropbox.java b/src/main/java/org/springframework/social/dropbox/api/Dropbox.java
new file mode 100644
index 0000000..d90585e
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/Dropbox.java
@@ -0,0 +1,127 @@
+package org.springframework.social.dropbox.api;
+
+import java.util.List;
+
+
+/**
+ * Dropbox Interface
+ *
+ * @author Bryce Fischer
+ * @author Robert Drysdale
+ */
+public interface Dropbox {
+ /**
+ * Retrieve Details for a Dropbox's Profile Details
+ *
+ * @return Dropbox Users Profile Details
+ */
+ DropboxUserProfile getUserProfile();
+
+ /**
+ * Get Metadata For a File or Directory
+ *
+ * @param path
+ * @return Metadata
+ */
+ Metadata getItemMetadata(String path);
+
+ /**
+ * Restore a file to a revision
+ * Will also restore an deleted file
+ *
+ * @param path
+ * @param rev
+ * @return Metadata
+ */
+ Metadata restore(String path, String rev) ;
+
+ /**
+ * Copy File to new file or directory
+ *
+ * @param fromPath
+ * @param toPath
+ * @return Metadata
+ */
+ Metadata copy(String fromPath, String toPath);
+
+ /**
+ * Create a new folder
+ *
+ * @param folder
+ * @return Metadata
+ */
+ Metadata createFolder(String folder);
+
+ /**
+ * Delete a file
+ *
+ * @param path
+ * @return Metadata
+ */
+ Metadata delete(String path);
+
+ /**
+ * Move a File
+ *
+ * @param fromPath
+ * @param toPath
+ * @return Metadata
+ */
+ Metadata move(String fromPath, String toPath);
+
+ /**
+ * Get List of Revisions for a File
+ * @param path
+ * @return List of Metadata
+ */
+ List getRevisions(String path);
+
+ /**
+ * Search for a File
+ *
+ * @param path
+ * @param query
+ * @return List of Metadata
+ */
+ List search(String path, String query);
+
+ /**
+ * Get Thumbnail for a file
+ *
+ * @param path
+ * @return Dropbox File
+ */
+ DropboxFile getThumbnail(String path);
+
+ /**
+ * Retrieve a File
+ * @param path
+ * @return Dropbox File
+ */
+ DropboxFile getFile(String path);
+
+ /**
+ * Get Url for a File that can be streamed as media
+ *
+ * @param path
+ * @return File Url with Expires Date
+ */
+ FileUrl getMedia(String path);
+
+ /**
+ * Get Url for a File that can be shared
+ *
+ * @param path
+ * @return File Url with Expires Date
+ */
+ FileUrl getShare(String path);
+
+ /**
+ * Push a File to Dropbox
+ *
+ * @param path
+ * @param file
+ * @return Metadata
+ */
+ Metadata putFile(String path, byte[] file);
+}
diff --git a/src/main/java/org/springframework/social/dropbox/api/DropboxApi.java b/src/main/java/org/springframework/social/dropbox/api/DropboxApi.java
deleted file mode 100644
index 1300e5a..0000000
--- a/src/main/java/org/springframework/social/dropbox/api/DropboxApi.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.springframework.social.dropbox.api;
-
-import java.math.BigInteger;
-import java.util.List;
-
-/**
- * User: Bryce Fischer
- * Date: 5/17/11
- * Time: 8:57 AM
- */
-public interface DropboxApi {
- DropboxUserProfile getUserProfile();
-
- List getItemMetadata(String path, boolean list, BigInteger maxFiles);
-}
diff --git a/src/main/java/org/springframework/social/dropbox/api/DropboxFile.java b/src/main/java/org/springframework/social/dropbox/api/DropboxFile.java
new file mode 100644
index 0000000..522bfa8
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/DropboxFile.java
@@ -0,0 +1,46 @@
+package org.springframework.social.dropbox.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+
+/**
+ * Dropbox File Details
+ *
+ * @author Robert Drysdale
+ *
+ */
+public class DropboxFile implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final String contentType;
+ private final long size;
+ private final InputStream inputStream;
+
+ public DropboxFile(String contentType, long size, InputStream inputStream) {
+ this.contentType = contentType;
+ this.size = size;
+ this.inputStream = inputStream;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+ public byte[] getBytes() throws IOException {
+ byte[] ret = new byte[(int)size];
+ for (int i = 0; i < size; i++) {
+ ret[i] = (byte)inputStream.read();
+ }
+
+ return ret;
+ }
+}
diff --git a/src/main/java/org/springframework/social/dropbox/api/DropboxItemMetadata.java b/src/main/java/org/springframework/social/dropbox/api/DropboxItemMetadata.java
deleted file mode 100644
index 63200f9..0000000
--- a/src/main/java/org/springframework/social/dropbox/api/DropboxItemMetadata.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.springframework.social.dropbox.api;
-
-/**
- * User: Bryce Fischer
- * Date: 5/17/11
- * Time: 9:19 AM
- */
-public class DropboxItemMetadata {
-}
diff --git a/src/main/java/org/springframework/social/dropbox/api/DropboxUserProfile.java b/src/main/java/org/springframework/social/dropbox/api/DropboxUserProfile.java
index ddffec9..97769e1 100644
--- a/src/main/java/org/springframework/social/dropbox/api/DropboxUserProfile.java
+++ b/src/main/java/org/springframework/social/dropbox/api/DropboxUserProfile.java
@@ -3,9 +3,10 @@
import java.math.BigInteger;
/**
- * User: Bryce Fischer
- * Date: 5/17/11
- * Time: 9:15 AM
+ *
+ * Dropbox User Profile
+ *
+ * @author Bryce Fischer
*/
public class DropboxUserProfile {
private String country;
diff --git a/src/main/java/org/springframework/social/dropbox/api/FileUrl.java b/src/main/java/org/springframework/social/dropbox/api/FileUrl.java
new file mode 100644
index 0000000..58819fc
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/FileUrl.java
@@ -0,0 +1,32 @@
+package org.springframework.social.dropbox.api;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * File Url that can be shared or streamed as media
+ *
+ * @author Robert Drysdale
+ *
+ */
+public class FileUrl implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String url;
+ private final Date expires;
+
+ public FileUrl(String url, Date expires) {
+ this.url = url;
+ this.expires = expires;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public Date getExpires() {
+ return expires;
+ }
+
+}
diff --git a/src/main/java/org/springframework/social/dropbox/api/Metadata.java b/src/main/java/org/springframework/social/dropbox/api/Metadata.java
new file mode 100644
index 0000000..9035489
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/Metadata.java
@@ -0,0 +1,100 @@
+package org.springframework.social.dropbox.api;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Metadata which describes a directory or file
+ * in Dropbox
+ *
+ * @author Robert Drysdale
+ *
+ */
+public class Metadata implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final String size;
+ private final int bytes;
+ private final boolean isDir;
+ private final boolean isDeleted;
+ private final String rev;
+ private final String hash;
+ private final boolean thumbExists;
+ private final String icon;
+ private final Date modified;
+ private final String root;
+ private final String path;
+ private final String mimeType;
+ private final List contents;
+
+ public Metadata(String size, int bytes, boolean isDir, boolean isDeleted,
+ String rev, String hash, boolean thumbExists, String icon,
+ Date modified, String root, String path, String mimeType, List contents) {
+ super();
+ this.size = size;
+ this.bytes = bytes;
+ this.isDir = isDir;
+ this.isDeleted = isDeleted;
+ this.rev = rev;
+ this.hash = hash;
+ this.thumbExists = thumbExists;
+ this.icon = icon;
+ this.modified = modified;
+ this.root = root;
+ this.path = path;
+ this.mimeType = mimeType;
+ this.contents = contents;
+ }
+
+ public String getSize() {
+ return size;
+ }
+
+ public int getBytes() {
+ return bytes;
+ }
+
+ public boolean isDir() {
+ return isDir;
+ }
+
+ public boolean isDeleted() {
+ return isDeleted;
+ }
+
+ public String getRev() {
+ return rev;
+ }
+
+ public String getHash() {
+ return hash;
+ }
+
+ public boolean isThumbExists() {
+ return thumbExists;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public Date getModified() {
+ return modified;
+ }
+
+ public String getRoot() {
+ return root;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ public List getContents() {
+ return contents;
+ }
+}
diff --git a/src/main/java/org/springframework/social/dropbox/api/impl/DropboxModule.java b/src/main/java/org/springframework/social/dropbox/api/impl/DropboxModule.java
index a69ee2a..a2013e0 100644
--- a/src/main/java/org/springframework/social/dropbox/api/impl/DropboxModule.java
+++ b/src/main/java/org/springframework/social/dropbox/api/impl/DropboxModule.java
@@ -3,6 +3,8 @@
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.module.SimpleModule;
import org.springframework.social.dropbox.api.DropboxUserProfile;
+import org.springframework.social.dropbox.api.FileUrl;
+import org.springframework.social.dropbox.api.Metadata;
/**
* User: Bryce Fischer
@@ -17,5 +19,7 @@ public DropboxModule() {
@Override
public void setupModule(SetupContext context) {
context.setMixInAnnotations(DropboxUserProfile.class, DropboxUserProfileMixin.class);
+ context.setMixInAnnotations(Metadata.class, MetadataMixin.class);
+ context.setMixInAnnotations(FileUrl.class, FileUrlMixin.class);
}
}
diff --git a/src/main/java/org/springframework/social/dropbox/api/impl/DropboxTemplate.java b/src/main/java/org/springframework/social/dropbox/api/impl/DropboxTemplate.java
index 92c85eb..49f20cc 100644
--- a/src/main/java/org/springframework/social/dropbox/api/impl/DropboxTemplate.java
+++ b/src/main/java/org/springframework/social/dropbox/api/impl/DropboxTemplate.java
@@ -1,41 +1,180 @@
package org.springframework.social.dropbox.api.impl;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.List;
+
+import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
-import org.springframework.social.dropbox.api.DropboxApi;
-import org.springframework.social.dropbox.api.DropboxItemMetadata;
+import org.springframework.social.dropbox.api.Dropbox;
+import org.springframework.social.dropbox.api.DropboxFile;
import org.springframework.social.dropbox.api.DropboxUserProfile;
+import org.springframework.social.dropbox.api.FileUrl;
+import org.springframework.social.dropbox.api.Metadata;
import org.springframework.social.oauth1.AbstractOAuth1ApiBinding;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
-
-import java.math.BigInteger;
-import java.util.List;
+import org.springframework.web.util.UriTemplate;
/**
* User: Bryce Fischer
* Date: 5/17/11
* Time: 9:22 AM
*/
-public class DropboxTemplate extends AbstractOAuth1ApiBinding implements DropboxApi {
- public DropboxTemplate(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) {
- super(consumerKey, consumerSecret, accessToken, accessTokenSecret);
-
+public class DropboxTemplate extends AbstractOAuth1ApiBinding implements Dropbox {
+ private final String appFolderUrl;
+ private ObjectMapper objectMapper;
+ public DropboxTemplate(String appKey, String appSecret, String accessToken, String accessTokenSecret, boolean appFolder) {
+ super(appKey, appSecret, accessToken, accessTokenSecret);
+ appFolderUrl = appFolder ? "sandbox" : "dropbox";
registerDropboxJsonModule(getRestTemplate());
}
public DropboxTemplate() {
super();
+ appFolderUrl = null;
}
public DropboxUserProfile getUserProfile() {
- return getRestTemplate().getForObject("https://api.dropbox.com/1/account/info", DropboxUserProfile.class);
+ return getRestTemplate().getForObject(ACCOUNT_INFO_URL, DropboxUserProfile.class);
}
- public List getItemMetadata(String path, boolean list, BigInteger maxFiles) {
- return null;
+ public Metadata getItemMetadata(String path) {
+ return getRestTemplate().getForObject(METADATA_URL, Metadata.class, appFolderUrl, path);
}
-
+
+ public Metadata restore(String path, String rev) {
+ return getRestTemplate().getForObject(RESTORE_URL + "?rev=" + rev, Metadata.class, appFolderUrl, path);
+ }
+
+ public Metadata copy(String fromPath, String toPath) {
+ MultiValueMap vars = new LinkedMultiValueMap();
+ vars.add("root", appFolderUrl);
+ vars.add("from_path", fromPath);
+ vars.add("to_path", toPath);
+ return getRestTemplate().postForObject(COPY_URL, vars, Metadata.class);
+ }
+
+ public Metadata createFolder(String folder) {
+ MultiValueMap vars = new LinkedMultiValueMap();
+ vars.add("root", appFolderUrl);
+ vars.add("path", folder);
+ return getRestTemplate().postForObject(CREATE_FOLDER_URL, vars, Metadata.class);
+ }
+
+ public Metadata delete(String path) {
+ MultiValueMap vars = new LinkedMultiValueMap();
+ vars.add("root", appFolderUrl);
+ vars.add("path", path);
+ return getRestTemplate().postForObject(DELETE_URL, vars, Metadata.class);
+ }
+
+ public Metadata move(String fromPath, String toPath) {
+ MultiValueMap vars = new LinkedMultiValueMap();
+ vars.add("root", appFolderUrl);
+ vars.add("from_path", fromPath);
+ vars.add("to_path", toPath);
+ return getRestTemplate().postForObject(MOVE_URL, vars, Metadata.class);
+ }
+
+ public List getRevisions(String path) {
+ JsonNode node = getRestTemplate().getForObject(REVISIONS_URL, JsonNode.class, appFolderUrl, path);
+
+ try {
+ return objectMapper.readValue(node, new TypeReference>() {});
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public List search(String path, String query) {
+ JsonNode node = getRestTemplate().getForObject(SEARCH_URL + "?query=" + query, JsonNode.class, appFolderUrl, path);
+
+ try {
+ return objectMapper.readValue(node, new TypeReference>() {});
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public DropboxFile getThumbnail(String path) {
+ try {
+ UriTemplate uriTemplate = new UriTemplate(THUMBNAILS_URL);
+ URI uri = uriTemplate.expand(appFolderUrl, path);
+ ClientHttpResponse response = getRestTemplate().getRequestFactory().createRequest(uri, HttpMethod.GET).execute();
+ HttpHeaders headers = response.getHeaders();
+
+ return new DropboxFile(
+ headers.getContentType().toString(),
+ headers.getContentLength(),
+ response.getBody());
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public DropboxFile getFile(String path) {
+ try {
+ UriTemplate uriTemplate = new UriTemplate(FILE_URL);
+ URI uri = uriTemplate.expand(appFolderUrl, path);
+ ClientHttpResponse response = getRestTemplate().getRequestFactory().createRequest(uri, HttpMethod.GET).execute();
+ HttpHeaders headers = response.getHeaders();
+
+ return new DropboxFile(
+ headers.getContentType().toString(),
+ headers.getContentLength(),
+ response.getBody());
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public FileUrl getMedia(String path) {
+ return getRestTemplate().getForObject(MEDIA_URL, FileUrl.class, appFolderUrl, path);
+ }
+
+ public FileUrl getShare(String path) {
+ return getRestTemplate().getForObject(SHARES_URL, FileUrl.class, appFolderUrl, path);
+ }
+
+ public Metadata putFile(String path, byte[] file) {
+ UriTemplate uriTemplate = new UriTemplate(FILE_PUT_URL);
+ URI uri = uriTemplate.expand(appFolderUrl, path);
+
+ try {
+ ClientHttpRequest request = getRestTemplate().getRequestFactory().createRequest(uri, HttpMethod.PUT);
+ request.getBody().write(file);
+
+ ClientHttpResponse response = request.execute();
+ ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();
+ if (errorHandler.hasError(response)) {
+ errorHandler.handleError(response);
+ return null;
+ }
+ else {
+ InputStream stream = response.getBody();
+ return objectMapper.readValue(stream, Metadata.class);
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private void registerDropboxJsonModule(RestTemplate restTemplate) {
List> converters = restTemplate.getMessageConverters();
@@ -43,10 +182,29 @@ private void registerDropboxJsonModule(RestTemplate restTemplate) {
if (converter instanceof MappingJacksonHttpMessageConverter) {
MappingJacksonHttpMessageConverter jsonConverter = (MappingJacksonHttpMessageConverter) converter;
- ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper = new ObjectMapper();
objectMapper.registerModule(new DropboxModule());
jsonConverter.setObjectMapper(objectMapper);
}
}
}
+
+ public static final String BASE_URL = "https://api.dropbox.com/1/";
+ public static final String BASE_CONTENT_URL = "https://api-content.dropbox.com/1/";
+
+ public static final String ACCOUNT_INFO_URL = BASE_URL + "account/info";
+ public static final String COPY_URL = BASE_URL + "fileops/copy";
+ public static final String CREATE_FOLDER_URL = BASE_URL + "fileops/create_folder";
+ public static final String DELETE_URL = BASE_URL + "fileops/delete";
+ public static final String FILE_URL = BASE_CONTENT_URL + "files/{appFolderUrl}/{path}";
+ public static final String FILE_POST_URL = BASE_CONTENT_URL + "files/{appFolderUrl}/{path}";
+ public static final String FILE_PUT_URL = BASE_CONTENT_URL + "files_put/{appFolderUrl}/{path}";
+ public static final String MEDIA_URL = BASE_URL + "media/{appFolderUrl}/{path}";
+ public static final String METADATA_URL = BASE_URL + "metadata/{appFolderUrl}/{path}";
+ public static final String MOVE_URL = BASE_URL + "fileops/move";
+ public static final String RESTORE_URL = BASE_URL + "restore/{appFolderUrl}/{path}";
+ public static final String REVISIONS_URL = BASE_URL + "revisions/{appFolderUrl}/{path}";
+ public static final String SEARCH_URL = BASE_URL + "search/{appFolderUrl}/{path}";
+ public static final String SHARES_URL = BASE_URL + "shares/{appFolderUrl}/{path}";
+ public static final String THUMBNAILS_URL = BASE_CONTENT_URL + "thumbnails/{appFolderUrl}/{path}";
}
diff --git a/src/main/java/org/springframework/social/dropbox/api/impl/FileUrlMixin.java b/src/main/java/org/springframework/social/dropbox/api/impl/FileUrlMixin.java
new file mode 100644
index 0000000..6684e8f
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/impl/FileUrlMixin.java
@@ -0,0 +1,15 @@
+package org.springframework.social.dropbox.api.impl;
+
+import java.util.Date;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class FileUrlMixin {
+ @JsonCreator
+ public FileUrlMixin(
+ @JsonProperty("url") String url,
+ @JsonProperty("expires") Date expires) {}
+}
diff --git a/src/main/java/org/springframework/social/dropbox/api/impl/MetadataMixin.java b/src/main/java/org/springframework/social/dropbox/api/impl/MetadataMixin.java
new file mode 100644
index 0000000..29b22d3
--- /dev/null
+++ b/src/main/java/org/springframework/social/dropbox/api/impl/MetadataMixin.java
@@ -0,0 +1,28 @@
+package org.springframework.social.dropbox.api.impl;
+
+import java.util.Date;
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.springframework.social.dropbox.api.Metadata;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MetadataMixin {
+ @JsonCreator
+ public MetadataMixin(
+ @JsonProperty("size") String size,
+ @JsonProperty("bytes") int bytes,
+ @JsonProperty("is_dir") boolean isDir,
+ @JsonProperty("is_deleted") boolean isDeleted,
+ @JsonProperty("rev") String rev,
+ @JsonProperty("hash") String hash,
+ @JsonProperty("thumb_exists") boolean thumbExists,
+ @JsonProperty("icon") String icon,
+ @JsonProperty("modified") Date modified,
+ @JsonProperty("root") String root,
+ @JsonProperty("path") String path,
+ @JsonProperty("mime_type") String mimeType,
+ @JsonProperty("contents") List contents) {}
+}
diff --git a/src/main/java/org/springframework/social/dropbox/connect/DropboxAdapter.java b/src/main/java/org/springframework/social/dropbox/connect/DropboxAdapter.java
index 24fe2ee..e751bd4 100644
--- a/src/main/java/org/springframework/social/dropbox/connect/DropboxAdapter.java
+++ b/src/main/java/org/springframework/social/dropbox/connect/DropboxAdapter.java
@@ -4,7 +4,7 @@
import org.springframework.social.connect.ConnectionValues;
import org.springframework.social.connect.UserProfile;
import org.springframework.social.connect.UserProfileBuilder;
-import org.springframework.social.dropbox.api.DropboxApi;
+import org.springframework.social.dropbox.api.Dropbox;
import org.springframework.social.dropbox.api.DropboxUserProfile;
import org.springframework.web.client.HttpClientErrorException;
@@ -13,9 +13,9 @@
* Date: 5/17/11
* Time: 11:33 AM
*/
-public class DropboxAdapter implements ApiAdapter {
+public class DropboxAdapter implements ApiAdapter {
@Override
- public boolean test(DropboxApi dropboxApi) {
+ public boolean test(Dropbox dropboxApi) {
try {
dropboxApi.getUserProfile();
return true;
@@ -25,7 +25,7 @@ public boolean test(DropboxApi dropboxApi) {
}
@Override
- public void setConnectionValues(DropboxApi dropboxApi, ConnectionValues values) {
+ public void setConnectionValues(Dropbox dropboxApi, ConnectionValues values) {
DropboxUserProfile profile = dropboxApi.getUserProfile();
values.setProviderUserId(profile.getUid().toString());
values.setDisplayName(profile.getDisplayName());
@@ -33,13 +33,13 @@ public void setConnectionValues(DropboxApi dropboxApi, ConnectionValues values)
}
@Override
- public UserProfile fetchUserProfile(DropboxApi dropboxApi) {
+ public UserProfile fetchUserProfile(Dropbox dropboxApi) {
DropboxUserProfile profile = dropboxApi.getUserProfile();
return new UserProfileBuilder().setName(profile.getDisplayName()).setUsername(profile.getEmail()).setEmail(profile.getEmail()).build();
}
@Override
- public void updateStatus(DropboxApi dropboxApi, String s) {
+ public void updateStatus(Dropbox dropboxApi, String s) {
// Not Supported
}
}
diff --git a/src/main/java/org/springframework/social/dropbox/connect/DropboxConnectionFactory.java b/src/main/java/org/springframework/social/dropbox/connect/DropboxConnectionFactory.java
index bb226f9..31c7d2d 100644
--- a/src/main/java/org/springframework/social/dropbox/connect/DropboxConnectionFactory.java
+++ b/src/main/java/org/springframework/social/dropbox/connect/DropboxConnectionFactory.java
@@ -1,15 +1,28 @@
package org.springframework.social.dropbox.connect;
import org.springframework.social.connect.support.OAuth1ConnectionFactory;
-import org.springframework.social.dropbox.api.DropboxApi;
+import org.springframework.social.dropbox.api.Dropbox;
/**
- * User: Bryce Fischer
- * Date: 5/17/11
- * Time: 11:38 AM
+ * Dropbox Connection Factory
+ *
+ * @author Bryce Fischer
+ * @author Robert Drysdale
*/
-public class DropboxConnectionFactory extends OAuth1ConnectionFactory {
- public DropboxConnectionFactory(String consumerKey, String consumerSecret) {
- super("dropbox", new DropboxServiceProvider(consumerKey, consumerSecret), new DropboxAdapter());
+public class DropboxConnectionFactory extends OAuth1ConnectionFactory {
+
+ /**
+ * Dropbox Connection Factory
+ *
+ * appFolder must align with how app is registered in Dropbox.
+ * App can be allowed access to only an app folder (default)
+ * or the whole of Dropbox
+ *
+ * @param appKey Registered key
+ * @param appSecret Registered
+ * @param appFolder Whether to use sandboxed app folder or access whole of Dropbox
+ */
+ public DropboxConnectionFactory(String appKey, String appSecret, boolean appFolder) {
+ super("dropbox", new DropboxServiceProvider(appKey, appSecret, appFolder), new DropboxAdapter());
}
}
diff --git a/src/main/java/org/springframework/social/dropbox/connect/DropboxServiceProvider.java b/src/main/java/org/springframework/social/dropbox/connect/DropboxServiceProvider.java
index 5cb5f83..8c34a0d 100644
--- a/src/main/java/org/springframework/social/dropbox/connect/DropboxServiceProvider.java
+++ b/src/main/java/org/springframework/social/dropbox/connect/DropboxServiceProvider.java
@@ -1,6 +1,6 @@
package org.springframework.social.dropbox.connect;
-import org.springframework.social.dropbox.api.DropboxApi;
+import org.springframework.social.dropbox.api.Dropbox;
import org.springframework.social.dropbox.api.impl.DropboxTemplate;
import org.springframework.social.oauth1.AbstractOAuth1ServiceProvider;
import org.springframework.social.oauth1.OAuth1Template;
@@ -11,18 +11,20 @@
* Date: 5/17/11
* Time: 11:29 AM
*/
-public class DropboxServiceProvider extends AbstractOAuth1ServiceProvider {
-
- public DropboxServiceProvider(String consumerKey, String consumerSecret) {
+public class DropboxServiceProvider extends AbstractOAuth1ServiceProvider {
+ private final boolean appFolder;
+
+ public DropboxServiceProvider(String consumerKey, String consumerSecret, boolean appFolder) {
super(consumerKey, consumerSecret, new OAuth1Template(consumerKey, consumerSecret,
"https://api.dropbox.com/1/oauth/request_token",
"https://www.dropbox.com/1/oauth/authorize",
"https://api.dropbox.com/1/oauth/access_token",
OAuth1Version.CORE_10));
+ this.appFolder = appFolder;
}
@Override
- public DropboxApi getApi(String accessToken, String secret) {
- return new DropboxTemplate(getConsumerKey(), getConsumerSecret(), accessToken, secret);
+ public Dropbox getApi(String accessToken, String secret) {
+ return new DropboxTemplate(getConsumerKey(), getConsumerSecret(), accessToken, secret, appFolder);
}
}
diff --git a/src/test/java/org/springframework/social/dropbox/api/impl/AbstractDropboxApiTest.java b/src/test/java/org/springframework/social/dropbox/api/impl/AbstractDropboxApiTest.java
index abd08a5..0396b07 100644
--- a/src/test/java/org/springframework/social/dropbox/api/impl/AbstractDropboxApiTest.java
+++ b/src/test/java/org/springframework/social/dropbox/api/impl/AbstractDropboxApiTest.java
@@ -1,5 +1,8 @@
package org.springframework.social.dropbox.api.impl;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
import org.junit.Before;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@@ -20,7 +23,7 @@ public abstract class AbstractDropboxApiTest {
@Before
public void setUp() throws Exception {
- dropbox = new DropboxTemplate("API_KEY", "API_SECRET", "ACCESS_TOKEN", "ACCESS_TOKEN_SECRET");
+ dropbox = new DropboxTemplate("API_KEY", "API_SECRET", "ACCESS_TOKEN", "ACCESS_TOKEN_SECRET", false);
mockServer = MockRestServiceServer.createServer(dropbox.getRestTemplate());
responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
@@ -29,4 +32,13 @@ public void setUp() throws Exception {
protected Resource jsonResource(String filename) {
return new ClassPathResource(filename + ".json");
}
+
+ protected Date fromDropboxDate(String date) {
+ try {
+ return new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").parse(date);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/src/test/java/org/springframework/social/dropbox/api/impl/DropboxTemplateTest.java b/src/test/java/org/springframework/social/dropbox/api/impl/DropboxTemplateTest.java
index 440faca..4c5935b 100644
--- a/src/test/java/org/springframework/social/dropbox/api/impl/DropboxTemplateTest.java
+++ b/src/test/java/org/springframework/social/dropbox/api/impl/DropboxTemplateTest.java
@@ -1,16 +1,26 @@
package org.springframework.social.dropbox.api.impl;
-import org.junit.Test;
-import org.springframework.social.dropbox.api.DropboxUserProfile;
-
-import java.math.BigInteger;
-
import static junit.framework.Assert.assertEquals;
import static org.springframework.http.HttpMethod.GET;
+import static org.springframework.http.HttpMethod.POST;
+import static org.springframework.http.HttpMethod.PUT;
import static org.springframework.social.test.client.RequestMatchers.method;
import static org.springframework.social.test.client.RequestMatchers.requestTo;
import static org.springframework.social.test.client.ResponseCreators.withResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.junit.Test;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.social.dropbox.api.DropboxFile;
+import org.springframework.social.dropbox.api.DropboxUserProfile;
+import org.springframework.social.dropbox.api.FileUrl;
+import org.springframework.social.dropbox.api.Metadata;
+
/**
* User: Bryce Fischer
* Date: 5/17/11
@@ -34,4 +44,285 @@ public void getUserProfileValid() throws Exception {
assertEquals(BigInteger.valueOf(44962990383L), profile.getSharedQuota());
assertEquals(BigInteger.valueOf(46970996076L), profile.getNormalQuota());
}
+
+ @Test
+ public void putFile() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.FILE_PUT_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "file.json")))
+ .andExpect(method(PUT))
+ .andRespond(withResponse(jsonResource("/file_put_metadata"), responseHeaders));
+
+ FileInputStream stream = new FileInputStream(jsonResource("metadata").getFile());
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ while(true) {
+ int b = stream.read();
+ if (b == -1) {
+ break;
+ }
+ bytes.write(b);
+ }
+
+ Metadata metadata = dropbox.putFile("file.json", bytes.toByteArray());
+ assertEquals("7702a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(12265, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 02 Dec 2011 11:27:27 +0000"), metadata.getModified());
+ assertEquals("/file.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ assertEquals("12KB", metadata.getSize());
+ }
+
+ @Test
+ public void copyFile() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.COPY_URL))
+ .andExpect(method(POST))
+ .andRespond(withResponse(jsonResource("/copy"), responseHeaders));
+
+ Metadata metadata = dropbox.copy("file.json", "file3.json");
+ assertEquals("8e02a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(12265, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 12:24:07 +0000"), metadata.getModified());
+ assertEquals("/file3.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ assertEquals("12KB", metadata.getSize());
+ }
+
+ @Test
+ public void moveFile() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.MOVE_URL))
+ .andExpect(method(POST))
+ .andRespond(withResponse(jsonResource("/file_moved"), responseHeaders));
+
+ Metadata metadata = dropbox.move("file.json", "file_moved.json");
+ assertEquals("9202a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(12265, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 14:39:42 +0000"), metadata.getModified());
+ assertEquals("/file_moved.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ assertEquals("12KB", metadata.getSize());
+ }
+
+ @Test
+ public void restoreFile() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.RESTORE_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "file3.json")
+ + "?rev=8e02a9405f"))
+ .andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/restored"), responseHeaders));
+
+ Metadata metadata = dropbox.restore("file3.json", "8e02a9405f");
+ assertEquals("9302a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(12265, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 14:48:58 +0000"), metadata.getModified());
+ assertEquals("/file3.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ assertEquals("12KB", metadata.getSize());
+ }
+
+ @Test
+ public void getMedia() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.MEDIA_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "file3.json")))
+ .andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/media"), responseHeaders));
+
+ FileUrl url = dropbox.getMedia("file3.json");
+ assertEquals("https://dl.dropbox.com/0/view/6rcp09bdfz1kxfv/file3.json", url.getUrl());
+ assertEquals(fromDropboxDate("Sun, 15 Jan 2012 15:24:47 +0000"), url.getExpires());
+ }
+
+ @Test
+ public void getShare() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.SHARES_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "file3.json")))
+ .andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/share"), responseHeaders));
+
+ FileUrl url = dropbox.getShare("file3.json");
+ assertEquals("http://db.tt/LnS1qL1q", url.getUrl());
+ assertEquals(fromDropboxDate("Sun, 15 Jan 2012 15:24:47 +0000"), url.getExpires());
+ }
+
+ @Test
+ public void searchFile() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.SEARCH_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "")
+ + "?query=json"))
+ .andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/search"), responseHeaders));
+
+ List list = dropbox.search("", "json");
+ assertEquals(3, list.size());
+ Metadata metadata = list.get(0);
+
+ assertEquals("8d02a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(12265, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 12:23:30 +0000"), metadata.getModified());
+ assertEquals("/file2.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ assertEquals("12KB", metadata.getSize());
+ }
+
+ @Test
+ public void createFolder() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.CREATE_FOLDER_URL))
+ .andExpect(method(POST))
+ .andRespond(withResponse(jsonResource("/create_folder"), responseHeaders));
+
+ Metadata metadata = dropbox.createFolder("test");
+ assertEquals("8f02a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(0, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 12:35:37 +0000"), metadata.getModified());
+ assertEquals("/test", metadata.getPath());
+ assertEquals(true, metadata.isDir());
+ assertEquals("folder", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("0 bytes", metadata.getSize());
+ }
+
+ @Test
+ public void delete() throws Exception {
+ mockServer
+ .expect(requestTo(DropboxTemplate.DELETE_URL))
+ .andExpect(method(POST))
+ .andRespond(withResponse(jsonResource("/delete"), responseHeaders));
+
+ Metadata metadata = dropbox.delete("file3.json");
+ assertEquals("9002a9405f", metadata.getRev());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(0, metadata.getBytes());
+ assertEquals(fromDropboxDate("Fri, 16 Dec 2011 12:57:00 +0000"), metadata.getModified());
+ assertEquals("/file3.json", metadata.getPath());
+ assertEquals(false, metadata.isDir());
+ assertEquals("page_white", metadata.getIcon());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("0 bytes", metadata.getSize());
+ assertEquals(true, metadata.isDeleted());
+ assertEquals("application/octet-stream", metadata.getMimeType());
+ }
+
+ @Test
+ public void getFile() throws Exception {
+
+ HttpHeaders h = new HttpHeaders();
+ h.setContentType(MediaType.APPLICATION_JSON);
+ h.setContentLength(1234);
+
+ mockServer
+ .expect(requestTo(DropboxTemplate.FILE_URL
+ .replaceFirst("\\{appFolderUrl\\}", "dropbox")
+ .replaceFirst("\\{path\\}", "Getting%20Started.pdf")))
+ .andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/metadata"), h));
+
+ DropboxFile file = dropbox.getFile("Getting Started.pdf");
+ byte[] bytes = file.getBytes();
+ assertEquals(1234, bytes.length);
+ }
+
+ @Test
+ public void getRevisions() throws Exception {
+ mockServer.expect(requestTo(DropboxTemplate.REVISIONS_URL.replaceFirst("\\{appFolderUrl\\}", "dropbox").replaceFirst("\\{path\\}", "file.json"))).andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/revisions"), responseHeaders));
+ List revisions = dropbox.getRevisions("file.json");
+
+ Metadata file = revisions.get(0);
+ assertEquals("7702a9405f", file.getRev());
+ assertEquals(false, file.isThumbExists());
+ assertEquals(12265, file.getBytes());
+ assertEquals(fromDropboxDate("Fri, 02 Dec 2011 11:27:27 +0000"), file.getModified());
+ assertEquals("/file.json", file.getPath());
+ assertEquals(false, file.isDir());
+ assertEquals("12KB", file.getSize());
+ assertEquals("dropbox", file.getRoot());
+ assertEquals("page_white", file.getIcon());
+ assertEquals("application/octet-stream", file.getMimeType());
+
+ file = revisions.get(1);
+ assertEquals("7602a9405f", file.getRev());
+ assertEquals(false, file.isThumbExists());
+ assertEquals(556035, file.getBytes());
+ assertEquals(fromDropboxDate("Fri, 02 Dec 2011 11:24:16 +0000"), file.getModified());
+ assertEquals("/file.json", file.getPath());
+ assertEquals(false, file.isDir());
+ assertEquals("543KB", file.getSize());
+ assertEquals("dropbox", file.getRoot());
+ assertEquals("page_white", file.getIcon());
+ assertEquals("application/octet-stream", file.getMimeType());
+ }
+
+ @Test
+ public void getMetadata() throws Exception {
+ mockServer.expect(requestTo(DropboxTemplate.METADATA_URL.replaceFirst("\\{appFolderUrl\\}", "dropbox").replaceFirst("\\{path\\}", ""))).andExpect(method(GET))
+ .andRespond(withResponse(jsonResource("/metadata"), responseHeaders));
+ Metadata metadata = dropbox.getItemMetadata("");
+
+ assertEquals("0881bfe7f09e0fe856cf9a27000ac00c", metadata.getHash());
+ assertEquals(false, metadata.isThumbExists());
+ assertEquals(0, metadata.getBytes());
+ assertEquals("/", metadata.getPath());
+ assertEquals(true, metadata.isDir());
+ assertEquals("0 bytes", metadata.getSize());
+ assertEquals("dropbox", metadata.getRoot());
+ assertEquals("folder", metadata.getIcon());
+
+ List contents = metadata.getContents();
+ assertEquals(9, contents.size());
+
+ Metadata folder = contents.get(0);
+ assertEquals("1202a9405f", folder.getRev());
+ assertEquals(false, folder.isThumbExists());
+ assertEquals(0, folder.getBytes());
+ assertEquals(fromDropboxDate("Wed, 08 Jun 2011 20:58:29 +0000"), folder.getModified());
+ assertEquals("/cv", folder.getPath());
+ assertEquals(true, folder.isDir());
+ assertEquals("0 bytes", folder.getSize());
+ assertEquals("dropbox", folder.getRoot());
+ assertEquals("folder", folder.getIcon());
+
+ Metadata file = contents.get(1);
+ assertEquals("702a9405f", file.getRev());
+ assertEquals(false, file.isThumbExists());
+ assertEquals(230783, file.getBytes());
+ assertEquals(fromDropboxDate("Thu, 05 May 2011 14:28:24 +0000"), file.getModified());
+ assertEquals("/Getting Started.pdf", file.getPath());
+ assertEquals(false, file.isDir());
+ assertEquals("225.4KB", file.getSize());
+ assertEquals("dropbox", file.getRoot());
+ assertEquals("page_white_acrobat", file.getIcon());
+ assertEquals("application/pdf", file.getMimeType());
+ }
}
diff --git a/src/test/java/org/springframework/social/dropbox/connect/DropboxAdapterTest.java b/src/test/java/org/springframework/social/dropbox/connect/DropboxAdapterTest.java
index 09d3568..27e20cf 100644
--- a/src/test/java/org/springframework/social/dropbox/connect/DropboxAdapterTest.java
+++ b/src/test/java/org/springframework/social/dropbox/connect/DropboxAdapterTest.java
@@ -3,7 +3,7 @@
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.social.connect.UserProfile;
-import org.springframework.social.dropbox.api.DropboxApi;
+import org.springframework.social.dropbox.api.Dropbox;
import org.springframework.social.dropbox.api.DropboxUserProfile;
import java.math.BigInteger;
@@ -17,7 +17,7 @@
*/
public class DropboxAdapterTest {
private DropboxAdapter adapter = new DropboxAdapter();
- private DropboxApi dropboxApi = Mockito.mock(DropboxApi.class);
+ private Dropbox dropboxApi = Mockito.mock(Dropbox.class);
@Test
public void fetchProfile() throws Exception {
diff --git a/src/test/resources/copy.json b/src/test/resources/copy.json
new file mode 100644
index 0000000..c9a765e
--- /dev/null
+++ b/src/test/resources/copy.json
@@ -0,0 +1,13 @@
+{
+ "revision":142,
+ "rev":"8e02a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 12:24:07 +0000",
+ "path":"/file3.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+}
\ No newline at end of file
diff --git a/src/test/resources/create_folder.json b/src/test/resources/create_folder.json
new file mode 100644
index 0000000..1fdeaf2
--- /dev/null
+++ b/src/test/resources/create_folder.json
@@ -0,0 +1,12 @@
+{
+ "revision":143,
+ "rev":"8f02a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Fri, 16 Dec 2011 12:35:37 +0000",
+ "path":"/test",
+ "is_dir":true,
+ "icon":"folder",
+ "root":"dropbox",
+ "size":"0 bytes"
+}
\ No newline at end of file
diff --git a/src/test/resources/delete.json b/src/test/resources/delete.json
new file mode 100644
index 0000000..af8fa2b
--- /dev/null
+++ b/src/test/resources/delete.json
@@ -0,0 +1,14 @@
+{
+ "is_deleted":true,
+ "revision":144,
+ "rev":"9002a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Fri, 16 Dec 2011 12:57:00 +0000",
+ "path":"/file3.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"0 bytes"
+}
\ No newline at end of file
diff --git a/src/test/resources/file_moved.json b/src/test/resources/file_moved.json
new file mode 100644
index 0000000..f9005ae
--- /dev/null
+++ b/src/test/resources/file_moved.json
@@ -0,0 +1,13 @@
+{
+ "revision":146,
+ "rev":"9202a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 14:39:42 +0000",
+ "path":"/file_moved.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+}
\ No newline at end of file
diff --git a/src/test/resources/file_put_metadata.json b/src/test/resources/file_put_metadata.json
new file mode 100644
index 0000000..1578076
--- /dev/null
+++ b/src/test/resources/file_put_metadata.json
@@ -0,0 +1,13 @@
+{
+ "revision":119,
+ "rev":"7702a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 02 Dec 2011 11:27:27 +0000",
+ "path":"/file.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+}
\ No newline at end of file
diff --git a/src/test/resources/media.json b/src/test/resources/media.json
new file mode 100644
index 0000000..1e2e81a
--- /dev/null
+++ b/src/test/resources/media.json
@@ -0,0 +1,4 @@
+{
+ "url": "https://dl.dropbox.com/0/view/6rcp09bdfz1kxfv/file3.json",
+ "expires": "Sun, 15 Jan 2012 15:24:47 +0000"
+}
diff --git a/src/test/resources/metadata.json b/src/test/resources/metadata.json
new file mode 100644
index 0000000..96ccdbd
--- /dev/null
+++ b/src/test/resources/metadata.json
@@ -0,0 +1,122 @@
+{
+ "hash":"0881bfe7f09e0fe856cf9a27000ac00c",
+ "thumb_exists":false,
+ "bytes":0,
+ "path":"/",
+ "is_dir":true,
+ "size":"0 bytes",
+ "root":"dropbox",
+ "contents":[
+ {
+ "revision":18,
+ "rev":"1202a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Wed, 08 Jun 2011 20:58:29 +0000",
+ "path":"/cv",
+ "is_dir":true,
+ "icon":"folder",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":7,
+ "rev":"702a9405f",
+ "thumb_exists":false,
+ "bytes":230783,
+ "modified":"Thu, 05 May 2011 14:28:24 +0000",
+ "path":"/Getting Started.pdf",
+ "is_dir":false,
+ "icon":"page_white_acrobat",
+ "root":"dropbox",
+ "mime_type":"application/pdf",
+ "size":"225.4KB"
+ },
+ {
+ "revision":93,
+ "rev":"5d02a9405f",
+ "thumb_exists":false,
+ "bytes":729629,
+ "modified":"Sun, 20 Nov 2011 21:33:54 +0000",
+ "path":"/Test.xlsx",
+ "is_dir":false,
+ "icon":"page_white_excel",
+ "root":"dropbox",
+ "mime_type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "size":"712.5KB"
+ },
+ {
+ "revision":43,
+ "rev":"2b02a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Thu, 21 Jul 2011 23:25:36 +0000",
+ "path":"/stuff",
+ "is_dir":true,
+ "icon":"folder_user",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":112,
+ "rev":"7002a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Tue, 29 Nov 2011 14:29:51 +0000",
+ "path":"/test",
+ "is_dir":true,
+ "icon":"folder",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":41,
+ "rev":"2902a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Wed, 20 Jul 2011 10:33:52 +0000",
+ "path":"/project",
+ "is_dir":true,
+ "icon":"folder_user",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":14,
+ "rev":"e02a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Fri, 03 Jun 2011 16:55:58 +0000",
+ "path":"/Photos",
+ "is_dir":true,
+ "icon":"folder_photos",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":15,
+ "rev":"f02a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Fri, 03 Jun 2011 16:55:58 +0000",
+ "path":"/Public",
+ "is_dir":true,
+ "icon":"folder_public",
+ "root":"dropbox",
+ "size":"0 bytes"
+ },
+ {
+ "revision":33,
+ "rev":"2102a9405f",
+ "thumb_exists":false,
+ "bytes":0,
+ "modified":"Thu, 16 Jun 2011 14:04:14 +0000",
+ "path":"/random",
+ "is_dir":true,
+ "icon":"folder",
+ "root":"dropbox",
+ "size":"0 bytes"
+ }
+ ],
+ "icon":"folder"
+}
\ No newline at end of file
diff --git a/src/test/resources/restored.json b/src/test/resources/restored.json
new file mode 100644
index 0000000..e500d02
--- /dev/null
+++ b/src/test/resources/restored.json
@@ -0,0 +1,13 @@
+{
+ "revision":147,
+ "rev":"9302a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 14:48:58 +0000",
+ "path":"/file3.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+}
\ No newline at end of file
diff --git a/src/test/resources/revisions.json b/src/test/resources/revisions.json
new file mode 100644
index 0000000..8c3417d
--- /dev/null
+++ b/src/test/resources/revisions.json
@@ -0,0 +1,28 @@
+[
+ {
+ "revision":119,
+ "rev":"7702a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 02 Dec 2011 11:27:27 +0000",
+ "path":"/file.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+ },
+ {
+ "revision":118,
+ "rev":"7602a9405f",
+ "thumb_exists":false,
+ "bytes":556035,
+ "modified":"Fri, 02 Dec 2011 11:24:16 +0000",
+ "path":"/file.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"543KB"
+ }
+]
\ No newline at end of file
diff --git a/src/test/resources/search.json b/src/test/resources/search.json
new file mode 100644
index 0000000..03196bc
--- /dev/null
+++ b/src/test/resources/search.json
@@ -0,0 +1,41 @@
+[
+ {
+ "revision":141,
+ "rev":"8d02a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 12:23:30 +0000",
+ "path":"/file2.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+ },
+ {
+ "revision":146,
+ "rev":"9202a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 14:39:42 +0000",
+ "path":"/file_moved.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+ },
+ {
+ "revision":147,
+ "rev":"9302a9405f",
+ "thumb_exists":false,
+ "bytes":12265,
+ "modified":"Fri, 16 Dec 2011 14:48:58 +0000",
+ "path":"/file3.json",
+ "is_dir":false,
+ "icon":"page_white",
+ "root":"dropbox",
+ "mime_type":"application/octet-stream",
+ "size":"12KB"
+ }
+]
\ No newline at end of file
diff --git a/src/test/resources/share.json b/src/test/resources/share.json
new file mode 100644
index 0000000..65832e4
--- /dev/null
+++ b/src/test/resources/share.json
@@ -0,0 +1,4 @@
+{
+ "url": "http://db.tt/LnS1qL1q",
+ "expires": "Sun, 15 Jan 2012 15:24:47 +0000"
+}
\ No newline at end of file