You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ga...@apache.org on 2014/06/21 00:01:11 UTC
git commit: JCLOUDS-457: Added completeMultipartUpload and
abortMultipartUplod.
Repository: jclouds-labs-aws
Updated Branches:
refs/heads/master d0941fec0 -> 6194a3ee4
JCLOUDS-457: Added completeMultipartUpload and abortMultipartUplod.
Now the Glacier client supports completeMultipartUpload and i
abortMultipartUpload operations.
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/commit/6194a3ee
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/tree/6194a3ee
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/diff/6194a3ee
Branch: refs/heads/master
Commit: 6194a3ee4d0c5afd21fb1174124e689bca834dab
Parents: d0941fe
Author: Roman C. Coedo <ro...@gmail.com>
Authored: Sun Jun 1 21:19:25 2014 +0200
Committer: Andrew Gaul <ga...@apache.org>
Committed: Fri Jun 20 15:00:37 2014 -0700
----------------------------------------------------------------------
.../org/jclouds/glacier/GlacierAsyncClient.java | 27 ++++++++++++
.../java/org/jclouds/glacier/GlacierClient.java | 31 +++++++++++++
.../binders/BindArchiveSizeToHeaders.java | 41 +++++++++++++++++
.../binders/BindMultipartTreeHashToHeaders.java | 46 ++++++++++++++++++++
.../glacier/reference/GlacierHeaders.java | 1 +
.../jclouds/glacier/GlacierClientMockTest.java | 34 +++++++++++++++
6 files changed, 180 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
----------------------------------------------------------------------
diff --git a/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java b/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
index 997fb5a..e492b7c 100644
--- a/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
+++ b/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
@@ -20,6 +20,7 @@ import static org.jclouds.blobstore.attr.BlobScopes.CONTAINER;
import java.io.Closeable;
import java.net.URI;
+import java.util.Map;
import javax.inject.Named;
import javax.ws.rs.DELETE;
@@ -31,9 +32,11 @@ import javax.ws.rs.PathParam;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.blobstore.attr.BlobScope;
+import org.jclouds.glacier.binders.BindArchiveSizeToHeaders;
import org.jclouds.glacier.binders.BindContentRangeToHeaders;
import org.jclouds.glacier.binders.BindDescriptionToHeaders;
import org.jclouds.glacier.binders.BindHashesToHeaders;
+import org.jclouds.glacier.binders.BindMultipartTreeHashToHeaders;
import org.jclouds.glacier.binders.BindPartSizeToHeaders;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
@@ -59,6 +62,7 @@ import org.jclouds.rest.annotations.ParamValidators;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
+import com.google.common.hash.HashCode;
import com.google.common.util.concurrent.ListenableFuture;
/**
@@ -187,4 +191,27 @@ public interface GlacierAsyncClient extends Closeable {
@PathParam("uploadId") String uploadId,
@BinderParam(BindContentRangeToHeaders.class) ContentRange range,
@ParamValidators(PayloadValidator.class) @BinderParam(BindHashesToHeaders.class) Payload payload);
+
+ /**
+ * @see GlacierClient#completeMultipartUpload
+ */
+ @Named("CompleteMultipartUpload")
+ @POST
+ @Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
+ @ResponseParser(ParseArchiveIdHeader.class)
+ ListenableFuture<String> completeMultipartUpload(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
+ @PathParam("uploadId") String uploadId,
+ @BinderParam(BindMultipartTreeHashToHeaders.class) Map<Integer, HashCode> hashes,
+ @BinderParam(BindArchiveSizeToHeaders.class) long archiveSizeInMB);
+
+ /**
+ * @see GlacierClient#abortMultipartUpload
+ */
+ @Named("AbortMultipartUpload")
+ @DELETE
+ @Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
+ ListenableFuture<Boolean> abortMultipartUpload(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
+ @PathParam("uploadId") String uploadId);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
----------------------------------------------------------------------
diff --git a/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java b/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
index 9eaa6ac..29f743d 100644
--- a/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
+++ b/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
@@ -18,6 +18,7 @@ package org.jclouds.glacier;
import java.io.Closeable;
import java.net.URI;
+import java.util.Map;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
@@ -25,6 +26,8 @@ import org.jclouds.glacier.options.PaginationOptions;
import org.jclouds.glacier.util.ContentRange;
import org.jclouds.io.Payload;
+import com.google.common.hash.HashCode;
+
/**
* Provides access to Amazon Glacier resources via their REST API.
* <p/>
@@ -149,4 +152,32 @@ public interface GlacierClient extends Closeable {
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-upload-part.html" />
*/
String uploadPart(String vaultName, String uploadId, ContentRange range, Payload payload);
+
+ /**
+ * Completes the multipart upload.
+ *
+ * @param vaultName
+ * Name of the Vault where the archive is going to be stored.
+ * @param uploadId
+ * Multipart upload identifier.
+ * @param hashes
+ * Map containing the pairs partnumber-treehash of each uploaded part.
+ * @param archiveSizeInMB
+ * Size of the complete archive.
+ * @return A String containing the Archive identifier in Amazon Glacier.
+ * @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-complete-upload.html" />
+ */
+ String completeMultipartUpload(String vaultName, String uploadId, Map<Integer, HashCode> hashes, long archiveSizeInMB);
+
+ /**
+ * Aborts the multipart upload.
+ *
+ * @param vaultName
+ * Name of the Vault where the archive was going to be stored.
+ * @param uploadId
+ * Multipart upload identifier.
+ * @return True if the multipart upload was aborted, false otherwise.
+ * @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-abort-upload.html" />
+ */
+ boolean abortMultipartUpload(String vaultName, String uploadId);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/main/java/org/jclouds/glacier/binders/BindArchiveSizeToHeaders.java
----------------------------------------------------------------------
diff --git a/glacier/src/main/java/org/jclouds/glacier/binders/BindArchiveSizeToHeaders.java b/glacier/src/main/java/org/jclouds/glacier/binders/BindArchiveSizeToHeaders.java
new file mode 100644
index 0000000..97c500c
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/binders/BindArchiveSizeToHeaders.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.glacier.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.glacier.reference.GlacierHeaders;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+/**
+ * Binds the Archive size to the request headers.
+ */
+public class BindArchiveSizeToHeaders implements Binder {
+ @SuppressWarnings("unchecked")
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Long, "This binder is only valid for long");
+ checkNotNull(request, "request");
+ Long archiveSizeInMB = Long.class.cast(input);
+ return (R) request.toBuilder()
+ .replaceHeader(GlacierHeaders.ARCHIVE_SIZE, Long.toString(archiveSizeInMB << 20))
+ .build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/main/java/org/jclouds/glacier/binders/BindMultipartTreeHashToHeaders.java
----------------------------------------------------------------------
diff --git a/glacier/src/main/java/org/jclouds/glacier/binders/BindMultipartTreeHashToHeaders.java b/glacier/src/main/java/org/jclouds/glacier/binders/BindMultipartTreeHashToHeaders.java
new file mode 100644
index 0000000..2c5f819
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/binders/BindMultipartTreeHashToHeaders.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.glacier.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import org.jclouds.glacier.reference.GlacierHeaders;
+import org.jclouds.glacier.util.TreeHash;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.hash.HashCode;
+
+/**
+ * Binds the Tree hash to the request headers.
+ */
+public class BindMultipartTreeHashToHeaders implements Binder {
+ @SuppressWarnings("unchecked")
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Map, "This binder is only valid for Map");
+ checkNotNull(request, "request");
+ Map<Integer, HashCode> map = Map.class.cast(input);
+ checkArgument(map.size() != 0, "The map cannot be empty");
+ return (R) request.toBuilder()
+ .addHeader(GlacierHeaders.TREE_HASH, TreeHash.buildTreeHashFromMap(map).toString())
+ .build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/main/java/org/jclouds/glacier/reference/GlacierHeaders.java
----------------------------------------------------------------------
diff --git a/glacier/src/main/java/org/jclouds/glacier/reference/GlacierHeaders.java b/glacier/src/main/java/org/jclouds/glacier/reference/GlacierHeaders.java
index dbb945e..4162580 100644
--- a/glacier/src/main/java/org/jclouds/glacier/reference/GlacierHeaders.java
+++ b/glacier/src/main/java/org/jclouds/glacier/reference/GlacierHeaders.java
@@ -32,6 +32,7 @@ public final class GlacierHeaders {
public static final String ARCHIVE_ID = HEADER_PREFIX + "archive-id";
public static final String MULTIPART_UPLOAD_ID = HEADER_PREFIX + "multipart-upload-id";
public static final String PART_SIZE = HEADER_PREFIX + "part-size";
+ public static final String ARCHIVE_SIZE = HEADER_PREFIX + "archive-size";
private GlacierHeaders() {
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs-aws/blob/6194a3ee/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
----------------------------------------------------------------------
diff --git a/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java b/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
index 57fca41..c1b5de5 100644
--- a/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
+++ b/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
@@ -49,7 +49,9 @@ import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.hash.HashCode;
import com.google.common.io.Resources;
import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
@@ -271,4 +273,36 @@ public class GlacierClientMockTest {
assertEquals(request.getHeader(HttpHeaders.CONTENT_RANGE), range.buildHeader());
assertEquals(request.getHeader(HttpHeaders.CONTENT_LENGTH), payload.getContentMetadata().getContentLength().toString());
}
+
+ @Test
+ public void testCompleteMultipartUpload() throws IOException, InterruptedException {
+ MockResponse mr = buildBaseResponse(201);
+ mr.addHeader(HttpHeaders.LOCATION, ARCHIVE_LOCATION);
+ mr.addHeader(GlacierHeaders.ARCHIVE_ID, ARCHIVE_ID);
+ server.enqueue(mr);
+
+ HashCode partHashcode = HashCode.fromString("9bc1b2a288b26af7257a36277ae3816a7d4f16e89c1e7e77d0a5c48bad62b360");
+ ImmutableMap<Integer, HashCode> map = ImmutableMap.of(
+ 1, partHashcode,
+ 2, partHashcode,
+ 3, partHashcode,
+ 4, partHashcode);
+ assertEquals(client.completeMultipartUpload(VAULT_NAME, MULTIPART_UPLOAD_ID, map, 8L), ARCHIVE_ID);
+ RecordedRequest request = server.takeRequest();
+ assertEquals(request.getRequestLine(),
+ "POST /-/vaults/" + VAULT_NAME + "/multipart-uploads/" + MULTIPART_UPLOAD_ID + " " + HTTP);
+ assertEquals(request.getHeader(GlacierHeaders.TREE_HASH),
+ "9491cb2ed1d4e7cd53215f4017c23ec4ad21d7050a1e6bb636c4f67e8cddb844");
+ assertEquals(request.getHeader(GlacierHeaders.ARCHIVE_SIZE), "8388608");
+ }
+
+ @Test
+ public void testAbortMultipartUpload() throws IOException, InterruptedException {
+ MockResponse mr = buildBaseResponse(204);
+ server.enqueue(mr);
+
+ assertTrue(client.abortMultipartUpload(VAULT_NAME, MULTIPART_UPLOAD_ID));
+ assertEquals(server.takeRequest().getRequestLine(),
+ "DELETE /-/vaults/" + VAULT_NAME + "/multipart-uploads/" + MULTIPART_UPLOAD_ID + " " + HTTP);
+ }
}