JCLOUDS-457: Added list Multipart operations
Added listParts and listMultipartUploads operations to the Glacier
client.
diff --git a/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java b/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
index e492b7c..7517f56 100644
--- a/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
+++ b/glacier/src/main/java/org/jclouds/glacier/GlacierAsyncClient.java
@@ -38,12 +38,16 @@
import org.jclouds.glacier.binders.BindHashesToHeaders;
import org.jclouds.glacier.binders.BindMultipartTreeHashToHeaders;
import org.jclouds.glacier.binders.BindPartSizeToHeaders;
+import org.jclouds.glacier.domain.MultipartUploadMetadata;
+import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.fallbacks.FalseOnIllegalArgumentException;
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
import org.jclouds.glacier.functions.ParseArchiveIdHeader;
import org.jclouds.glacier.functions.ParseMultipartUploadIdHeader;
+import org.jclouds.glacier.functions.ParseMultipartUploadListFromHttpContent;
+import org.jclouds.glacier.functions.ParseMultipartUploadPartListFromHttpContent;
import org.jclouds.glacier.functions.ParseMultipartUploadTreeHashHeader;
import org.jclouds.glacier.functions.ParseVaultMetadataFromHttpContent;
import org.jclouds.glacier.functions.ParseVaultMetadataListFromHttpContent;
@@ -214,4 +218,48 @@
ListenableFuture<Boolean> abortMultipartUpload(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
@PathParam("uploadId") String uploadId);
+
+ /**
+ * @see GlacierClient#listParts
+ */
+ @Named("ListParts")
+ @GET
+ @Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
+ @ResponseParser(ParseMultipartUploadPartListFromHttpContent.class)
+ ListenableFuture<MultipartUploadMetadata> listParts(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
+ @PathParam("uploadId") String uploadId,
+ PaginationOptions options);
+
+ /**
+ * @see GlacierClient#listParts
+ */
+ @Named("ListParts")
+ @GET
+ @Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
+ @ResponseParser(ParseMultipartUploadPartListFromHttpContent.class)
+ ListenableFuture<MultipartUploadMetadata> listParts(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
+ @PathParam("uploadId") String uploadId);
+
+ /**
+ * @see GlacierClient#listMultipartUploads
+ */
+ @Named("ListMultipartUploads")
+ @GET
+ @Path("/-/vaults/{vault}/multipart-uploads")
+ @ResponseParser(ParseMultipartUploadListFromHttpContent.class)
+ ListenableFuture<PaginatedMultipartUploadCollection> listMultipartUploads(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
+ PaginationOptions options);
+
+ /**
+ * @see GlacierClient#listMultipartUploads
+ */
+ @Named("ListMultipartUploads")
+ @GET
+ @Path("/-/vaults/{vault}/multipart-uploads")
+ @ResponseParser(ParseMultipartUploadListFromHttpContent.class)
+ ListenableFuture<PaginatedMultipartUploadCollection> listMultipartUploads(
+ @ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName);
}
diff --git a/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java b/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
index 29f743d..162ec91 100644
--- a/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
+++ b/glacier/src/main/java/org/jclouds/glacier/GlacierClient.java
@@ -20,6 +20,8 @@
import java.net.URI;
import java.util.Map;
+import org.jclouds.glacier.domain.MultipartUploadMetadata;
+import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.options.PaginationOptions;
@@ -180,4 +182,40 @@
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-abort-upload.html" />
*/
boolean abortMultipartUpload(String vaultName, String uploadId);
+
+ /**
+ * Lists the multipart upload parts.
+ *
+ * @param vaultName
+ * Name of the Vault where the archive is going to be stored.
+ * @param uploadId
+ * Multipart upload identifier.
+ * @param options
+ * Options used for pagination.
+ * @return A MultipartUploadMetadata, containing an iterable part list with a marker.
+ * @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-list-parts.html" />
+ */
+ MultipartUploadMetadata listParts(String vaultName, String uploadId, PaginationOptions options);
+
+ /**
+ * Lists the multipart upload parts.
+ */
+ MultipartUploadMetadata listParts(String vaultName, String uploadId);
+
+ /**
+ * Lists the multipart uploads in a vault.
+ *
+ * @param vaultName
+ * Name of the Vault where the archive is going to be stored.
+ * @param options
+ * Options used for pagination.
+ * @return A PaginatedMultipartUploadCollection, containing an iterable multipart upload list with a marker.
+ * @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-list-uploads.html" />
+ */
+ PaginatedMultipartUploadCollection listMultipartUploads(String vaultName, PaginationOptions options);
+
+ /**
+ * Lists the multipart uploads in a vault.
+ */
+ PaginatedMultipartUploadCollection listMultipartUploads(String vaultName);
}
diff --git a/glacier/src/main/java/org/jclouds/glacier/domain/MultipartUploadMetadata.java b/glacier/src/main/java/org/jclouds/glacier/domain/MultipartUploadMetadata.java
new file mode 100644
index 0000000..1f68d07
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/domain/MultipartUploadMetadata.java
@@ -0,0 +1,141 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Date;
+import java.util.Iterator;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.glacier.options.PaginationOptions;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.ComparisonChain;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Defines the attributes needed for Multipart uploads. Extends IterableWithMarker to support requesting paginated
+ * multipart upload parts.
+ */
+public class MultipartUploadMetadata extends IterableWithMarker<PartMetadata> implements Comparable<MultipartUploadMetadata> {
+
+ @SerializedName("ArchiveDescription")
+ private final String archiveDescription;
+ @SerializedName("CreationDate")
+ private final Date creationDate;
+ @SerializedName("MultipartUploadId")
+ private final String multipartUploadId;
+ @SerializedName("PartSizeInBytes")
+ private final long partSizeInBytes;
+ @SerializedName("VaultARN")
+ private final String vaultARN;
+ @SerializedName("Parts")
+ private final Iterable<PartMetadata> parts;
+ @SerializedName("Marker")
+ private final String marker;
+
+ @ConstructorProperties({ "ArchiveDescription", "CreationDate", "MultipartUploadId", "PartSizeInBytes", "VaultARN",
+ "Parts", "Marker" })
+ public MultipartUploadMetadata(@Nullable String archiveDescription, Date creationDate, String multipartUploadId,
+ long partSizeInBytes, String vaultARN, @Nullable Iterable<PartMetadata> parts, @Nullable String marker) {
+ super();
+ this.archiveDescription = archiveDescription;
+ this.creationDate = (Date) checkNotNull(creationDate, "creationDate").clone();
+ this.multipartUploadId = checkNotNull(multipartUploadId, "multipartUploadId");
+ this.partSizeInBytes = partSizeInBytes;
+ this.vaultARN = checkNotNull(vaultARN, "vaultARN");
+ this.parts = parts;
+ this.marker = marker;
+ }
+
+ public String getArchiveDescription() {
+ return archiveDescription;
+ }
+
+ public Date getCreationDate() {
+ return (Date) creationDate.clone();
+ }
+
+ public String getMultipartUploadId() {
+ return multipartUploadId;
+ }
+
+ public long getPartSizeInBytes() {
+ return partSizeInBytes;
+ }
+
+ public long getPartSizeInMB() {
+ return partSizeInBytes >> 20;
+ }
+
+ public String getVaultARN() {
+ return vaultARN;
+ }
+
+ @Override
+ public Iterator<PartMetadata> iterator() {
+ return parts == null ? null : parts.iterator();
+ }
+
+ @Override
+ public Optional<Object> nextMarker() {
+ return Optional.<Object>fromNullable(marker);
+ }
+
+ public PaginationOptions nextPaginationOptions() {
+ return PaginationOptions.class.cast(nextMarker().get());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.archiveDescription, this.creationDate, this.multipartUploadId, this.partSizeInBytes,
+ this.vaultARN, this.marker, this.parts);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MultipartUploadMetadata other = (MultipartUploadMetadata) obj;
+
+ return Objects.equal(this.archiveDescription, other.archiveDescription)
+ && Objects.equal(this.creationDate, other.creationDate)
+ && Objects.equal(this.multipartUploadId, other.multipartUploadId)
+ && Objects.equal(this.partSizeInBytes, other.partSizeInBytes)
+ && Objects.equal(this.vaultARN, other.vaultARN)
+ && Objects.equal(this.marker, other.marker)
+ && Objects.equal(this.parts, other.parts);
+ }
+
+ @Override
+ public String toString() {
+ return "MultipartUploadMetadata [archiveDescription=" + archiveDescription + ", creationDate=" + creationDate
+ + ", multipartUploadId=" + multipartUploadId + ", partSizeInBytes=" + partSizeInBytes + ", vaultARN="
+ + vaultARN + ", marker=" + marker + ", parts=" + parts + "]";
+ }
+
+ @Override
+ public int compareTo(MultipartUploadMetadata o) {
+ return ComparisonChain.start().compare(this.creationDate, o.creationDate).result();
+ }
+}
diff --git a/glacier/src/main/java/org/jclouds/glacier/domain/PaginatedMultipartUploadCollection.java b/glacier/src/main/java/org/jclouds/glacier/domain/PaginatedMultipartUploadCollection.java
new file mode 100644
index 0000000..9555e41
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/domain/PaginatedMultipartUploadCollection.java
@@ -0,0 +1,60 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.util.Iterator;
+
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.glacier.options.PaginationOptions;
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Optional;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Paginated collection used to store multipart upload lists.
+ */
+public class PaginatedMultipartUploadCollection extends IterableWithMarker<MultipartUploadMetadata> {
+
+ @SerializedName("UploadsList")
+ private final Iterable<MultipartUploadMetadata> uploads;
+ @SerializedName("Marker")
+ private final String marker;
+
+ @ConstructorProperties({ "UploadsList", "Marker" })
+ public PaginatedMultipartUploadCollection(Iterable<MultipartUploadMetadata> uploads, @Nullable String marker) {
+ this.uploads = checkNotNull(uploads, "uploads");
+ this.marker = marker;
+ }
+
+ @Override
+ public Iterator<MultipartUploadMetadata> iterator() {
+ return uploads.iterator();
+ }
+
+ @Override
+ public Optional<Object> nextMarker() {
+ return Optional.<Object>fromNullable(marker);
+ }
+
+ public PaginationOptions nextPaginationOptions() {
+ return PaginationOptions.class.cast(nextMarker().get());
+ }
+}
diff --git a/glacier/src/main/java/org/jclouds/glacier/domain/PartMetadata.java b/glacier/src/main/java/org/jclouds/glacier/domain/PartMetadata.java
new file mode 100644
index 0000000..3a08447
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/domain/PartMetadata.java
@@ -0,0 +1,53 @@
+/*
+ * 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.domain;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+
+import org.jclouds.glacier.util.ContentRange;
+
+import com.google.common.hash.HashCode;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Defines the attributes needed for a multipart upload part.
+ */
+public class PartMetadata {
+
+ @SerializedName("SHA256TreeHash")
+ private final HashCode treeHash;
+ @SerializedName("RangeInBytes")
+ private final ContentRange range;
+
+ @ConstructorProperties({ "SHA256TreeHash", "RangeInBytes" })
+ public PartMetadata(String treeHash, String range) {
+ super();
+ this.treeHash = HashCode.fromString(checkNotNull(treeHash, "treeHash"));
+ this.range = ContentRange.fromString(checkNotNull(range, "range"));
+ }
+
+ public ContentRange getRange() {
+ return range;
+ }
+
+ public HashCode getTreeHash() {
+ return treeHash;
+ }
+
+}
diff --git a/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadListFromHttpContent.java b/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadListFromHttpContent.java
new file mode 100644
index 0000000..c2b5c23
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadListFromHttpContent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.functions;
+
+import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Parses the JSON multipart upload list from the HttpResponse.
+ */
+public class ParseMultipartUploadListFromHttpContent extends ParseJson<PaginatedMultipartUploadCollection> {
+
+ @Inject
+ public ParseMultipartUploadListFromHttpContent(Json json) {
+ super(json, TypeLiteral.get(PaginatedMultipartUploadCollection.class));
+ }
+}
diff --git a/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadPartListFromHttpContent.java b/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadPartListFromHttpContent.java
new file mode 100644
index 0000000..684ac7a
--- /dev/null
+++ b/glacier/src/main/java/org/jclouds/glacier/functions/ParseMultipartUploadPartListFromHttpContent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.functions;
+
+import org.jclouds.glacier.domain.MultipartUploadMetadata;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Parses the JSON multipart upload part list from the HttpResponse.
+ */
+public class ParseMultipartUploadPartListFromHttpContent extends ParseJson<MultipartUploadMetadata> {
+
+ @Inject
+ public ParseMultipartUploadPartListFromHttpContent(Json json) {
+ super(json, TypeLiteral.get(MultipartUploadMetadata.class));
+ }
+}
diff --git a/glacier/src/test/java/org/jclouds/glacier/GlacierClientLiveTest.java b/glacier/src/test/java/org/jclouds/glacier/GlacierClientLiveTest.java
index 100d990..a5142b1 100644
--- a/glacier/src/test/java/org/jclouds/glacier/GlacierClientLiveTest.java
+++ b/glacier/src/test/java/org/jclouds/glacier/GlacierClientLiveTest.java
@@ -16,16 +16,25 @@
*/
package org.jclouds.glacier;
+import static org.jclouds.glacier.util.TestUtils.MiB;
+import static org.jclouds.glacier.util.TestUtils.buildPayload;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.util.UUID;
import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.glacier.domain.MultipartUploadMetadata;
+import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
+import org.jclouds.glacier.util.ContentRange;
import org.testng.annotations.Test;
+import com.google.common.collect.ImmutableList;
+
/**
* Live test for Glacier.
*/
@@ -68,7 +77,43 @@
assertTrue(vaults.contains(api.describeVault(VAULT_NAME3)));
}
- @Test(groups = { "integration", "live" }, dependsOnMethods = { "testListAndDescribeVaults" })
+ @Test(groups = { "integration", "live" }, dependsOnMethods = { "testCreateVault" })
+ public void testListMultipartUploadsWithEmptyList() throws Exception {
+ assertEquals(api.listMultipartUploads(VAULT_NAME1).size(), 0);
+ }
+
+ @Test(groups = { "integration", "live" }, dependsOnMethods = { "testListMultipartUploadsWithEmptyList" })
+ public void testInitiateAndAbortMultipartUpload() throws Exception {
+ String uploadId = api.initiateMultipartUpload(VAULT_NAME1, 8);
+ try {
+ assertNotNull(uploadId);
+ } finally {
+ api.abortMultipartUpload(VAULT_NAME1, uploadId);
+ }
+ }
+
+ @Test(groups = { "integration", "live" }, dependsOnMethods = { "testInitiateAndAbortMultipartUpload" })
+ public void testListMultipartUploads() throws Exception {
+ long partSizeInMb = 1;
+ String uploadId = api.initiateMultipartUpload(VAULT_NAME1, partSizeInMb);
+ try {
+ assertNotNull(api.uploadPart(VAULT_NAME1, uploadId,
+ ContentRange.fromPartNumber(0, partSizeInMb), buildPayload(partSizeInMb * MiB)));
+ PaginatedMultipartUploadCollection uploads = api.listMultipartUploads(VAULT_NAME1);
+ ImmutableList.Builder<String> list = ImmutableList.builder();
+ for (MultipartUploadMetadata upload : uploads) {
+ list.add(upload.getMultipartUploadId());
+ }
+ assertTrue(list.build().contains(uploadId));
+ assertTrue(api.abortMultipartUpload(VAULT_NAME1, uploadId));
+ } finally {
+ api.abortMultipartUpload(VAULT_NAME1, uploadId);
+ }
+ }
+
+ @Test(groups = { "integration", "live" },
+ dependsOnMethods = { "testListAndDescribeVaults", "testListMultipartUploadsWithEmptyList",
+ "testInitiateAndAbortMultipartUpload", "testListMultipartUploads" })
public void testDeleteVault() throws Exception {
assertTrue(api.deleteVault(VAULT_NAME1));
assertTrue(api.deleteVault(VAULT_NAME2));
diff --git a/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java b/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
index 6932b25..d996bdf 100644
--- a/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
+++ b/glacier/src/test/java/org/jclouds/glacier/GlacierClientMockTest.java
@@ -37,7 +37,10 @@
import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.glacier.domain.MultipartUploadMetadata;
+import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
+import org.jclouds.glacier.domain.PartMetadata;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.options.PaginationOptions;
import org.jclouds.glacier.reference.GlacierHeaders;
@@ -85,6 +88,7 @@
private static final String DESCRIPTION = "test description";
private static final String MULTIPART_UPLOAD_LOCATION = VAULT_LOCATION + "/multipart-uploads/" + ARCHIVE_ID;
private static final String MULTIPART_UPLOAD_ID = "OW2fM5iVylEpFEMM9_HpKowRapC3vn5sSL39_396UW9zLFUWVrnRHaPjUJddQ5OxSHVXjYtrN47NBZ-khxOjyEXAMPLE";
+ private static final String MARKER = "xsQdFIRsfJr20CW2AbZBKpRZAFTZSJIMtL2hYf8mvp8dM0m4RUzlaqoEye6g3h3ecqB_zqwB7zLDMeSWhwo65re4C4Ev";
private static final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()));
@@ -305,4 +309,58 @@
assertEquals(server.takeRequest().getRequestLine(),
"DELETE /-/vaults/" + VAULT_NAME + "/multipart-uploads/" + MULTIPART_UPLOAD_ID + " " + HTTP);
}
+
+ @Test
+ public void testListParts() throws IOException, InterruptedException {
+ MockResponse mr = buildBaseResponse(200);
+ mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
+ mr.setBody(getResponseBody("/json/listPartsResponseBody.json"));
+ mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
+ server.enqueue(mr);
+
+ MultipartUploadMetadata result = client.listParts(VAULT_NAME, MULTIPART_UPLOAD_ID,
+ PaginationOptions.Builder.limit(1).marker("1001"));
+ assertEquals(result.getArchiveDescription(), "archive description 1");
+ assertEquals(result.getMultipartUploadId(), MULTIPART_UPLOAD_ID);
+ assertEquals(result.getPartSizeInBytes(), 4194304);
+ PartMetadata part = result.iterator().next();
+ assertEquals(part.getTreeHash(), HashCode.fromString("01d34dabf7be316472c93b1ef80721f5d4"));
+ assertEquals("4194304-8388607", part.getRange().getFrom() + "-" + part.getRange().getTo());
+ assertEquals(server.takeRequest().getRequestLine(),
+ "GET /-/vaults/examplevault/multipart-uploads/" + MULTIPART_UPLOAD_ID + "?limit=1&marker=1001 " + HTTP);
+ }
+
+ @Test
+ public void testListMultipartUploads() throws IOException, InterruptedException {
+ MockResponse mr = buildBaseResponse(200);
+ mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
+ mr.setBody(getResponseBody("/json/listMultipartUploadsResponseBody.json"));
+ mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
+ server.enqueue(mr);
+
+ PaginatedMultipartUploadCollection result = client.listMultipartUploads(
+ VAULT_NAME, PaginationOptions.Builder.limit(1).marker(MARKER));
+ MultipartUploadMetadata mum = result.iterator().next();
+ assertEquals(mum.getArchiveDescription(), "archive 2");
+ assertEquals(mum.getMultipartUploadId(),
+ "nPyGOnyFcx67qqX7E-0tSGiRi88hHMOwOxR-_jNyM6RjVMFfV29lFqZ3rNsSaWBugg6OP92pRtufeHdQH7ClIpSF6uJc");
+ assertEquals(mum.iterator(), null);
+ assertEquals(mum.getPartSizeInBytes(), 4194304);
+ assertEquals(mum.getVaultARN(), VAULT_ARN);
+ assertEquals(server.takeRequest().getRequestLine(),
+ "GET /-/vaults/examplevault/multipart-uploads?limit=1&marker=" + MARKER + " " + HTTP);
+ }
+
+ @Test
+ public void testListMultipartUploadsWithEmptyList() throws IOException, InterruptedException {
+ MockResponse mr = buildBaseResponse(200);
+ mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
+ mr.setBody(getResponseBody("/json/listMultipartUploadsWithEmptyListResponseBody.json"));
+ mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
+ server.enqueue(mr);
+
+ assertEquals(client.listMultipartUploads(VAULT_NAME, PaginationOptions.Builder.limit(1).marker(MARKER)).size(), 0);
+ assertEquals(server.takeRequest().getRequestLine(),
+ "GET /-/vaults/examplevault/multipart-uploads?limit=1&marker=" + MARKER + " " + HTTP);
+ }
}
diff --git a/glacier/src/test/resources/json/listMultipartUploadsResponseBody.json b/glacier/src/test/resources/json/listMultipartUploadsResponseBody.json
new file mode 100644
index 0000000..1524578
--- /dev/null
+++ b/glacier/src/test/resources/json/listMultipartUploadsResponseBody.json
@@ -0,0 +1,12 @@
+{
+ "Marker": "qt-RBst_7yO8gVIonIBsAxr2t-db0pE4s8MNeGjKjGdNpuU-cdSAcqG62guwV9r5jh5mLyFPzFEitTpNE7iQfHiu1XoV",
+ "UploadsList" : [
+ {
+ "ArchiveDescription": "archive 2",
+ "CreationDate": "2012-04-01T15:00:00.000Z",
+ "MultipartUploadId": "nPyGOnyFcx67qqX7E-0tSGiRi88hHMOwOxR-_jNyM6RjVMFfV29lFqZ3rNsSaWBugg6OP92pRtufeHdQH7ClIpSF6uJc",
+ "PartSizeInBytes": 4194304,
+ "VaultARN": "arn:aws:glacier:us-east-1:012345678901:vaults/examplevault"
+ }
+ ]
+}
diff --git a/glacier/src/test/resources/json/listMultipartUploadsWithEmptyListResponseBody.json b/glacier/src/test/resources/json/listMultipartUploadsWithEmptyListResponseBody.json
new file mode 100644
index 0000000..0e98a77
--- /dev/null
+++ b/glacier/src/test/resources/json/listMultipartUploadsWithEmptyListResponseBody.json
@@ -0,0 +1,4 @@
+{
+ "Marker": "qt-RBst_7yO8gVIonIBsAxr2t-db0pE4s8MNeGjKjGdNpuU-cdSAcqG62guwV9r5jh5mLyFPzFEitTpNE7iQfHiu1XoV",
+ "UploadsList" : []
+}
diff --git a/glacier/src/test/resources/json/listPartsResponseBody.json b/glacier/src/test/resources/json/listPartsResponseBody.json
new file mode 100644
index 0000000..cab3b85
--- /dev/null
+++ b/glacier/src/test/resources/json/listPartsResponseBody.json
@@ -0,0 +1,13 @@
+{
+ "ArchiveDescription" : "archive description 1",
+ "CreationDate" : "2012-03-20T17:03:43.221Z",
+ "Marker": "MfgsKHVjbQ6EldVl72bn3_n5h2TaGZQUO-Qb3B9j3TITf7WajQ",
+ "MultipartUploadId" : "OW2fM5iVylEpFEMM9_HpKowRapC3vn5sSL39_396UW9zLFUWVrnRHaPjUJddQ5OxSHVXjYtrN47NBZ-khxOjyEXAMPLE",
+ "PartSizeInBytes" : 4194304,
+ "Parts" :
+ [ {
+ "RangeInBytes" : "4194304-8388607",
+ "SHA256TreeHash" : "01d34dabf7be316472c93b1ef80721f5d4"
+ }],
+ "VaultARN" : "arn:aws:glacier:us-east-1:012345678901:vaults/demo1-vault"
+}