Return lastModified and size when listing S3 parts

This commit is contained in:
Andrew Gaul 2017-02-16 18:52:44 -08:00
parent 43c0b3472a
commit d2041667d7
5 changed files with 143 additions and 2 deletions

View File

@ -75,6 +75,7 @@ import org.jclouds.s3.domain.BucketMetadata;
import org.jclouds.s3.domain.CannedAccessPolicy; import org.jclouds.s3.domain.CannedAccessPolicy;
import org.jclouds.s3.domain.DeleteResult; import org.jclouds.s3.domain.DeleteResult;
import org.jclouds.s3.domain.ListBucketResponse; import org.jclouds.s3.domain.ListBucketResponse;
import org.jclouds.s3.domain.ListMultipartUploadResponse;
import org.jclouds.s3.domain.ListMultipartUploadsResponse; import org.jclouds.s3.domain.ListMultipartUploadsResponse;
import org.jclouds.s3.domain.ObjectMetadata; import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.Payer; import org.jclouds.s3.domain.Payer;
@ -104,8 +105,10 @@ import org.jclouds.s3.xml.ListBucketHandler;
import org.jclouds.s3.xml.ListMultipartUploadsHandler; import org.jclouds.s3.xml.ListMultipartUploadsHandler;
import org.jclouds.s3.xml.LocationConstraintHandler; import org.jclouds.s3.xml.LocationConstraintHandler;
import org.jclouds.s3.xml.PartIdsFromHttpResponse; import org.jclouds.s3.xml.PartIdsFromHttpResponse;
import org.jclouds.s3.xml.PartIdsFromHttpResponseFull;
import org.jclouds.s3.xml.PayerHandler; import org.jclouds.s3.xml.PayerHandler;
import com.google.common.annotations.Beta;
import com.google.inject.Provides; import com.google.inject.Provides;
/** /**
@ -780,6 +783,8 @@ public interface S3Client extends Closeable {
@PathParam("key") String key, @QueryParam("uploadId") String uploadId, @PathParam("key") String key, @QueryParam("uploadId") String uploadId,
@BinderParam(BindPartIdsAndETagsToRequest.class) Map<Integer, String> parts); @BinderParam(BindPartIdsAndETagsToRequest.class) Map<Integer, String> parts);
/** @deprecated see #listMultipartPartsFull */
@Deprecated
@Named("ListMultipartParts") @Named("ListMultipartParts")
@GET @GET
@Path("/{key}") @Path("/{key}")
@ -788,6 +793,15 @@ public interface S3Client extends Closeable {
@BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName, @BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
@PathParam("key") String key, @QueryParam("uploadId") String uploadId); @PathParam("key") String key, @QueryParam("uploadId") String uploadId);
@Beta
@Named("ListMultipartParts")
@GET
@Path("/{key}")
@XMLResponseParser(PartIdsFromHttpResponseFull.class)
Map<Integer, ListMultipartUploadResponse> listMultipartPartsFull(@Bucket @EndpointParam(parser = AssignCorrectHostnameForBucket.class)
@BinderParam(BindAsHostPrefixIfConfigured.class) @ParamValidators(BucketNameValidator.class) String bucketName,
@PathParam("key") String key, @QueryParam("uploadId") String uploadId);
@Named("ListMultipartUploads") @Named("ListMultipartUploads")
@GET @GET
@Path("/") @Path("/")

View File

@ -0,0 +1,42 @@
/*
* 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.s3.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.Beta;
@AutoValue
@Beta
public abstract class ListMultipartUploadResponse {
public abstract int partNumber();
public abstract Date lastModified();
public abstract String eTag();
public abstract long size();
public static ListMultipartUploadResponse create(int partNumber, Date lastModified, String eTag, long size) {
checkArgument(partNumber > 0, "partNumber must be greater than zero, was: %s", partNumber);
checkNotNull(eTag, "eTag");
lastModified = (Date) checkNotNull(lastModified, "lastModified").clone();
checkArgument(size >= 0, "size must be positive, was: %s", size);
return new AutoValue_ListMultipartUploadResponse(partNumber, lastModified, eTag, size);
}
}

View File

@ -33,7 +33,10 @@ import com.google.common.collect.ImmutableMap;
* Parses the following XML document: * Parses the following XML document:
* <p/> * <p/>
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01" * ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
*
* @deprecated see PartIdsFromHttpResponseFull
*/ */
@Deprecated
public class PartIdsFromHttpResponse extends ParseSax.HandlerWithResult<Map<Integer, String>> { public class PartIdsFromHttpResponse extends ParseSax.HandlerWithResult<Map<Integer, String>> {
private final StringBuilder currentText = new StringBuilder(); private final StringBuilder currentText = new StringBuilder();

View File

@ -0,0 +1,79 @@
/*
* 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.s3.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import java.util.Date;
import java.util.Map;
import javax.inject.Inject;
import org.jclouds.date.DateService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.s3.domain.ListMultipartUploadResponse;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableMap;
/**
* Parses the following XML document:
* <p/>
* ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01"
*/
@Beta
public final class PartIdsFromHttpResponseFull extends ParseSax.HandlerWithResult<Map<Integer, ListMultipartUploadResponse>> {
private final StringBuilder currentText = new StringBuilder();
private final DateService dateParser;
private int partNumber;
private Date lastModfied;
private String eTag;
private long size;
private final ImmutableMap.Builder<Integer, ListMultipartUploadResponse> parts = ImmutableMap.builder();
@Inject
PartIdsFromHttpResponseFull(DateService dateParser) {
this.dateParser = dateParser;
}
public Map<Integer, ListMultipartUploadResponse> getResult() {
return parts.build();
}
public void endElement(String uri, String name, String qName) {
if (qName.equals("PartNumber")) {
partNumber = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("LastModified")) {
lastModfied = dateParser.iso8601DateOrSecondsDateParse(currentOrNull(currentText));
} else if (qName.equals("ETag")) {
eTag = currentText.toString().trim();
} else if (qName.equals("Size")) {
size = Long.parseLong(currentText.toString().trim());
} else if (qName.equals("Part")) {
parts.put(partNumber, ListMultipartUploadResponse.create(partNumber, lastModfied, eTag, size));
}
currentText.setLength(0);
}
public void characters(char[] ch, int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -56,6 +56,7 @@ import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.s3.domain.AccessControlList.Permission; import org.jclouds.s3.domain.AccessControlList.Permission;
import org.jclouds.s3.domain.CannedAccessPolicy; import org.jclouds.s3.domain.CannedAccessPolicy;
import org.jclouds.s3.domain.DeleteResult; import org.jclouds.s3.domain.DeleteResult;
import org.jclouds.s3.domain.ListMultipartUploadResponse;
import org.jclouds.s3.domain.ListMultipartUploadsResponse; import org.jclouds.s3.domain.ListMultipartUploadsResponse;
import org.jclouds.s3.domain.ObjectMetadata; import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.ObjectMetadataBuilder; import org.jclouds.s3.domain.ObjectMetadataBuilder;
@ -514,7 +515,7 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
String key = "constitution.txt"; String key = "constitution.txt";
String uploadId = getApi().initiateMultipartUpload(containerName, String uploadId = getApi().initiateMultipartUpload(containerName,
ObjectMetadataBuilder.create().key(key).contentMD5(oneHundredOneConstitutionsMD5.asBytes()).build()); ObjectMetadataBuilder.create().key(key).contentMD5(oneHundredOneConstitutionsMD5.asBytes()).build());
assertThat(getApi().listMultipartParts(containerName, key, uploadId)).isEmpty(); assertThat(getApi().listMultipartPartsFull(containerName, key, uploadId)).isEmpty();
byte[] buffer = oneHundredOneConstitutions.read(); byte[] buffer = oneHundredOneConstitutions.read();
assertEquals(oneHundredOneConstitutions.size(), (long) buffer.length); assertEquals(oneHundredOneConstitutions.size(), (long) buffer.length);
@ -534,7 +535,9 @@ public class S3ClientLiveTest extends BaseBlobStoreIntegrationTest {
// available there. // available there.
eTagOf1 = getApi().uploadPart(containerName, key, 1, uploadId, part1); eTagOf1 = getApi().uploadPart(containerName, key, 1, uploadId, part1);
} }
assertThat(getApi().listMultipartParts(containerName, key, uploadId)).containsOnlyKeys(1); Map<Integer, ListMultipartUploadResponse> map = getApi().listMultipartPartsFull(containerName, key, uploadId);
assertThat(map).containsOnlyKeys(1);
assertThat(map.get(1).eTag()).isEqualTo(eTagOf1);
getApi().completeMultipartUpload(containerName, key, uploadId, ImmutableMap.of(1, eTagOf1)); getApi().completeMultipartUpload(containerName, key, uploadId, ImmutableMap.of(1, eTagOf1));