Add support for listing multipart uploads

Only supported in Azure, B2, and S3.  Fixes #118.
pull/139/merge
Andrew Gaul 2016-06-14 14:25:42 -07:00
rodzic 72138e1278
commit 187eb065aa
4 zmienionych plików z 99 dodań i 18 usunięć

Wyświetl plik

@ -61,6 +61,16 @@ final class Quirks {
"azureblob"
);
static final Set<String> NO_LIST_MULTIPART_UPLOADS = ImmutableSet.of(
"atmos",
"filesystem",
"google-cloud-storage",
"openstack-swift",
"rackspace-cloudfiles-uk",
"rackspace-cloudfiles-us",
"transient"
);
/** Blobstores which do not allow listing zero keys. */
static final Set<String> NO_LIST_ZERO_KEYS = ImmutableSet.of(
"atmos",

Wyświetl plik

@ -501,8 +501,8 @@ final class S3ProxyHandler extends AbstractHandler {
handleContainerLocation(response, blobStore, path[1]);
return;
} else if ("".equals(request.getParameter("uploads"))) {
handleListMultipartUploads(response, blobStore,
uploadId);
handleListMultipartUploads(request, response, blobStore,
path[1]);
return;
}
handleBlobList(request, response, blobStore, path[1]);
@ -974,11 +974,64 @@ final class S3ProxyHandler extends AbstractHandler {
}
}
private void handleListMultipartUploads(HttpServletResponse response,
BlobStore blobStore, String uploadId)
throws IOException, S3Exception {
// TODO: list all blobs starting with uploadId
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
private void handleListMultipartUploads(HttpServletRequest request,
HttpServletResponse response, BlobStore blobStore,
String container) throws IOException, S3Exception {
if (request.getParameter("delimiter") != null ||
request.getParameter("prefix") != null ||
request.getParameter("max-uploads") != null ||
request.getParameter("key-marker") != null ||
request.getParameter("upload-id-marker") != null) {
throw new UnsupportedOperationException();
}
List<MultipartUpload> uploads = blobStore.listMultipartUploads(
container);
try (Writer writer = response.getWriter()) {
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
writer);
xml.writeStartDocument();
xml.writeStartElement("ListMultipartUploadsResult");
xml.writeDefaultNamespace(AWS_XMLNS);
writeSimpleElement(xml, "Bucket", container);
// TODO: bogus values
xml.writeEmptyElement("KeyMarker");
xml.writeEmptyElement("UploadIdMarker");
xml.writeEmptyElement("NextKeyMarker");
xml.writeEmptyElement("NextUploadIdMarker");
xml.writeEmptyElement("Delimiter");
xml.writeEmptyElement("Prefix");
writeSimpleElement(xml, "MaxUploads", "1000");
writeSimpleElement(xml, "IsTruncated", "false");
for (MultipartUpload upload : uploads) {
xml.writeStartElement("Upload");
writeSimpleElement(xml, "Key", upload.blobName());
writeSimpleElement(xml, "UploadId", upload.id());
writeInitiatorStanza(xml);
writeOwnerStanza(xml);
writeSimpleElement(xml, "StorageClass", "STANDARD");
// TODO: bogus value
writeSimpleElement(xml, "Initiated",
blobStore.getContext().utils().date()
.iso8601DateFormat(new Date()));
xml.writeEndElement();
}
xml.writeEmptyElement("CommonPrefixes");
xml.writeEndElement();
xml.flush();
} catch (XMLStreamException xse) {
throw new IOException(xse);
}
}
private void handleContainerExists(HttpServletResponse response,
@ -1923,18 +1976,8 @@ final class S3ProxyHandler extends AbstractHandler {
writeSimpleElement(xml, "Key", encodeBlob(
encodingType, blobName));
writeSimpleElement(xml, "UploadId", uploadId);
// TODO: bogus values
xml.writeStartElement("Initiator");
writeSimpleElement(xml, "ID", FAKE_INITIATOR_ID);
writeSimpleElement(xml, "DisplayName",
FAKE_INITIATOR_DISPLAY_NAME);
xml.writeEndElement();
writeInitiatorStanza(xml);
writeOwnerStanza(xml);
writeSimpleElement(xml, "StorageClass", "STANDARD");
// TODO: pagination
@ -2604,6 +2647,18 @@ final class S3ProxyHandler extends AbstractHandler {
}
}
// TODO: bogus values
private static void writeInitiatorStanza(XMLStreamWriter xml)
throws XMLStreamException {
xml.writeStartElement("Initiator");
writeSimpleElement(xml, "ID", FAKE_INITIATOR_ID);
writeSimpleElement(xml, "DisplayName",
FAKE_INITIATOR_DISPLAY_NAME);
xml.writeEndElement();
}
// TODO: bogus values
private static void writeOwnerStanza(XMLStreamWriter xml)
throws XMLStreamException {

Wyświetl plik

@ -123,6 +123,14 @@ public final class JcloudsS3BlobIntegrationLiveTest
super.testCopyIfNoneMatchNegative();
}
@Override
public void testListMultipartUploads() throws Exception {
if (Quirks.NO_LIST_MULTIPART_UPLOADS.contains(blobStoreType)) {
throw new SkipException("list multipart uploads not supported");
}
super.testListMultipartUploads();
}
@Override
protected void checkCacheControl(Blob blob, String cacheControl) {
if (!Quirks.NO_CACHE_CONTROL_SUPPORT.contains(blobStoreType)) {

Wyświetl plik

@ -162,6 +162,14 @@ public final class JcloudsS3ClientLiveTest extends S3ClientLiveTest {
super.testUpdateObjectCannedACL();
}
@Override
public void testListMultipartUploads() throws Exception {
if (Quirks.NO_LIST_MULTIPART_UPLOADS.contains(blobStoreType)) {
throw new SkipException("list multipart uploads not supported");
}
super.testListMultipartUploads();
}
@Override
protected void assertCacheControl(S3Object newObject, String string) {
if (Quirks.NO_CACHE_CONTROL_SUPPORT.contains(blobStoreType)) {