diff --git a/README.md b/README.md index 9dfe53c2e..2f008218f 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,12 @@ Then just invoke `gradle runAccessAsAppUser` to run the AccessAsAppUser example! Note: The JCE bundled with oracle JRE supports keys upto 128 bit length only. To use larger cryptographic keys, install [JCE Unlimited Strength Jurisdiction Policy Files](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html). +#### BatchRequestExample + +There migt be cases where you want a bunch of requests to be executed as a single request. This example will show you how to do that + +Just invoke `gradle runBatchExample` to run the BatchRequestExample example! + Building -------- diff --git a/build.gradle b/build.gradle index 8c72c1335..ce89b85ca 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,15 @@ repositories { mavenCentral() } +sourceSets { + example { + java { + compileClasspath += main.output + runtimeClasspath += main.runtimeClasspath + } + } +} + dependencies { compile 'com.eclipsesource.minimal-json:minimal-json:0.9.1' compile 'org.bitbucket.b_c:jose4j:0.4.4' @@ -26,6 +35,7 @@ dependencies { testCompile 'org.mockito:mockito-core:1.9.5' testCompile 'org.slf4j:slf4j-api:1.7.7' testCompile 'org.slf4j:slf4j-nop:1.7.7' + exampleCompile 'com.eclipsesource.minimal-json:minimal-json:0.9.1' } compileJava { @@ -52,15 +62,6 @@ javadoc { checkstyleMain { classpath += configurations.compile } checkstyleTest { classpath += configurations.compile } -sourceSets { - example { - java { - compileClasspath += main.output - runtimeClasspath += main.runtimeClasspath - } - } -} - task runExample(type: JavaExec, dependsOn: 'exampleClasses') { classpath = sourceSets.example.runtimeClasspath main = 'com.box.sdk.example.Main' @@ -76,6 +77,11 @@ task runAccessAsAppUser(type: JavaExec, dependsOn: 'exampleClasses') { main = 'com.box.sdk.example.AccessAsAppUser' } +task runBatchExample(type: JavaExec, dependsOn: 'exampleClasses') { + classpath = sourceSets.example.runtimeClasspath + main = 'com.box.sdk.example.BatchRequestExample' +} + task javadocJar(type: Jar) { classifier = 'javadoc' from javadoc diff --git a/config/checkstyle/suppressions.xml b/config/checkstyle/suppressions.xml index 92ee3f784..58d445bbd 100644 --- a/config/checkstyle/suppressions.xml +++ b/config/checkstyle/suppressions.xml @@ -11,4 +11,8 @@ files="example.*\.java"/> + + diff --git a/src/example/java/com/box/sdk/example/BatchRequestExample.java b/src/example/java/com/box/sdk/example/BatchRequestExample.java new file mode 100644 index 000000000..e375c39ab --- /dev/null +++ b/src/example/java/com/box/sdk/example/BatchRequestExample.java @@ -0,0 +1,87 @@ +package com.box.sdk.example; + +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.box.sdk.BatchAPIRequest; +import com.box.sdk.BoxAPIRequest; +import com.box.sdk.BoxAPIResponse; +import com.box.sdk.BoxConfig; +import com.box.sdk.BoxDeveloperEditionAPIConnection; +import com.box.sdk.BoxFolder; +import com.box.sdk.BoxJSONRequest; +import com.box.sdk.BoxJSONResponse; +import com.box.sdk.BoxUser; +import com.box.sdk.IAccessTokenCache; +import com.box.sdk.InMemoryLRUAccessTokenCache; +import com.box.sdk.http.HttpMethod; + +/** + * + */ +public final class BatchRequestExample { + + private static final int MAX_CACHE_ENTRIES = 100; + private static final String APP_USER_NAME = "BATCH-TEST-APP-USER-NAME"; + + private BatchRequestExample() { } + + public static void main(String[] args) throws IOException { + // Turn off logging to prevent polluting the output. + Logger.getLogger("com.box.sdk").setLevel(Level.OFF); + + + //It is a best practice to use an access token cache to prevent unneeded requests to Box for access tokens. + //For production applications it is recommended to use a distributed cache like Memcached or Redis, and to + //implement IAccessTokenCache to store and retrieve access tokens appropriately for your environment. + IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES); + + Reader reader = new FileReader("src/example/config/config.json"); + BoxConfig boxConfig = BoxConfig.readFrom(reader); + + BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection( + boxConfig, accessTokenCache); + + List requests = new ArrayList(); + + //Get current user request + URL getMeURL = BoxUser.GET_ME_URL.build(api.getBaseURL()); + BoxAPIRequest getMeRequest = new BoxAPIRequest(getMeURL, HttpMethod.GET); + requests.add(getMeRequest); + + //Create App User Request + URL createUserURL = BoxUser.USERS_URL_TEMPLATE.build(api.getBaseURL()); + BoxJSONRequest createAppUserRequest = new BoxJSONRequest(createUserURL, HttpMethod.POST); + createAppUserRequest.setBody("{\"name\":\"" + APP_USER_NAME + "\",\"is_platform_access_only\":true}"); + requests.add(createAppUserRequest); + + //Get Root Folder Request + URL getRootFolderURL = BoxFolder.FOLDER_INFO_URL_TEMPLATE.build(api.getBaseURL(), 0); + BoxAPIRequest getRootFolderRequest = new BoxAPIRequest(getRootFolderURL, HttpMethod.GET); + requests.add(getRootFolderRequest); + + BatchAPIRequest batchRequest = new BatchAPIRequest(api); + List responses = batchRequest.execute(requests); + + System.out.println("GET ME RESPONSE:"); + System.out.println("Response Code: " + responses.get(0).getResponseCode()); + System.out.println("Response: " + ((BoxJSONResponse) responses.get(1)).getJSON()); + + System.out.println("CREATE APP USER RESPONSE:"); + System.out.println("Response Code: " + responses.get(1).getResponseCode()); + System.out.println("Response: " + ((BoxJSONResponse) responses.get(1)).getJSON()); + + System.out.println("GET ROOT FOLDER RESPONSE:"); + System.out.println("Response Code: " + responses.get(2).getResponseCode()); + BoxJSONResponse rootFolderResponse = (BoxJSONResponse) responses.get(1); + BoxFolder.Info rootFolderInfo = new BoxFolder(api, rootFolderResponse.getJsonObject().get("id").asString()) + .new Info(rootFolderResponse.getJsonObject()); + System.out.println("Root Folder Created At: " + rootFolderInfo.getCreatedAt()); + } +} diff --git a/src/main/java/com/box/sdk/BatchAPIRequest.java b/src/main/java/com/box/sdk/BatchAPIRequest.java new file mode 100644 index 000000000..88871bcfe --- /dev/null +++ b/src/main/java/com/box/sdk/BatchAPIRequest.java @@ -0,0 +1,126 @@ +package com.box.sdk; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import com.box.sdk.http.HttpHeaders; +import com.box.sdk.http.HttpMethod; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +/** + * Used to make a bunch of HTTP Requests as a batch. Currently the number of requests that can be batched at once + * is capped at 20 by the API layer. Also there are certain requests which cannot be performed + * by Batch API. Check API documentation for more information. + * + *

The request itself is a BoxJSONRequest but extends it to provide additional functionality for aggregating + * a bunch of requests and responding with multiple responses as if the requests were called individually

+ */ +public class BatchAPIRequest extends BoxJSONRequest { + /** + * Batch URL Template. + */ + public static final URLTemplate BATCH_URL_TEMPLATE = new URLTemplate("batch"); + private final BoxAPIConnection api; + + /** + * Constructs an authenticated BatchRequest using a provided BoxAPIConnection. + * @param api an API connection for authenticating the request. + */ + public BatchAPIRequest(BoxAPIConnection api) { + super(api, BATCH_URL_TEMPLATE.build(api.getBaseURL()), HttpMethod.GET); + this.api = api; + } + + /** + * Execute a set of API calls as batch request. + * @param requests list of api requests that has to be executed in batch. + * @return list of BoxAPIResponses + */ + public List execute(List requests) { + this.prepareRequest(requests); + BoxJSONResponse batchResponse = (BoxJSONResponse) send(); + return this.parseResponse(batchResponse); + } + + /** + * Prepare a batch api request using list of individual reuests. + * @param requests list of api requests that has to be executed in batch. + */ + protected void prepareRequest(List requests) { + JsonObject body = new JsonObject(); + JsonArray requestsJSONArray = new JsonArray(); + for (BoxAPIRequest request: requests) { + JsonObject batchRequest = new JsonObject(); + batchRequest.add("method", request.getMethod()); + batchRequest.add("relative_url", request.getUrl().toString().substring(this.api.getBaseURL().length() - 1)); + //If the actual request has a JSON body then add it to vatch request + if (request instanceof BoxJSONRequest) { + BoxJSONRequest jsonRequest = (BoxJSONRequest) request; + batchRequest.add("body", jsonRequest.getBodyAsJsonObject()); + } + //Add any headers that are in the request, except Authorization + if (request.getHeaders() != null) { + JsonObject batchRequestHeaders = new JsonObject(); + for (RequestHeader header: request.getHeaders()) { + if (header.getKey() != null && !header.getKey().isEmpty() + && HttpHeaders.AUTHORIZATION.equals(header.getKey())) { + batchRequestHeaders.add(header.getKey(), header.getValue()); + } + } + batchRequest.add("headers", batchRequestHeaders); + } + + //Add the request to array + requestsJSONArray.add(batchRequest); + } + //Add the requests array to body + body.add("requests", requestsJSONArray); + super.setBody(body); + } + + /** + * Parses btch api response to create a list of BoxAPIResponse objects. + * @param batchResponse response of a batch api request + * @return list of BoxAPIResponses + */ + protected List parseResponse(BoxJSONResponse batchResponse) { + JsonObject responseJSON = JsonObject.readFrom(batchResponse.getJSON()); + List responses = new ArrayList(); + Iterator responseIterator = responseJSON.get("responses").asArray().iterator(); + while (responseIterator.hasNext()) { + JsonObject jsonResponse = responseIterator.next().asObject(); + BoxAPIResponse response = null; + + //Gather headers + Map responseHeaders = new HashMap(); + + if (jsonResponse.get("headers") != null) { + JsonObject batchResponseHeadersObject = jsonResponse.get("headers").asObject(); + for (JsonObject.Member member : batchResponseHeadersObject) { + String headerName = member.getName(); + String headerValue = member.getValue().asString(); + responseHeaders.put(headerName, headerValue); + } + } + + // Construct a BoxAPIResponse when response is null, or a BoxJSONResponse when there's a response + // (not anticipating any other response as per current APIs. + // Ideally we should do it based on response header) + if (jsonResponse.get("response") == null) { + response = + new BoxAPIResponse(jsonResponse.get("status").asInt(), responseHeaders); + } else { + response = + new BoxJSONResponse(jsonResponse.get("status").asInt(), responseHeaders, + jsonResponse.get("response").asObject()); + } + responses.add(response); + } + return responses; + } +} diff --git a/src/main/java/com/box/sdk/BoxAPIRequest.java b/src/main/java/com/box/sdk/BoxAPIRequest.java index e921bb50f..9f2121928 100644 --- a/src/main/java/com/box/sdk/BoxAPIRequest.java +++ b/src/main/java/com/box/sdk/BoxAPIRequest.java @@ -14,6 +14,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import com.box.sdk.http.HttpHeaders; import com.box.sdk.http.HttpMethod; /** @@ -81,11 +82,20 @@ public BoxAPIRequest(BoxAPIConnection api, URL url, String method) { /** * Constructs an authenticated BoxAPIRequest using a provided BoxAPIConnection. * @param api an API connection for authenticating the request. - * @param uploadPartEndpoint the URL of the request. + * @param url the URL of the request. * @param method the HTTP method of the request. */ - public BoxAPIRequest(BoxAPIConnection api, URL uploadPartEndpoint, HttpMethod method) { - this(api, uploadPartEndpoint, method.name()); + public BoxAPIRequest(BoxAPIConnection api, URL url, HttpMethod method) { + this(api, url, method.name()); + } + + /** + * Constructs an request, using URL and HttpMethod. + * @param url the URL of the request. + * @param method the HTTP method of the request. + */ + public BoxAPIRequest(URL url, HttpMethod method) { + this(url, method.name()); } /** @@ -182,6 +192,23 @@ public URL getUrl() { return this.url; } + /** + * Gets the http method from the request. + * + * @return http method + */ + public String getMethod() { + return this.method; + } + + /** + * Get headers as list of RequestHeader objects. + * @return headers as list of RequestHeader objects + */ + protected List getHeaders() { + return this.headers; + } + /** * Sends this request and returns a BoxAPIResponse containing the server's response. * @@ -377,7 +404,7 @@ private BoxAPIResponse trySend(ProgressListener listener) { if (this.api != null) { if (this.shouldAuthenticate) { - connection.addRequestProperty("Authorization", "Bearer " + this.api.lockAccessToken()); + connection.addRequestProperty(HttpHeaders.AUTHORIZATION, "Bearer " + this.api.lockAccessToken()); } connection.setRequestProperty("User-Agent", this.api.getUserAgent()); if (this.api.getProxy() != null) { @@ -533,19 +560,35 @@ private static boolean isResponseRedirect(int responseCode) { return (responseCode == 301 || responseCode == 302); } - private final class RequestHeader { + /** + * Class for mapping a request header and value. + */ + public final class RequestHeader { private final String key; private final String value; + /** + * Construct a request header from header key and value. + * @param key header name + * @param value header value + */ public RequestHeader(String key, String value) { this.key = key; this.value = value; } + /** + * Get header key. + * @return http header name + */ public String getKey() { return this.key; } + /** + * Get header value. + * @return http header value + */ public String getValue() { return this.value; } diff --git a/src/main/java/com/box/sdk/BoxAPIResponse.java b/src/main/java/com/box/sdk/BoxAPIResponse.java index 424ae94b5..c136aa4f9 100644 --- a/src/main/java/com/box/sdk/BoxAPIResponse.java +++ b/src/main/java/com/box/sdk/BoxAPIResponse.java @@ -27,6 +27,8 @@ public class BoxAPIResponse { private static final int BUFFER_SIZE = 8192; private final HttpURLConnection connection; + //Batch API Response will have headers in response body + private final Map headers; private int responseCode; private String bodyString; @@ -48,6 +50,18 @@ public class BoxAPIResponse { */ public BoxAPIResponse() { this.connection = null; + this.headers = null; + } + + /** + * Constructs a BoxAPIResponse with a http response code and response headers. + * @param responseCode http response code + * @param headers map of headers + */ + public BoxAPIResponse(int responseCode, Map headers) { + this.connection = null; + this.responseCode = responseCode; + this.headers = headers; } /** @@ -56,6 +70,7 @@ public BoxAPIResponse() { */ public BoxAPIResponse(HttpURLConnection connection) { this.connection = connection; + this.headers = null; this.inputStream = null; try { @@ -95,7 +110,16 @@ public long getContentLength() { * @return value of the header. */ public String getHeaderField(String fieldName) { - return this.connection.getHeaderField(fieldName); + // headers map is null for all regular response calls except when made as a batch request + if (this.headers == null) { + if (this.connection != null) { + return this.connection.getHeaderField(fieldName); + } else { + return null; + } + } else { + return this.headers.get(fieldName); + } } /** diff --git a/src/main/java/com/box/sdk/BoxCollaboration.java b/src/main/java/com/box/sdk/BoxCollaboration.java index 0fa86e36c..1f008d1fc 100644 --- a/src/main/java/com/box/sdk/BoxCollaboration.java +++ b/src/main/java/com/box/sdk/BoxCollaboration.java @@ -20,10 +20,22 @@ */ @BoxResourceType("collaboration") public class BoxCollaboration extends BoxResource { - private static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("collaborations"); - private static final URLTemplate PENDING_COLLABORATIONS_URL = new URLTemplate("collaborations?status=pending"); - private static final URLTemplate COLLABORATION_URL_TEMPLATE = new URLTemplate("collaborations/%s"); - private static final URLTemplate GET_ALL_FILE_COLLABORATIONS_URL = new URLTemplate("files/%s/collaborations/"); + /** + * Collaborations URL Template. + */ + public static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("collaborations"); + /** + * Pending Collaborations URL. + */ + public static final URLTemplate PENDING_COLLABORATIONS_URL = new URLTemplate("collaborations?status=pending"); + /** + * Collaboration URL Template. + */ + public static final URLTemplate COLLABORATION_URL_TEMPLATE = new URLTemplate("collaborations/%s"); + /** + * Get All File Collaboations URL. + */ + public static final URLTemplate GET_ALL_FILE_COLLABORATIONS_URL = new URLTemplate("files/%s/collaborations/"); /** * Constructs a BoxCollaboration for a collaboration with a given ID. diff --git a/src/main/java/com/box/sdk/BoxCollection.java b/src/main/java/com/box/sdk/BoxCollection.java index 08cd23294..482625532 100644 --- a/src/main/java/com/box/sdk/BoxCollection.java +++ b/src/main/java/com/box/sdk/BoxCollection.java @@ -18,8 +18,14 @@ @BoxResourceType("collection") public class BoxCollection extends BoxResource implements Iterable { - private static final URLTemplate GET_COLLECTIONS_URL_TEMPLATE = new URLTemplate("collections/"); - private static final URLTemplate GET_COLLECTION_ITEMS_URL = new URLTemplate("collections/%s/items/"); + /** + * Get Collections URL Template. + */ + public static final URLTemplate GET_COLLECTIONS_URL_TEMPLATE = new URLTemplate("collections/"); + /** + * Get Collection Items URL Template. + */ + public static final URLTemplate GET_COLLECTION_ITEMS_URL = new URLTemplate("collections/%s/items/"); /** * Constructs a BoxCollection for a collection with a given ID. diff --git a/src/main/java/com/box/sdk/BoxComment.java b/src/main/java/com/box/sdk/BoxComment.java index c72475ec3..ab7b8ae8b 100644 --- a/src/main/java/com/box/sdk/BoxComment.java +++ b/src/main/java/com/box/sdk/BoxComment.java @@ -18,9 +18,17 @@ */ @BoxResourceType("comment") public class BoxComment extends BoxResource { + + /** + * Add Comment URL Template. + */ + public static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); + /** + * Comment URL Template. + */ + public static final URLTemplate COMMENT_URL_TEMPLATE = new URLTemplate("comments/%s"); + private static final Pattern MENTION_REGEX = Pattern.compile("@\\[.+:.+\\]"); - private static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); - private static final URLTemplate COMMENT_URL_TEMPLATE = new URLTemplate("comments/%s"); /** * Constructs a BoxComment for a comment with a given ID. diff --git a/src/main/java/com/box/sdk/BoxDevicePin.java b/src/main/java/com/box/sdk/BoxDevicePin.java index 27184be06..4eaf94eef 100644 --- a/src/main/java/com/box/sdk/BoxDevicePin.java +++ b/src/main/java/com/box/sdk/BoxDevicePin.java @@ -20,12 +20,12 @@ public class BoxDevicePin extends BoxResource { /** * The URL template used for operation with the device pin. */ - private static final URLTemplate DEVICE_PIN_URL_TEMPLATE = new URLTemplate("device_pinners/%s"); + public static final URLTemplate DEVICE_PIN_URL_TEMPLATE = new URLTemplate("device_pinners/%s"); /** * The URL template used to get all the device pins within a given enterprise. */ - private static final URLTemplate ENTERPRISE_DEVICE_PINS_TEMPLATE = new URLTemplate("enterprises/%s/device_pinners"); + public static final URLTemplate ENTERPRISE_DEVICE_PINS_TEMPLATE = new URLTemplate("enterprises/%s/device_pinners"); /** * Default limit of the device info entries per one response page. diff --git a/src/main/java/com/box/sdk/BoxFile.java b/src/main/java/com/box/sdk/BoxFile.java index 14c5797c0..7d549696c 100644 --- a/src/main/java/com/box/sdk/BoxFile.java +++ b/src/main/java/com/box/sdk/BoxFile.java @@ -55,25 +55,71 @@ public enum ThumbnailFileType { JPG } - private static final URLTemplate FILE_URL_TEMPLATE = new URLTemplate("files/%s"); - private static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content"); - private static final URLTemplate VERSIONS_URL_TEMPLATE = new URLTemplate("files/%s/versions"); - private static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("files/%s/copy"); - private static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); - private static final URLTemplate GET_COMMENTS_URL_TEMPLATE = new URLTemplate("files/%s/comments"); - private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("files/%s/metadata/%s/%s"); - private static final URLTemplate ADD_TASK_URL_TEMPLATE = new URLTemplate("tasks"); - private static final URLTemplate GET_TASKS_URL_TEMPLATE = new URLTemplate("files/%s/tasks"); - private static final URLTemplate GET_THUMBNAIL_PNG_TEMPLATE = new URLTemplate("files/%s/thumbnail.png"); - private static final URLTemplate GET_THUMBNAIL_JPG_TEMPLATE = new URLTemplate("files/%s/thumbnail.jpg"); - private static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/%s/upload_sessions"); - private static final URLTemplate UPLOAD_SESSION_STATUS_URL_TEMPLATE = new URLTemplate( + /** + * File URL Template. + */ + public static final URLTemplate FILE_URL_TEMPLATE = new URLTemplate("files/%s"); + /** + * Content URL Template. + */ + public static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content"); + /** + * Versions URL Template. + */ + public static final URLTemplate VERSIONS_URL_TEMPLATE = new URLTemplate("files/%s/versions"); + /** + * Copy URL Template. + */ + public static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("files/%s/copy"); + /** + * Add Comment URL Template. + */ + public static final URLTemplate ADD_COMMENT_URL_TEMPLATE = new URLTemplate("comments"); + /** + * Get Comments URL Template. + */ + public static final URLTemplate GET_COMMENTS_URL_TEMPLATE = new URLTemplate("files/%s/comments"); + /** + * Metadata URL Template. + */ + public static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("files/%s/metadata/%s/%s"); + /** + * Add Task URL Template. + */ + public static final URLTemplate ADD_TASK_URL_TEMPLATE = new URLTemplate("tasks"); + /** + * Get Tasks URL Template. + */ + public static final URLTemplate GET_TASKS_URL_TEMPLATE = new URLTemplate("files/%s/tasks"); + /** + * Get Thumbnail PNG Template. + */ + public static final URLTemplate GET_THUMBNAIL_PNG_TEMPLATE = new URLTemplate("files/%s/thumbnail.png"); + /** + * Get Thumbnail JPG Template. + */ + public static final URLTemplate GET_THUMBNAIL_JPG_TEMPLATE = new URLTemplate("files/%s/thumbnail.jpg"); + /** + * Upload Session URL Template. + */ + public static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/%s/upload_sessions"); + /** + * Upload Session Status URL Template. + */ + public static final URLTemplate UPLOAD_SESSION_STATUS_URL_TEMPLATE = new URLTemplate( "files/upload_sessions/%s/status"); - private static final URLTemplate ABORT_UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions/%s"); - - private static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); - private static final URLTemplate GET_ALL_FILE_COLLABORATIONS_URL = new URLTemplate("files/%s/collaborations"); - + /** + * Abort Upload Session URL Template. + */ + public static final URLTemplate ABORT_UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions/%s"); + /** + * Add Collaborations URL Template. + */ + public static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); + /** + * Get All File Collaborations URL Template. + */ + public static final URLTemplate GET_ALL_FILE_COLLABORATIONS_URL = new URLTemplate("files/%s/collaborations"); private static final int BUFFER_SIZE = 8192; private static final int GET_COLLABORATORS_PAGE_SIZE = 1000; diff --git a/src/main/java/com/box/sdk/BoxFileVersion.java b/src/main/java/com/box/sdk/BoxFileVersion.java index e5792ea00..865490399 100644 --- a/src/main/java/com/box/sdk/BoxFileVersion.java +++ b/src/main/java/com/box/sdk/BoxFileVersion.java @@ -15,8 +15,14 @@ */ @BoxResourceType("file_version") public class BoxFileVersion extends BoxResource { - private static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content?version=%s"); - private static final URLTemplate VERSION_URL_TEMPLATE = new URLTemplate("files/%s/versions/%s"); + /** + * Content URL Template. + */ + public static final URLTemplate CONTENT_URL_TEMPLATE = new URLTemplate("files/%s/content?version=%s"); + /** + * Version URL Template. + */ + public static final URLTemplate VERSION_URL_TEMPLATE = new URLTemplate("files/%s/versions/%s"); private static final int BUFFER_SIZE = 8192; private String fileID; diff --git a/src/main/java/com/box/sdk/BoxFileVersionLegalHold.java b/src/main/java/com/box/sdk/BoxFileVersionLegalHold.java index 4afd48cd3..6766fa05f 100644 --- a/src/main/java/com/box/sdk/BoxFileVersionLegalHold.java +++ b/src/main/java/com/box/sdk/BoxFileVersionLegalHold.java @@ -21,7 +21,7 @@ public class BoxFileVersionLegalHold extends BoxResource { * The URL template used for operation with file version legal hold with given ID. * @see #getInfo(String...) */ - private static final URLTemplate FILE_VERSION_HOLD_URL_TEMPLATE = new URLTemplate("file_version_legal_holds/%s"); + public static final URLTemplate FILE_VERSION_HOLD_URL_TEMPLATE = new URLTemplate("file_version_legal_holds/%s"); /** * Constructs a file version legal hold with a given ID. diff --git a/src/main/java/com/box/sdk/BoxFileVersionRetention.java b/src/main/java/com/box/sdk/BoxFileVersionRetention.java index a2615473c..b477991a9 100644 --- a/src/main/java/com/box/sdk/BoxFileVersionRetention.java +++ b/src/main/java/com/box/sdk/BoxFileVersionRetention.java @@ -25,12 +25,12 @@ public class BoxFileVersionRetention extends BoxResource { /** * @see #getInfo(String...) */ - private static final URLTemplate RETENTION_URL_TEMPLATE = new URLTemplate("file_version_retentions/%s"); + public static final URLTemplate RETENTION_URL_TEMPLATE = new URLTemplate("file_version_retentions/%s"); /** * The URL template used for operation with file version retentions. */ - private static final URLTemplate ALL_RETENTIONS_URL_TEMPLATE = new URLTemplate("file_version_retentions"); + public static final URLTemplate ALL_RETENTIONS_URL_TEMPLATE = new URLTemplate("file_version_retentions"); /** * The default limit of entries per response. diff --git a/src/main/java/com/box/sdk/BoxFolder.java b/src/main/java/com/box/sdk/BoxFolder.java index 3b9c9a4a4..2c0d2a0c7 100644 --- a/src/main/java/com/box/sdk/BoxFolder.java +++ b/src/main/java/com/box/sdk/BoxFolder.java @@ -33,18 +33,54 @@ public class BoxFolder extends BoxItem implements Iterable { "item_status", "item_collection", "sync_state", "has_collaborations", "permissions", "tags", "can_non_owners_invite", "collections", "watermark_info"}; - private static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders"); - private static final URLTemplate CREATE_WEB_LINK_URL = new URLTemplate("web_links"); - private static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy"); - private static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b"); - private static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s"); - private static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content"); - private static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); - private static final URLTemplate GET_COLLABORATIONS_URL = new URLTemplate("folders/%s/collaborations"); - private static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/%s/items/"); - private static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); - private static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("folders/%s/metadata/%s/%s"); - private static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions"); + /** + * Create Folder URL Template. + */ + public static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders"); + /** + * Create Web Link URL Template. + */ + public static final URLTemplate CREATE_WEB_LINK_URL = new URLTemplate("web_links"); + /** + * Copy Folder URL Template. + */ + public static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy"); + /** + * Delete Folder URL Template. + */ + public static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b"); + /** + * Folder Info URL Template. + */ + public static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s"); + /** + * Upload File URL Template. + */ + public static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content"); + /** + * Add Collaboration URL Template. + */ + public static final URLTemplate ADD_COLLABORATION_URL = new URLTemplate("collaborations"); + /** + * Get Collaborations URL Template. + */ + public static final URLTemplate GET_COLLABORATIONS_URL = new URLTemplate("folders/%s/collaborations"); + /** + * Get Items URL Template. + */ + public static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/%s/items/"); + /** + * Search URL Template. + */ + public static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); + /** + * Metadata URL Template. + */ + public static final URLTemplate METADATA_URL_TEMPLATE = new URLTemplate("folders/%s/metadata/%s/%s"); + /** + * Upload Session URL Template. + */ + public static final URLTemplate UPLOAD_SESSION_URL_TEMPLATE = new URLTemplate("files/upload_sessions"); /** * Constructs a BoxFolder for a folder with a given ID. @@ -902,7 +938,7 @@ public Info(String json) { * Constructs an Info object using an already parsed JSON object. * @param jsonObject the parsed JSON object. */ - Info(JsonObject jsonObject) { + public Info(JsonObject jsonObject) { super(jsonObject); } diff --git a/src/main/java/com/box/sdk/BoxGroup.java b/src/main/java/com/box/sdk/BoxGroup.java index b8f110973..62e78ab25 100644 --- a/src/main/java/com/box/sdk/BoxGroup.java +++ b/src/main/java/com/box/sdk/BoxGroup.java @@ -23,27 +23,27 @@ public class BoxGroup extends BoxCollaborator { /** * @see #getAllGroups(BoxAPIConnection, String...) */ - private static final URLTemplate GROUPS_URL_TEMPLATE = new URLTemplate("groups"); + public static final URLTemplate GROUPS_URL_TEMPLATE = new URLTemplate("groups"); /** * @see #getInfo() */ - private static final URLTemplate GROUP_URL_TEMPLATE = new URLTemplate("groups/%s"); + public static final URLTemplate GROUP_URL_TEMPLATE = new URLTemplate("groups/%s"); /** * @see #getMemberships() */ - private static final URLTemplate MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("groups/%s/memberships"); + public static final URLTemplate MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("groups/%s/memberships"); /** * @see #addMembership(BoxUser) */ - private static final URLTemplate ADD_MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships"); + public static final URLTemplate ADD_MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships"); /** * @see #getCollaborations() */ - private static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("groups/%s/collaborations"); + public static final URLTemplate COLLABORATIONS_URL_TEMPLATE = new URLTemplate("groups/%s/collaborations"); /** * Constructs a BoxGroup for a group with a given ID. diff --git a/src/main/java/com/box/sdk/BoxGroupMembership.java b/src/main/java/com/box/sdk/BoxGroupMembership.java index 8d4781867..2ef92b251 100644 --- a/src/main/java/com/box/sdk/BoxGroupMembership.java +++ b/src/main/java/com/box/sdk/BoxGroupMembership.java @@ -21,7 +21,7 @@ public class BoxGroupMembership extends BoxResource { * The URL template for all group membership requests. * @see #getInfo() */ - private static final URLTemplate MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships/%s"); + public static final URLTemplate MEMBERSHIP_URL_TEMPLATE = new URLTemplate("group_memberships/%s"); /** * Constructs a BoxGroupMembership for a group membership with a given ID. diff --git a/src/main/java/com/box/sdk/BoxItem.java b/src/main/java/com/box/sdk/BoxItem.java index dd1174b76..dad8de9b8 100644 --- a/src/main/java/com/box/sdk/BoxItem.java +++ b/src/main/java/com/box/sdk/BoxItem.java @@ -25,13 +25,15 @@ public abstract class BoxItem extends BoxResource { "version_number", "comment_count", "permissions", "tags", "lock", "extension", "is_package", "folder_upload_email", "item_collection", "sync_state", "has_collaborations", "can_non_owners_invite", "file_version", "collections"}; - - private static final URLTemplate SHARED_ITEM_URL_TEMPLATE = new URLTemplate("shared_items"); + /** + * Shared Item URL Template. + */ + public static final URLTemplate SHARED_ITEM_URL_TEMPLATE = new URLTemplate("shared_items"); /** * Url template for operations with watermarks. */ - private static final URLTemplate WATERMARK_URL_TEMPLATE = new URLTemplate("/watermark"); + public static final URLTemplate WATERMARK_URL_TEMPLATE = new URLTemplate("/watermark"); /** * Constructs a BoxItem for an item with a given ID. diff --git a/src/main/java/com/box/sdk/BoxJSONObject.java b/src/main/java/com/box/sdk/BoxJSONObject.java index 09bd9294e..f380eb504 100644 --- a/src/main/java/com/box/sdk/BoxJSONObject.java +++ b/src/main/java/com/box/sdk/BoxJSONObject.java @@ -72,6 +72,18 @@ public String getPendingChanges() { return jsonObject.toString(); } + /** + * Gets a JSON string containing any pending changes to this object that can be sent back to the Box API. + * @return a JSON string containing the pending changes. + */ + public JsonObject getPendingChangesAsJsonObject() { + JsonObject jsonObject = this.getPendingJSONObject(); + if (jsonObject == null) { + return null; + } + return jsonObject; + } + /** * Invoked with a JSON member whenever this object is updated or created from a JSON object. * diff --git a/src/main/java/com/box/sdk/BoxJSONRequest.java b/src/main/java/com/box/sdk/BoxJSONRequest.java index 1c86b1241..105f34a95 100644 --- a/src/main/java/com/box/sdk/BoxJSONRequest.java +++ b/src/main/java/com/box/sdk/BoxJSONRequest.java @@ -3,6 +3,7 @@ import java.net.URL; import com.box.sdk.http.HttpMethod; +import com.eclipsesource.json.JsonObject; /** * Used to make HTTP requests containing JSON to the Box API. @@ -11,7 +12,7 @@ * automatically sets the appropriate "Content-Type" HTTP headers and allows the JSON in the request to be logged.

*/ public class BoxJSONRequest extends BoxAPIRequest { - private String json; + private JsonObject jsonObject; /** * Constructs an authenticated BoxJSONRequest using a provided BoxAPIConnection. @@ -21,7 +22,6 @@ public class BoxJSONRequest extends BoxAPIRequest { */ public BoxJSONRequest(BoxAPIConnection api, URL url, String method) { super(api, url, method); - this.addHeader("Content-Type", "application/json"); } @@ -33,7 +33,16 @@ public BoxJSONRequest(BoxAPIConnection api, URL url, String method) { */ public BoxJSONRequest(BoxAPIConnection api, URL url, HttpMethod method) { super(api, url, method); + this.addHeader("Content-Type", "application/json"); + } + /** + * Constructs an authenticated BoxJSONRequest. + * @param url the URL of the request. + * @param method the HTTP method of the request. + */ + public BoxJSONRequest(URL url, HttpMethod method) { + super(url, method); this.addHeader("Content-Type", "application/json"); } @@ -44,11 +53,28 @@ public BoxJSONRequest(BoxAPIConnection api, URL url, HttpMethod method) { @Override public void setBody(String body) { super.setBody(body); - this.json = body; + this.jsonObject = JsonObject.readFrom(body); + } + + /** + * Sets the body of this request to a given JsonObject. + * @param body the JsonObject to use as the body. + */ + public void setBody(JsonObject body) { + super.setBody(body.toString()); + this.jsonObject = body; + } + + /** + * Gets the body of this request as a JsonObject. + * @return body represented as JsonObject. + */ + public JsonObject getBodyAsJsonObject() { + return this.jsonObject; } @Override protected String bodyToString() { - return this.json; + return this.jsonObject.toString(); } } diff --git a/src/main/java/com/box/sdk/BoxJSONResponse.java b/src/main/java/com/box/sdk/BoxJSONResponse.java index de61a1743..082e7aea9 100644 --- a/src/main/java/com/box/sdk/BoxJSONResponse.java +++ b/src/main/java/com/box/sdk/BoxJSONResponse.java @@ -3,6 +3,9 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; +import java.util.Map; + +import com.eclipsesource.json.JsonObject; /** * Used to read HTTP responses containing JSON from the Box API. @@ -12,8 +15,7 @@ */ public class BoxJSONResponse extends BoxAPIResponse { private static final int BUFFER_SIZE = 8192; - - private String json; + private JsonObject jsonObject; /** * Constructs a BoxJSONResponse without an associated HttpURLConnection. @@ -30,34 +32,57 @@ public BoxJSONResponse(HttpURLConnection connection) { super(connection); } + /** + * Constructs a BoxAPIResponse with an http response code and response body. + * @param responseCode http response code + * @param httpHeaders map of http headers + * @param body response body as Json Object + */ + public BoxJSONResponse(int responseCode, Map httpHeaders, JsonObject body) { + super(responseCode, httpHeaders); + this.jsonObject = body; + } + + /** + * Get response as Json Object. + * @return response as JsonObject + */ + public JsonObject getJsonObject() { + if (this.jsonObject != null) { + return this.jsonObject; + } else { + return JsonObject.readFrom(this.getJSON()); + } + } + /** * Gets the body of the response as a JSON string. When this method is called, the response's body will be read and * the response will be disconnected, meaning that the stream returned by {@link #getBody} can no longer be used. * @return the body of the response as a JSON string. */ public String getJSON() { - if (this.json != null) { - return this.json; - } + if (this.jsonObject != null) { + return this.jsonObject.toString(); + } else { + InputStreamReader reader = new InputStreamReader(this.getBody(), StandardCharsets.UTF_8); + StringBuilder builder = new StringBuilder(); + char[] buffer = new char[BUFFER_SIZE]; - InputStreamReader reader = new InputStreamReader(this.getBody(), StandardCharsets.UTF_8); - StringBuilder builder = new StringBuilder(); - char[] buffer = new char[BUFFER_SIZE]; + try { + int read = reader.read(buffer, 0, BUFFER_SIZE); + while (read != -1) { + builder.append(buffer, 0, read); + read = reader.read(buffer, 0, BUFFER_SIZE); + } - try { - int read = reader.read(buffer, 0, BUFFER_SIZE); - while (read != -1) { - builder.append(buffer, 0, read); - read = reader.read(buffer, 0, BUFFER_SIZE); + this.disconnect(); + reader.close(); + } catch (IOException e) { + throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); } - - this.disconnect(); - reader.close(); - } catch (IOException e) { - throw new BoxAPIException("Couldn't connect to the Box API due to a network error.", e); + this.jsonObject = JsonObject.readFrom(builder.toString()); + return builder.toString(); } - this.json = builder.toString(); - return this.json; } @Override diff --git a/src/main/java/com/box/sdk/BoxLegalHoldAssignment.java b/src/main/java/com/box/sdk/BoxLegalHoldAssignment.java index 1c24c6305..b312c1a6c 100644 --- a/src/main/java/com/box/sdk/BoxLegalHoldAssignment.java +++ b/src/main/java/com/box/sdk/BoxLegalHoldAssignment.java @@ -43,12 +43,12 @@ public class BoxLegalHoldAssignment extends BoxResource { /** * The URL template used for operation with legal hold policy assignments. */ - private static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("legal_hold_policy_assignments"); + public static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("legal_hold_policy_assignments"); /** * The URL template used for operation with legal hold policy assignment with given ID. */ - private static final URLTemplate LEGAL_HOLD_ASSIGNMENT_URL_TEMPLATE + public static final URLTemplate LEGAL_HOLD_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("legal_hold_policy_assignments/%s"); /** diff --git a/src/main/java/com/box/sdk/BoxLegalHoldPolicy.java b/src/main/java/com/box/sdk/BoxLegalHoldPolicy.java index 1a8bb1957..df8da1026 100644 --- a/src/main/java/com/box/sdk/BoxLegalHoldPolicy.java +++ b/src/main/java/com/box/sdk/BoxLegalHoldPolicy.java @@ -19,12 +19,23 @@ */ @BoxResourceType("legal_hold") public class BoxLegalHoldPolicy extends BoxResource { - - private static final URLTemplate LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies/%s"); - private static final URLTemplate ALL_LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies"); - private static final URLTemplate LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE + /** + * Legal Hold URL Template. + */ + public static final URLTemplate LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies/%s"); + /** + * All Legal Hold URL Template. + */ + public static final URLTemplate ALL_LEGAL_HOLD_URL_TEMPLATE = new URLTemplate("legal_hold_policies"); + /** + * Legal Hold Assignments URL Template. + */ + public static final URLTemplate LEGAL_HOLD_ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("legal_hold_policies/%s/assignments"); - private static final URLTemplate LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE + /** + * List of File Version Holds URL Template. + */ + public static final URLTemplate LIST_OF_FILE_VERSION_HOLDS_URL_TEMPLATE = new URLTemplate("file_version_legal_holds"); private static final int DEFAULT_LIMIT = 100; diff --git a/src/main/java/com/box/sdk/BoxRecents.java b/src/main/java/com/box/sdk/BoxRecents.java index ee7d64ef2..decc6cf7e 100644 --- a/src/main/java/com/box/sdk/BoxRecents.java +++ b/src/main/java/com/box/sdk/BoxRecents.java @@ -8,7 +8,10 @@ */ public final class BoxRecents { - private static final URLTemplate RECENTS_URL_TEMPLATE = new URLTemplate("recent_items"); + /** + * Recents URL Template. + */ + public static final URLTemplate RECENTS_URL_TEMPLATE = new URLTemplate("recent_items"); //Constructor is not allowed private BoxRecents() { diff --git a/src/main/java/com/box/sdk/BoxRetentionPolicy.java b/src/main/java/com/box/sdk/BoxRetentionPolicy.java index e0481014e..65c50ad43 100644 --- a/src/main/java/com/box/sdk/BoxRetentionPolicy.java +++ b/src/main/java/com/box/sdk/BoxRetentionPolicy.java @@ -20,6 +20,20 @@ */ @BoxResourceType("retention_policy") public class BoxRetentionPolicy extends BoxResource { + /** + * The URL template used for operation with retention policies. + */ + public static final URLTemplate RETENTION_POLICIES_URL_TEMPLATE = new URLTemplate("retention_policies"); + + /** + * The URL template used for operation with retention policy with given ID. + */ + public static final URLTemplate POLICY_URL_TEMPLATE = new URLTemplate("retention_policies/%s"); + + /** + * The URL template used for operation with retention policy assignments. + */ + public static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("retention_policies/%s/assignments"); /** * Will cause the content retained by the policy to be permanently deleted. @@ -57,21 +71,6 @@ public class BoxRetentionPolicy extends BoxResource { */ private static final int DEFAULT_LIMIT = 100; - /** - * The URL template used for operation with retention policies. - */ - private static final URLTemplate RETENTION_POLICIES_URL_TEMPLATE = new URLTemplate("retention_policies"); - - /** - * The URL template used for operation with retention policy with given ID. - */ - private static final URLTemplate POLICY_URL_TEMPLATE = new URLTemplate("retention_policies/%s"); - - /** - * The URL template used for operation with retention policy assignments. - */ - private static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("retention_policies/%s/assignments"); - /** * Constructs a retention policy for a resource with a given ID. * diff --git a/src/main/java/com/box/sdk/BoxRetentionPolicyAssignment.java b/src/main/java/com/box/sdk/BoxRetentionPolicyAssignment.java index 945125f7b..883b32198 100644 --- a/src/main/java/com/box/sdk/BoxRetentionPolicyAssignment.java +++ b/src/main/java/com/box/sdk/BoxRetentionPolicyAssignment.java @@ -30,12 +30,12 @@ public class BoxRetentionPolicyAssignment extends BoxResource { /** * The URL template used for operation with retention policy assignments. */ - private static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("retention_policy_assignments"); + public static final URLTemplate ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("retention_policy_assignments"); /** * The URL template used for operation with retention policy assignment with given ID. */ - private static final URLTemplate RETENTION_POLICY_ASSIGNMENT_URL_TEMPLATE + public static final URLTemplate RETENTION_POLICY_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("retention_policy_assignments/%s"); /** diff --git a/src/main/java/com/box/sdk/BoxSearch.java b/src/main/java/com/box/sdk/BoxSearch.java index dffa6fc32..49351382b 100644 --- a/src/main/java/com/box/sdk/BoxSearch.java +++ b/src/main/java/com/box/sdk/BoxSearch.java @@ -14,7 +14,10 @@ */ public class BoxSearch { - private static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); + /** + * Search URL Template. + */ + public static final URLTemplate SEARCH_URL_TEMPLATE = new URLTemplate("search"); private final BoxAPIConnection api; /** diff --git a/src/main/java/com/box/sdk/BoxTask.java b/src/main/java/com/box/sdk/BoxTask.java index 115a50ce2..7be0b3ee6 100644 --- a/src/main/java/com/box/sdk/BoxTask.java +++ b/src/main/java/com/box/sdk/BoxTask.java @@ -17,9 +17,18 @@ @BoxResourceType("task") public class BoxTask extends BoxResource { - private static final URLTemplate TASK_URL_TEMPLATE = new URLTemplate("tasks/%s"); - private static final URLTemplate GET_ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("tasks/%s/assignments"); - private static final URLTemplate ADD_TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments"); + /** + * Task URL Template. + */ + public static final URLTemplate TASK_URL_TEMPLATE = new URLTemplate("tasks/%s"); + /** + * Get Assignments URL Template. + */ + public static final URLTemplate GET_ASSIGNMENTS_URL_TEMPLATE = new URLTemplate("tasks/%s/assignments"); + /** + * Add Task Assignment URL Template. + */ + public static final URLTemplate ADD_TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments"); /** * Constructs a BoxTask for a task with a given ID. diff --git a/src/main/java/com/box/sdk/BoxTaskAssignment.java b/src/main/java/com/box/sdk/BoxTaskAssignment.java index 46f354e86..82e2ab31b 100644 --- a/src/main/java/com/box/sdk/BoxTaskAssignment.java +++ b/src/main/java/com/box/sdk/BoxTaskAssignment.java @@ -14,7 +14,10 @@ @BoxResourceType("task_assignment") public class BoxTaskAssignment extends BoxResource { - private static final URLTemplate TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments/%s"); + /** + * Task Assignment URL Template. + */ + public static final URLTemplate TASK_ASSIGNMENT_URL_TEMPLATE = new URLTemplate("task_assignments/%s"); /** * Constructs a BoxTaskAssignment for a task assignment with a given ID. diff --git a/src/main/java/com/box/sdk/BoxTrash.java b/src/main/java/com/box/sdk/BoxTrash.java index a7814c898..6479cd968 100644 --- a/src/main/java/com/box/sdk/BoxTrash.java +++ b/src/main/java/com/box/sdk/BoxTrash.java @@ -13,13 +13,29 @@ * handling for errors related to the Box REST API, you should capture this exception explicitly.

*/ public class BoxTrash implements Iterable { - private static final long LIMIT = 1000; - private static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/trash/items/"); - private static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s/trash"); - private static final URLTemplate FILE_INFO_URL_TEMPLATE = new URLTemplate("files/%s/trash"); - private static final URLTemplate RESTORE_FILE_URL_TEMPLATE = new URLTemplate("files/%s"); - private static final URLTemplate RESTORE_FOLDER_URL_TEMPLATE = new URLTemplate("folders/%s"); + /** + * Get Item URL Template. + */ + public static final URLTemplate GET_ITEMS_URL = new URLTemplate("folders/trash/items/"); + /** + * Folder Info URL Template. + */ + public static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s/trash"); + /** + * File Info URL Template. + */ + public static final URLTemplate FILE_INFO_URL_TEMPLATE = new URLTemplate("files/%s/trash"); + /** + * Restore File URL Template. + */ + public static final URLTemplate RESTORE_FILE_URL_TEMPLATE = new URLTemplate("files/%s"); + /** + * Restore Folder URL Template. + */ + public static final URLTemplate RESTORE_FOLDER_URL_TEMPLATE = new URLTemplate("folders/%s"); + + private static final long LIMIT = 1000; private final BoxAPIConnection api; /** diff --git a/src/main/java/com/box/sdk/BoxUser.java b/src/main/java/com/box/sdk/BoxUser.java index 8de344c2d..78b889fe6 100644 --- a/src/main/java/com/box/sdk/BoxUser.java +++ b/src/main/java/com/box/sdk/BoxUser.java @@ -29,13 +29,34 @@ public class BoxUser extends BoxCollaborator { "address", "avatar_url", "is_exempt_from_device_limits", "is_exempt_from_login_verification", "enterprise", "my_tags", "hostname", "is_platform_access_only", "external_app_user_id"}; - private static final URLTemplate USER_URL_TEMPLATE = new URLTemplate("users/%s"); - private static final URLTemplate GET_ME_URL = new URLTemplate("users/me"); - private static final URLTemplate USERS_URL_TEMPLATE = new URLTemplate("users"); - private static final URLTemplate USER_MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("users/%s/memberships"); - private static final URLTemplate EMAIL_ALIAS_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases/%s"); - private static final URLTemplate EMAIL_ALIASES_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases"); - private static final URLTemplate MOVE_FOLDER_TO_USER_TEMPLATE = new URLTemplate("users/%s/folders/%s"); + /** + * User URL Template. + */ + public static final URLTemplate USER_URL_TEMPLATE = new URLTemplate("users/%s"); + /** + * Get Me URL Template. + */ + public static final URLTemplate GET_ME_URL = new URLTemplate("users/me"); + /** + * Users URL Template. + */ + public static final URLTemplate USERS_URL_TEMPLATE = new URLTemplate("users"); + /** + * User Memberships URL Template. + */ + public static final URLTemplate USER_MEMBERSHIPS_URL_TEMPLATE = new URLTemplate("users/%s/memberships"); + /** + * E-Mail Alias URL Template. + */ + public static final URLTemplate EMAIL_ALIAS_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases/%s"); + /** + * E-Mail Aliases URL Template. + */ + public static final URLTemplate EMAIL_ALIASES_URL_TEMPLATE = new URLTemplate("users/%s/email_aliases"); + /** + * Move Folder To User Template. + */ + public static final URLTemplate MOVE_FOLDER_TO_USER_TEMPLATE = new URLTemplate("users/%s/folders/%s"); /** * Constructs a BoxUser for a user with a given ID. diff --git a/src/main/java/com/box/sdk/BoxWebHook.java b/src/main/java/com/box/sdk/BoxWebHook.java index 266548bfe..df21af4eb 100644 --- a/src/main/java/com/box/sdk/BoxWebHook.java +++ b/src/main/java/com/box/sdk/BoxWebHook.java @@ -25,6 +25,15 @@ @BoxResourceType("webhook") public class BoxWebHook extends BoxResource { + /** + * {@link URLTemplate} for {@link BoxWebHook}s resource. + */ + public static final URLTemplate WEBHOOKS_URL_TEMPLATE = new URLTemplate("webhooks"); + /** + * {@link URLTemplate} for single {@link BoxWebHook} resource. + */ + public static final URLTemplate WEBHOOK_URL_TEMPLATE = new URLTemplate("webhooks/%s"); + /** * JSON Key for {@link BoxWebHook} {@link #getID()}. */ @@ -65,15 +74,6 @@ public class BoxWebHook extends BoxResource { */ private static final String JSON_KEY_CREATED_AT = "created_at"; - /** - * {@link URLTemplate} for {@link BoxWebHook}s resource. - */ - private static final URLTemplate WEBHOOKS_URL_TEMPLATE = new URLTemplate("webhooks"); - /** - * {@link URLTemplate} for single {@link BoxWebHook} resource. - */ - private static final URLTemplate WEBHOOK_URL_TEMPLATE = new URLTemplate("webhooks/%s"); - /** * Maps a {@link Trigger} to its {@link Trigger#getValue()}. */ diff --git a/src/main/java/com/box/sdk/BoxWebLink.java b/src/main/java/com/box/sdk/BoxWebLink.java index bb18d77ac..e701a8109 100644 --- a/src/main/java/com/box/sdk/BoxWebLink.java +++ b/src/main/java/com/box/sdk/BoxWebLink.java @@ -26,8 +26,14 @@ public class BoxWebLink extends BoxItem { "path_collection", "created_at", "modified_at", "trashed_at", "purged_at", "created_by", "modified_by", "owned_by", "shared_link", "parent", "item_status", "collections"}; - private static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("web_links/%s/copy"); - private static final URLTemplate WEB_LINK_URL_TEMPLATE = new URLTemplate("web_links/%s"); + /** + * Copy URL Template. + */ + public static final URLTemplate COPY_URL_TEMPLATE = new URLTemplate("web_links/%s/copy"); + /** + * Web Link URL Template. + */ + public static final URLTemplate WEB_LINK_URL_TEMPLATE = new URLTemplate("web_links/%s"); /** * Constructs a BoxWebLink for a weblink with a given ID. diff --git a/src/main/java/com/box/sdk/EventLog.java b/src/main/java/com/box/sdk/EventLog.java index 618867f4c..af794aed0 100644 --- a/src/main/java/com/box/sdk/EventLog.java +++ b/src/main/java/com/box/sdk/EventLog.java @@ -19,10 +19,13 @@ *

*/ public class EventLog implements Iterable { + private static final int ENTERPRISE_LIMIT = 500; - private static final URLTemplate ENTERPRISE_EVENT_URL_TEMPLATE = new URLTemplate("events?stream_type=admin_logs&" + /** + * Enterprise Event URL Template. + */ + public static final URLTemplate ENTERPRISE_EVENT_URL_TEMPLATE = new URLTemplate("events?stream_type=admin_logs&" + "limit=" + ENTERPRISE_LIMIT); - private final int chunkSize; private final int limit; private final String nextStreamPosition; diff --git a/src/main/java/com/box/sdk/EventStream.java b/src/main/java/com/box/sdk/EventStream.java index 471c2412d..16ff821d4 100644 --- a/src/main/java/com/box/sdk/EventStream.java +++ b/src/main/java/com/box/sdk/EventStream.java @@ -19,10 +19,15 @@ * */ public class EventStream { + private static final int LIMIT = 800; - private static final URLTemplate EVENT_URL = new URLTemplate("events?limit=" + LIMIT + "&stream_position=%s"); private static final int STREAM_POSITION_NOW = -1; + /** + * Events URL. + */ + public static final URLTemplate EVENT_URL = new URLTemplate("events?limit=" + LIMIT + "&stream_position=%s"); + private final BoxAPIConnection api; private final long startingPosition; private final Collection listeners; diff --git a/src/main/java/com/box/sdk/Metadata.java b/src/main/java/com/box/sdk/Metadata.java index 02f446450..7f8e499e2 100644 --- a/src/main/java/com/box/sdk/Metadata.java +++ b/src/main/java/com/box/sdk/Metadata.java @@ -38,7 +38,7 @@ public class Metadata { /** * URL template for all metadata associated with item. */ - private static final URLTemplate GET_ALL_METADATA_URL_TEMPLATE = new URLTemplate("/metadata"); + public static final URLTemplate GET_ALL_METADATA_URL_TEMPLATE = new URLTemplate("/metadata"); /** * Values contained by the metadata object. diff --git a/src/main/java/com/box/sdk/MetadataTemplate.java b/src/main/java/com/box/sdk/MetadataTemplate.java index e38c26c14..86ac90435 100644 --- a/src/main/java/com/box/sdk/MetadataTemplate.java +++ b/src/main/java/com/box/sdk/MetadataTemplate.java @@ -21,19 +21,19 @@ public class MetadataTemplate extends BoxJSONObject { /** * @see #getMetadataTemplate(BoxAPIConnection) */ - private static final URLTemplate METADATA_TEMPLATE_URL_TEMPLATE + public static final URLTemplate METADATA_TEMPLATE_URL_TEMPLATE = new URLTemplate("metadata_templates/%s/%s/schema"); /** * @see #createMetadataTemplate(BoxAPIConnection, String, String, String, boolean, List) */ - private static final URLTemplate METADATA_TEMPLATE_SCHEMA_URL_TEMPLATE + public static final URLTemplate METADATA_TEMPLATE_SCHEMA_URL_TEMPLATE = new URLTemplate("metadata_templates/schema"); /** * @see #getEnterpriseMetadataTemplates(String, int, BoxAPIConnection, String...) */ - private static final URLTemplate ENTERPRISE_METADATA_URL_TEMPLATE = new URLTemplate("metadata_templates/%s"); + public static final URLTemplate ENTERPRISE_METADATA_URL_TEMPLATE = new URLTemplate("metadata_templates/%s"); /** * Default metadata type to be used in query. diff --git a/src/main/java/com/box/sdk/RealtimeServerConnection.java b/src/main/java/com/box/sdk/RealtimeServerConnection.java index 82e461ef0..47faaa682 100644 --- a/src/main/java/com/box/sdk/RealtimeServerConnection.java +++ b/src/main/java/com/box/sdk/RealtimeServerConnection.java @@ -7,8 +7,8 @@ import com.eclipsesource.json.JsonObject; class RealtimeServerConnection { - private static final URLTemplate EVENT_URL = new URLTemplate("events"); - private static final URLTemplate EVENT_POSITION_URL = new URLTemplate("events?stream_position=%s"); + public static final URLTemplate EVENT_URL = new URLTemplate("events"); + public static final URLTemplate EVENT_POSITION_URL = new URLTemplate("events?stream_position=%s"); private final BoxAPIConnection api; private final int timeout; diff --git a/src/main/java/com/box/sdk/URLTemplate.java b/src/main/java/com/box/sdk/URLTemplate.java index 15208de52..d33ffd53a 100644 --- a/src/main/java/com/box/sdk/URLTemplate.java +++ b/src/main/java/com/box/sdk/URLTemplate.java @@ -3,14 +3,27 @@ import java.net.MalformedURLException; import java.net.URL; -class URLTemplate { +/** + * A template class to build URLs from base URL, path, URL parameters and Query String. + */ +public class URLTemplate { private String template; - URLTemplate(String template) { + /** + * Construct an URL Template object from path. + * @param template path + */ + public URLTemplate(String template) { this.template = template; } - URL build(String base, Object... values) { + /** + * Build a URL with URL Parameters. + * @param base base URL + * @param values URL parameters + * @return URL + */ + public URL build(String base, Object... values) { String urlString = String.format(base + this.template, values); URL url = null; @@ -23,7 +36,14 @@ URL build(String base, Object... values) { return url; } - URL buildWithQuery(String base, String queryString, Object... values) { + /** + * Build a URL with Query String and URL Parameters. + * @param base base URL + * @param queryString query string + * @param values URL Parameters + * @return URL + */ + public URL buildWithQuery(String base, String queryString, Object... values) { String urlString = String.format(base + this.template, values) + queryString; URL url = null; try { diff --git a/src/main/java/com/box/sdk/http/HttpHeaders.java b/src/main/java/com/box/sdk/http/HttpHeaders.java index aac67afeb..6def10f46 100644 --- a/src/main/java/com/box/sdk/http/HttpHeaders.java +++ b/src/main/java/com/box/sdk/http/HttpHeaders.java @@ -40,6 +40,11 @@ public final class HttpHeaders { */ public static final String X_BOX_PART_ID = "X-Box-Part-Id"; + /** + * HTTP header key Authorization. + */ + public static final String AUTHORIZATION = "Authorization"; + //Prevents instantiation private HttpHeaders() { } diff --git a/src/test/java/com/box/sdk/BatchAPIRequestTest.java b/src/test/java/com/box/sdk/BatchAPIRequestTest.java new file mode 100644 index 000000000..a8a072198 --- /dev/null +++ b/src/test/java/com/box/sdk/BatchAPIRequestTest.java @@ -0,0 +1,130 @@ +package com.box.sdk; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import com.box.sdk.http.HttpMethod; +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +/** + * + */ +public class BatchAPIRequestTest { + @Test + @Category(UnitTest.class) + public void testThatBodyHasAllRequiredFieldsInEachResponse() { + try { + final String anyClientID = ""; + final String anyClientSecret = ""; + final String anyAccessToken = ""; + final String anyRefreshToken = ""; + + BoxAPIConnection api = new BoxAPIConnection(anyClientID, anyClientSecret, anyAccessToken, anyRefreshToken); + + List requests = new ArrayList(); + + //Get current user request + URL getMeURL = BoxUser.GET_ME_URL.build(api.getBaseURL()); + BoxAPIRequest getMeRequest = new BoxAPIRequest(getMeURL, HttpMethod.GET); + requests.add(getMeRequest); + + //Create App User Request + URL createUserURL = BoxUser.USERS_URL_TEMPLATE.build(api.getBaseURL()); + BoxJSONRequest createAppUserRequest = new BoxJSONRequest(createUserURL, HttpMethod.POST); + createAppUserRequest.setBody("{\"name\":\"some-name\"," + + "\"is_platform_access_only\":true}"); + requests.add(createAppUserRequest); + + //Get Root Folder Request + URL getRootFolderURL = BoxFolder.FOLDER_INFO_URL_TEMPLATE.build(api.getBaseURL(), 0); + BoxAPIRequest getRootFolderRequest = new BoxAPIRequest(getRootFolderURL, HttpMethod.GET); + requests.add(getRootFolderRequest); + + BatchAPIRequest batchRequest = new BatchAPIRequest(api); + batchRequest.prepareRequest(requests); + + assertTrue("requests field should be an array", + (batchRequest.getBodyAsJsonObject().get("requests").isArray())); + + JsonArray requestsArray = batchRequest.getBodyAsJsonObject().get("requests").asArray(); + for (JsonValue request : requestsArray) { + assertTrue("each request should be an object", + (request.isObject())); + assertTrue("each request should have a relative_url that is string", + (((JsonObject) request).get("relative_url").isString())); + assertTrue("each request should have a method that is string", + (((JsonObject) request).get("method").isString())); + assertTrue("each request should have headers as object", + (((JsonObject) request).get("headers").isObject())); + if (((JsonObject) request).get("method").asString().equals(HttpMethod.POST)) { + assertTrue("request should have body when method is POST", + (((JsonObject) request).get("body").isObject())); + } + } + + } catch (Exception e) { + fail("Exception during test execution " + e); + } + } + + @Test + @Category(UnitTest.class) + public void testTheParsingResponseWorksAsIntended() { + try { + final String anyClientID = ""; + final String anyClientSecret = ""; + final String anyAccessToken = ""; + final String anyRefreshToken = ""; + + BoxAPIConnection api = new BoxAPIConnection(anyClientID, anyClientSecret, anyAccessToken, anyRefreshToken); + BatchAPIRequest batchRequest = new BatchAPIRequest(api); + String stringResponse = "{\n" + + "\t\"responses\": [{\n" + + "\t\t\t\"status\": 201,\n" + + "\t\t\t\"response\": {\n" + + "\t\t\t\t\"type\": \"collaboration\",\n" + + "\t\t\t\t\"id\": \"123\"\n" + + "\t\t\t}\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"status\": 404,\n" + + "\t\t\t\"response\": {\n" + + "\t\t\t\t\"type\": \"error\",\n" + + "\t\t\t\t\"status\": 404,\n" + + "\t\t\t\t\"code\": \"not_found\",\n" + + "\t\t\t\t\"message\": \"Not Found\",\n" + + "\t\t\t\t\"request_id\": \"139334760758014ea2935ab\"\n" + + "\t\t\t}\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"status\": 200,\n" + + "\t\t\t\"response\": {\n" + + "\t\t\t\t\"type\": \"collaboration\",\n" + + "\t\t\t\t\"id\": \"456\"\n" + + "\t\t\t}\n" + + "\t\t}\n" + + "\t]\n" + + "}"; + JsonObject responseJson = JsonObject.readFrom(stringResponse); + BoxJSONResponse batchResponse = new BoxJSONResponse(200, null, responseJson); + List responses = batchRequest.parseResponse(batchResponse); + + assertTrue("There should be three responses", responses.size() == 3); + for (BoxAPIResponse response: responses) { + assertTrue("Always has response body", ((BoxJSONResponse) response).getJsonObject() != null); + } + + } catch (Exception e) { + fail("Exception during test execution " + e); + } + } + +} diff --git a/src/test/java/com/box/sdk/BoxGroupTest.java b/src/test/java/com/box/sdk/BoxGroupTest.java index 9dc9cc89b..4a3e071e2 100644 --- a/src/test/java/com/box/sdk/BoxGroupTest.java +++ b/src/test/java/com/box/sdk/BoxGroupTest.java @@ -39,7 +39,7 @@ */ public class BoxGroupTest { - private static final URLTemplate GROUPS_URL_TEMPLATE = new URLTemplate("groups"); + public static final URLTemplate GROUPS_URL_TEMPLATE = new URLTemplate("groups"); /** * Wiremock