You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by ch...@apache.org on 2020/03/11 08:49:37 UTC
[flink] branch release-1.10 updated: [FLINK-16014][s3] Force usage
of SAXParserFactory over XMLReaderFactory
This is an automated email from the ASF dual-hosted git repository.
chesnay pushed a commit to branch release-1.10
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/release-1.10 by this push:
new f1bd35c [FLINK-16014][s3] Force usage of SAXParserFactory over XMLReaderFactory
f1bd35c is described below
commit f1bd35c3fb3fecb9026d679d360c632d639f8499
Author: Arvid Heise <AH...@users.noreply.github.com>
AuthorDate: Wed Mar 11 09:31:10 2020 +0100
[FLINK-16014][s3] Force usage of SAXParserFactory over XMLReaderFactory
This avoids a ClassNotFound exception of the underlying XML reader class in plugin classloaders.
Root cause is a bug in JDK8 (JDK-8015099). XMLReaderFactory caches the class name independent of the classloader. On EMR, xercesImpl is on classpath (because of HDFS) and will be loaded at some point in time.
---
.../s3/model/transform/XmlResponsesSaxParser.java | 3767 ++++++++++++++++++++
flink-filesystems/flink-s3-fs-hadoop/pom.xml | 9 +
flink-filesystems/flink-s3-fs-presto/pom.xml | 9 +
tools/maven/suppressions.xml | 4 +
4 files changed, 3789 insertions(+)
diff --git a/flink-filesystems/flink-s3-fs-base/src/main/java/com/amazonaws/services/s3/model/transform/XmlResponsesSaxParser.java b/flink-filesystems/flink-s3-fs-base/src/main/java/com/amazonaws/services/s3/model/transform/XmlResponsesSaxParser.java
new file mode 100644
index 0000000..bc87b23
--- /dev/null
+++ b/flink-filesystems/flink-s3-fs-base/src/main/java/com/amazonaws/services/s3/model/transform/XmlResponsesSaxParser.java
@@ -0,0 +1,3767 @@
+/*
+ * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Portions copyright 2006-2009 James Murty. Please see LICENSE.txt
+ * for applicable license terms and NOTICE.txt for applicable notices.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License").
+ * You may not use this file except in compliance with the License.
+ * A copy of the License is located at
+ *
+ * http://aws.amazon.com/apache2.0
+ *
+ * or in the "license" file accompanying this file. This file 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 com.amazonaws.services.s3.model.transform;
+
+import com.amazonaws.services.s3.model.*;
+
+import static com.amazonaws.util.StringUtils.UTF8;
+
+import com.amazonaws.services.s3.model.inventory.ServerSideEncryptionKMS;
+import com.amazonaws.services.s3.model.inventory.ServerSideEncryptionS3;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.amazonaws.services.s3.model.lifecycle.LifecycleAndOperator;
+import com.amazonaws.services.s3.model.lifecycle.LifecycleFilter;
+import com.amazonaws.services.s3.model.lifecycle.LifecycleFilterPredicate;
+import com.amazonaws.services.s3.model.lifecycle.LifecyclePrefixPredicate;
+import com.amazonaws.services.s3.model.lifecycle.LifecycleTagPredicate;
+import com.amazonaws.services.s3.model.metrics.MetricsAndOperator;
+import com.amazonaws.services.s3.model.metrics.MetricsConfiguration;
+import com.amazonaws.services.s3.model.metrics.MetricsFilter;
+import com.amazonaws.services.s3.model.metrics.MetricsFilterPredicate;
+import com.amazonaws.services.s3.model.metrics.MetricsPrefixPredicate;
+import com.amazonaws.services.s3.model.metrics.MetricsTagPredicate;
+import com.amazonaws.services.s3.model.analytics.AnalyticsAndOperator;
+import com.amazonaws.services.s3.model.analytics.AnalyticsConfiguration;
+import com.amazonaws.services.s3.model.analytics.AnalyticsExportDestination;
+import com.amazonaws.services.s3.model.analytics.AnalyticsFilter;
+import com.amazonaws.services.s3.model.analytics.AnalyticsFilterPredicate;
+import com.amazonaws.services.s3.model.analytics.AnalyticsPrefixPredicate;
+import com.amazonaws.services.s3.model.analytics.AnalyticsS3BucketDestination;
+import com.amazonaws.services.s3.model.analytics.AnalyticsTagPredicate;
+import com.amazonaws.services.s3.model.analytics.StorageClassAnalysis;
+import com.amazonaws.services.s3.model.analytics.StorageClassAnalysisDataExport;
+import com.amazonaws.services.s3.model.inventory.InventoryConfiguration;
+import com.amazonaws.services.s3.model.inventory.InventoryDestination;
+import com.amazonaws.services.s3.model.inventory.InventoryFilter;
+import com.amazonaws.services.s3.model.inventory.InventoryPrefixPredicate;
+import com.amazonaws.services.s3.model.inventory.InventoryS3BucketDestination;
+import com.amazonaws.services.s3.model.inventory.InventorySchedule;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import com.amazonaws.SdkClientException;
+import com.amazonaws.services.s3.internal.Constants;
+import com.amazonaws.services.s3.internal.DeleteObjectsResponse;
+import com.amazonaws.services.s3.internal.ObjectExpirationResult;
+import com.amazonaws.services.s3.internal.S3RequesterChargedResult;
+import com.amazonaws.services.s3.internal.S3VersionResult;
+import com.amazonaws.services.s3.internal.ServerSideEncryptionResult;
+import com.amazonaws.services.s3.internal.ServiceUtils;
+import com.amazonaws.services.s3.model.BucketLifecycleConfiguration.NoncurrentVersionTransition;
+import com.amazonaws.services.s3.model.BucketLifecycleConfiguration.Rule;
+import com.amazonaws.services.s3.model.BucketLifecycleConfiguration.Transition;
+import com.amazonaws.services.s3.model.CORSRule.AllowedMethods;
+import com.amazonaws.services.s3.model.DeleteObjectsResult.DeletedObject;
+import com.amazonaws.services.s3.model.MultiObjectDeleteException.DeleteError;
+import com.amazonaws.services.s3.model.RequestPaymentConfiguration.Payer;
+import com.amazonaws.util.DateUtils;
+import com.amazonaws.util.SdkHttpUtils;
+import com.amazonaws.util.StringUtils;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+//
+// This class is copied from aws-java-sdk-s3 (Apache License 2.0)
+// in order to replaced {@code XMLReaderFactory.createXMLReader} by
+// {@code SAX_PARSER_FACTORY.newSAXParser().getXMLReader()} to
+// avoid JDK-8015099.
+//
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+/**
+ * XML Sax parser to read XML documents returned by S3 via the REST interface,
+ * converting these documents into objects.
+ */
+public class XmlResponsesSaxParser {
+ private static final Log log = LogFactory.getLog(XmlResponsesSaxParser.class);
+
+ private static final SAXParserFactory SAX_PARSER_FACTORY = SAXParserFactory.newInstance();
+
+ private XMLReader xr = null;
+
+ private boolean sanitizeXmlDocument = true;
+
+ /**
+ * Constructs the XML SAX parser.
+ *
+ * @throws SdkClientException
+ */
+ public XmlResponsesSaxParser() throws SdkClientException {
+ // Ensure we can load the XML Reader.
+ try {
+ xr = SAX_PARSER_FACTORY.newSAXParser().getXMLReader();
+ disableExternalResourceFetching(xr);
+ } catch (SAXException | ParserConfigurationException e) {
+ throw new SdkClientException("Couldn't initialize a SAX driver to create an XMLReader", e);
+ }
+ }
+
+ /**
+ * Parses an XML document from an input stream using a document handler.
+ *
+ * @param handler
+ * the handler for the XML document
+ * @param inputStream
+ * an input stream containing the XML document to parse
+ *
+ * @throws IOException
+ * on error reading from the input stream (ie connection reset)
+ * @throws SdkClientException
+ * on error with malformed XML, etc
+ */
+ protected void parseXmlInputStream(DefaultHandler handler, InputStream inputStream)
+ throws IOException {
+ try {
+
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing XML response document with handler: " + handler.getClass());
+ }
+
+ BufferedReader breader = new BufferedReader(new InputStreamReader(inputStream,
+ Constants.DEFAULT_ENCODING));
+ xr.setContentHandler(handler);
+ xr.setErrorHandler(handler);
+ xr.parse(new InputSource(breader));
+
+ } catch (IOException e) {
+ throw e;
+
+ } catch (Throwable t) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ if (log.isErrorEnabled()) {
+ log.error("Unable to close response InputStream up after XML parse failure", e);
+ }
+ }
+ throw new SdkClientException("Failed to parse XML document with handler "
+ + handler.getClass(), t);
+ }
+ }
+
+ protected InputStream sanitizeXmlDocument(DefaultHandler handler, InputStream inputStream)
+ throws IOException {
+
+ if (!sanitizeXmlDocument) {
+ // No sanitizing will be performed, return the original input stream unchanged.
+ return inputStream;
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Sanitizing XML document destined for handler " + handler.getClass());
+ }
+
+ InputStream sanitizedInputStream = null;
+
+ try {
+
+ /*
+ * Read object listing XML document from input stream provided into a
+ * string buffer, so we can replace troublesome characters before
+ * sending the document to the XML parser.
+ */
+ StringBuilder listingDocBuffer = new StringBuilder();
+ BufferedReader br = new BufferedReader(
+ new InputStreamReader(inputStream, Constants.DEFAULT_ENCODING));
+
+ char[] buf = new char[8192];
+ int read = -1;
+ while ((read = br.read(buf)) != -1) {
+ listingDocBuffer.append(buf, 0, read);
+ }
+ br.close();
+
+ /*
+ * Replace any carriage return (\r) characters with explicit XML
+ * character entities, to prevent the SAX parser from
+ * misinterpreting 0x0D characters as 0x0A and being unable to
+ * parse the XML.
+ */
+ String listingDoc = listingDocBuffer.toString().replaceAll("\r", "
");
+
+ sanitizedInputStream = new ByteArrayInputStream(
+ listingDoc.getBytes(UTF8));
+
+ } catch (IOException e) {
+ throw e;
+
+ } catch (Throwable t) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ if (log.isErrorEnabled()) {
+ log.error("Unable to close response InputStream after failure sanitizing XML document", e);
+ }
+ }
+ throw new SdkClientException("Failed to sanitize XML document destined for handler "
+ + handler.getClass(), t);
+ }
+ return sanitizedInputStream;
+ }
+ }
+
+ /**
+ * Disables certain dangerous features that attempt to automatically fetch DTDs
+ *
+ * See <a href="https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLReader">OWASP XXE Cheat Sheet</a>
+ * @param reader the reader to disable the features on
+ * @throws SAXNotRecognizedException
+ * @throws SAXNotSupportedException
+ */
+ private void disableExternalResourceFetching(XMLReader reader) throws SAXNotRecognizedException, SAXNotSupportedException {
+ reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false);
+ }
+
+ /**
+ * Checks if the specified string is empty or null and if so, returns null.
+ * Otherwise simply returns the string.
+ *
+ * @param s
+ * The string to check.
+ * @return Null if the specified string was null, or empty, otherwise
+ * returns the string the caller passed in.
+ */
+ private static String checkForEmptyString(String s) {
+ if (s == null) return null;
+ if (s.length() == 0) return null;
+
+ return s;
+ }
+
+ /**
+ * Safely parses the specified string as an integer and returns the value.
+ * If a NumberFormatException occurs while parsing the integer, an error is
+ * logged and -1 is returned.
+ *
+ * @param s
+ * The string to parse and return as an integer.
+ *
+ * @return The integer value of the specified string, otherwise -1 if there
+ * were any problems parsing the string as an integer.
+ */
+ private static int parseInt(String s) {
+ try {
+ return Integer.parseInt(s);
+ } catch (NumberFormatException nfe) {
+ log.error("Unable to parse integer value '" + s + "'", nfe);
+ }
+
+ return -1;
+ }
+
+ /**
+ * Safely parses the specified string as a long and returns the value. If a
+ * NumberFormatException occurs while parsing the long, an error is logged
+ * and -1 is returned.
+ *
+ * @param s
+ * The string to parse and return as a long.
+ *
+ * @return The long value of the specified string, otherwise -1 if there
+ * were any problems parsing the string as a long.
+ */
+ private static long parseLong(String s) {
+ try {
+ return Long.parseLong(s);
+ } catch (NumberFormatException nfe) {
+ log.error("Unable to parse long value '" + s + "'", nfe);
+ }
+
+ return -1;
+ }
+
+ /**
+ * Perform a url decode on the given value if specified.
+ * Return value by default;
+ */
+ private static String decodeIfSpecified(String value, boolean decode) {
+ return decode ? SdkHttpUtils.urlDecode(value) : value;
+ }
+
+ /**
+ * Parses a ListBucket response XML document from an input stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ * @throws SdkClientException
+ */
+ public ListBucketHandler parseListBucketObjectsResponse(InputStream inputStream, final boolean shouldSDKDecodeResponse)
+ throws IOException {
+ ListBucketHandler handler = new ListBucketHandler(shouldSDKDecodeResponse);
+ parseXmlInputStream(handler, sanitizeXmlDocument(handler, inputStream));
+
+ return handler;
+ }
+
+ /**
+ * Parses a ListBucketV2 response XML document from an input stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ * @throws SdkClientException
+ */
+ public ListObjectsV2Handler parseListObjectsV2Response(InputStream inputStream, final boolean shouldSDKDecodeResponse)
+ throws IOException {
+ ListObjectsV2Handler handler = new ListObjectsV2Handler(shouldSDKDecodeResponse);
+ parseXmlInputStream(handler, sanitizeXmlDocument(handler, inputStream));
+
+ return handler;
+ }
+
+ /**
+ * Parses a ListVersions response XML document from an input stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ * @throws SdkClientException
+ */
+ public ListVersionsHandler parseListVersionsResponse(InputStream inputStream, final boolean shouldSDKDecodeResponse)
+ throws IOException {
+ ListVersionsHandler handler = new ListVersionsHandler(shouldSDKDecodeResponse);
+ parseXmlInputStream(handler, sanitizeXmlDocument(handler, inputStream));
+ return handler;
+ }
+
+ /**
+ * Parses a ListAllMyBuckets response XML document from an input stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ * @throws SdkClientException
+ */
+ public ListAllMyBucketsHandler parseListMyBucketsResponse(InputStream inputStream)
+ throws IOException {
+ ListAllMyBucketsHandler handler = new ListAllMyBucketsHandler();
+ parseXmlInputStream(handler, sanitizeXmlDocument(handler, inputStream));
+ return handler;
+ }
+
+ /**
+ * Parses an AccessControlListHandler response XML document from an input
+ * stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ *
+ * @throws SdkClientException
+ */
+ public AccessControlListHandler parseAccessControlListResponse(InputStream inputStream)
+ throws IOException {
+ AccessControlListHandler handler = new AccessControlListHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ /**
+ * Parses a LoggingStatus response XML document for a bucket from an input
+ * stream.
+ *
+ * @param inputStream
+ * XML data input stream.
+ * @return the XML handler object populated with data parsed from the XML
+ * stream.
+ *
+ * @throws SdkClientException
+ */
+ public BucketLoggingConfigurationHandler parseLoggingStatusResponse(InputStream inputStream)
+ throws IOException {
+ BucketLoggingConfigurationHandler handler = new BucketLoggingConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public BucketLifecycleConfigurationHandler parseBucketLifecycleConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketLifecycleConfigurationHandler handler = new BucketLifecycleConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public BucketCrossOriginConfigurationHandler parseBucketCrossOriginConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketCrossOriginConfigurationHandler handler = new BucketCrossOriginConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public String parseBucketLocationResponse(InputStream inputStream)
+ throws IOException {
+ BucketLocationHandler handler = new BucketLocationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler.getLocation();
+ }
+
+ public BucketVersioningConfigurationHandler parseVersioningConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketVersioningConfigurationHandler handler = new BucketVersioningConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public BucketWebsiteConfigurationHandler parseWebsiteConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketWebsiteConfigurationHandler handler = new BucketWebsiteConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+
+ public BucketReplicationConfigurationHandler parseReplicationConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketReplicationConfigurationHandler handler = new BucketReplicationConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public BucketTaggingConfigurationHandler parseTaggingConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketTaggingConfigurationHandler handler = new BucketTaggingConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public BucketAccelerateConfigurationHandler parseAccelerateConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ BucketAccelerateConfigurationHandler handler = new BucketAccelerateConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public DeleteObjectsHandler parseDeletedObjectsResult(InputStream inputStream)
+ throws IOException {
+ DeleteObjectsHandler handler = new DeleteObjectsHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public CopyObjectResultHandler parseCopyObjectResponse(InputStream inputStream)
+ throws IOException {
+ CopyObjectResultHandler handler = new CopyObjectResultHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public CompleteMultipartUploadHandler parseCompleteMultipartUploadResponse(InputStream inputStream)
+ throws IOException {
+ CompleteMultipartUploadHandler handler = new CompleteMultipartUploadHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public InitiateMultipartUploadHandler parseInitiateMultipartUploadResponse(InputStream inputStream)
+ throws IOException {
+ InitiateMultipartUploadHandler handler = new InitiateMultipartUploadHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public ListMultipartUploadsHandler parseListMultipartUploadsResponse(InputStream inputStream)
+ throws IOException {
+ ListMultipartUploadsHandler handler = new ListMultipartUploadsHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public ListPartsHandler parseListPartsResponse(InputStream inputStream)
+ throws IOException {
+ ListPartsHandler handler = new ListPartsHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public GetObjectTaggingHandler parseObjectTaggingResponse(InputStream inputStream) throws IOException {
+ GetObjectTaggingHandler handler = new GetObjectTaggingHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public GetBucketMetricsConfigurationHandler parseGetBucketMetricsConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ GetBucketMetricsConfigurationHandler handler = new GetBucketMetricsConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public ListBucketMetricsConfigurationsHandler parseListBucketMetricsConfigurationsResponse(InputStream inputStream)
+ throws IOException {
+ ListBucketMetricsConfigurationsHandler handler = new ListBucketMetricsConfigurationsHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public GetBucketAnalyticsConfigurationHandler parseGetBucketAnalyticsConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ GetBucketAnalyticsConfigurationHandler handler = new GetBucketAnalyticsConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public ListBucketAnalyticsConfigurationHandler parseListBucketAnalyticsConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ ListBucketAnalyticsConfigurationHandler handler = new ListBucketAnalyticsConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public GetBucketInventoryConfigurationHandler parseGetBucketInventoryConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ GetBucketInventoryConfigurationHandler handler = new GetBucketInventoryConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ public ListBucketInventoryConfigurationsHandler parseBucketListInventoryConfigurationsResponse(InputStream inputStream)
+ throws IOException {
+ ListBucketInventoryConfigurationsHandler handler = new ListBucketInventoryConfigurationsHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ /**
+ * @param inputStream
+ *
+ * @return true if the bucket's is configured as Requester Pays, false if it
+ * is configured as Owner pays.
+ *
+ * @throws SdkClientException
+ */
+ public RequestPaymentConfigurationHandler parseRequestPaymentConfigurationResponse(InputStream inputStream)
+ throws IOException {
+ RequestPaymentConfigurationHandler handler = new RequestPaymentConfigurationHandler();
+ parseXmlInputStream(handler, inputStream);
+ return handler;
+ }
+
+ // ////////////
+ // Handlers //
+ // ////////////
+
+ /**
+ * Handler for ListBucket response XML documents.
+ */
+ public static class ListBucketHandler extends AbstractHandler {
+ private final ObjectListing objectListing = new ObjectListing();
+ private final boolean shouldSDKDecodeResponse;
+
+ private S3ObjectSummary currentObject = null;
+ private Owner currentOwner = null;
+ private String lastKey = null;
+
+ public ListBucketHandler(final boolean shouldSDKDecodeResponse) {
+ this.shouldSDKDecodeResponse = shouldSDKDecodeResponse;
+ }
+
+ public ObjectListing getObjectListing() {
+ return objectListing;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListBucketResult")) {
+ if (name.equals("Contents")) {
+ currentObject = new S3ObjectSummary();
+ currentObject.setBucketName(objectListing.getBucketName());
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents")) {
+ if (name.equals("Owner")) {
+ currentOwner = new Owner();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (atTopLevel()) {
+ if (name.equals("ListBucketResult")) {
+ /*
+ * S3 only includes the NextMarker XML element if the
+ * request specified a delimiter, but for consistency we'd
+ * like to always give easy access to the next marker if
+ * we're returning a list of results that's truncated.
+ */
+ if (objectListing.isTruncated()
+ && objectListing.getNextMarker() == null) {
+
+ String nextMarker = null;
+ if (!objectListing.getObjectSummaries().isEmpty()) {
+ nextMarker = objectListing.getObjectSummaries()
+ .get(objectListing.getObjectSummaries().size() - 1)
+ .getKey();
+
+ } else if (!objectListing.getCommonPrefixes().isEmpty()) {
+ nextMarker = objectListing.getCommonPrefixes()
+ .get(objectListing.getCommonPrefixes().size() - 1);
+ } else {
+ log.error("S3 response indicates truncated results, "
+ + "but contains no object summaries or "
+ + "common prefixes.");
+ }
+
+ objectListing.setNextMarker(nextMarker);
+ }
+ }
+ }
+
+ else if (in("ListBucketResult")) {
+ if (name.equals("Name")) {
+ objectListing.setBucketName(getText());
+ if (log.isDebugEnabled()) {
+ log.debug("Examining listing for bucket: "
+ + objectListing.getBucketName());
+ }
+
+ } else if (name.equals("Prefix")) {
+ objectListing.setPrefix(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("Marker")) {
+ objectListing.setMarker(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("NextMarker")) {
+ objectListing.setNextMarker(decodeIfSpecified
+ (getText(), shouldSDKDecodeResponse));
+
+ } else if (name.equals("MaxKeys")) {
+ objectListing.setMaxKeys(parseInt(getText()));
+
+ } else if (name.equals("Delimiter")) {
+ objectListing.setDelimiter(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("EncodingType")) {
+ objectListing.setEncodingType(shouldSDKDecodeResponse ?
+ null : checkForEmptyString(getText()));
+ } else if (name.equals("IsTruncated")) {
+ String isTruncatedStr =
+ StringUtils.lowerCase(getText());
+
+ if (isTruncatedStr.startsWith("false")) {
+ objectListing.setTruncated(false);
+ } else if (isTruncatedStr.startsWith("true")) {
+ objectListing.setTruncated(true);
+ } else {
+ throw new IllegalStateException(
+ "Invalid value for IsTruncated field: "
+ + isTruncatedStr);
+ }
+
+ } else if (name.equals("Contents")) {
+ objectListing.getObjectSummaries().add(currentObject);
+ currentObject = null;
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents")) {
+ if (name.equals("Key")) {
+ lastKey = getText();
+ currentObject.setKey(decodeIfSpecified
+ (lastKey, shouldSDKDecodeResponse));
+ } else if (name.equals("LastModified")) {
+ currentObject.setLastModified(
+ ServiceUtils.parseIso8601Date(getText()));
+
+ } else if (name.equals("ETag")) {
+ currentObject.setETag(
+ ServiceUtils.removeQuotes(getText()));
+
+ } else if (name.equals("Size")) {
+ currentObject.setSize(parseLong(getText()));
+
+ } else if (name.equals("StorageClass")) {
+ currentObject.setStorageClass(getText());
+
+ } else if (name.equals("Owner")) {
+ currentObject.setOwner(currentOwner);
+ currentOwner = null;
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents", "Owner")) {
+ if (name.equals("ID")) {
+ currentOwner.setId(getText());
+
+ } else if (name.equals("DisplayName")) {
+ currentOwner.setDisplayName(getText());
+ }
+ }
+
+ else if (in("ListBucketResult", "CommonPrefixes")) {
+ if (name.equals("Prefix")) {
+ objectListing.getCommonPrefixes().add
+ (decodeIfSpecified(getText(), shouldSDKDecodeResponse));
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for ListObjectsV2 response XML documents.
+ */
+ public static class ListObjectsV2Handler extends AbstractHandler {
+ private final ListObjectsV2Result result = new ListObjectsV2Result();
+ private final boolean shouldSDKDecodeResponse;
+
+ private S3ObjectSummary currentObject = null;
+ private Owner currentOwner = null;
+ private String lastKey = null;
+
+ public ListObjectsV2Handler(final boolean shouldSDKDecodeResponse) {
+ this.shouldSDKDecodeResponse = shouldSDKDecodeResponse;
+ }
+
+ public ListObjectsV2Result getResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListBucketResult")) {
+ if (name.equals("Contents")) {
+ currentObject = new S3ObjectSummary();
+ currentObject.setBucketName(result.getBucketName());
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents")) {
+ if (name.equals("Owner")) {
+ currentOwner = new Owner();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (atTopLevel()) {
+ if (name.equals("ListBucketResult")) {
+ /*
+ * S3 only includes the NextContinuationToken XML element if the
+ * request specified a delimiter, but for consistency we'd
+ * like to always give easy access to the next token if
+ * we're returning a list of results that's truncated.
+ */
+ if (result.isTruncated()
+ && result.getNextContinuationToken() == null) {
+
+ String nextContinuationToken = null;
+ if (!result.getObjectSummaries().isEmpty()) {
+ nextContinuationToken = result.getObjectSummaries()
+ .get(result.getObjectSummaries().size() - 1)
+ .getKey();
+
+ } else {
+ log.error("S3 response indicates truncated results, "
+ + "but contains no object summaries.");
+ }
+
+ result.setNextContinuationToken(nextContinuationToken);
+ }
+ }
+ }
+
+ else if (in("ListBucketResult")) {
+ if (name.equals("Name")) {
+ result.setBucketName(getText());
+ if (log.isDebugEnabled()) {
+ log.debug("Examining listing for bucket: "
+ + result.getBucketName());
+ }
+
+ } else if (name.equals("Prefix")) {
+ result.setPrefix(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("MaxKeys")) {
+ result.setMaxKeys(parseInt(getText()));
+
+ } else if (name.equals("NextContinuationToken")) {
+ result.setNextContinuationToken(getText());
+
+ } else if (name.equals("ContinuationToken")) {
+ result.setContinuationToken(getText());
+
+ } else if (name.equals("StartAfter")) {
+ result.setStartAfter(decodeIfSpecified
+ (getText(), shouldSDKDecodeResponse));
+
+ } else if (name.equals("KeyCount")) {
+ result.setKeyCount(parseInt(getText()));
+
+ } else if (name.equals("Delimiter")) {
+ result.setDelimiter(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("EncodingType")) {
+ result.setEncodingType(checkForEmptyString(getText()));
+ } else if (name.equals("IsTruncated")) {
+ String isTruncatedStr =
+ StringUtils.lowerCase(getText());
+
+ if (isTruncatedStr.startsWith("false")) {
+ result.setTruncated(false);
+ } else if (isTruncatedStr.startsWith("true")) {
+ result.setTruncated(true);
+ } else {
+ throw new IllegalStateException(
+ "Invalid value for IsTruncated field: "
+ + isTruncatedStr);
+ }
+
+ } else if (name.equals("Contents")) {
+ result.getObjectSummaries().add(currentObject);
+ currentObject = null;
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents")) {
+ if (name.equals("Key")) {
+ lastKey = getText();
+ currentObject.setKey(decodeIfSpecified
+ (lastKey, shouldSDKDecodeResponse));
+ } else if (name.equals("LastModified")) {
+ currentObject.setLastModified(
+ ServiceUtils.parseIso8601Date(getText()));
+
+ } else if (name.equals("ETag")) {
+ currentObject.setETag(
+ ServiceUtils.removeQuotes(getText()));
+
+ } else if (name.equals("Size")) {
+ currentObject.setSize(parseLong(getText()));
+
+ } else if (name.equals("StorageClass")) {
+ currentObject.setStorageClass(getText());
+
+ } else if (name.equals("Owner")) {
+ currentObject.setOwner(currentOwner);
+ currentOwner = null;
+ }
+ }
+
+ else if (in("ListBucketResult", "Contents", "Owner")) {
+ if (name.equals("ID")) {
+ currentOwner.setId(getText());
+
+ } else if (name.equals("DisplayName")) {
+ currentOwner.setDisplayName(getText());
+ }
+ }
+
+ else if (in("ListBucketResult", "CommonPrefixes")) {
+ if (name.equals("Prefix")) {
+ result.getCommonPrefixes().add
+ (decodeIfSpecified(getText(), shouldSDKDecodeResponse));
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for ListAllMyBuckets response XML documents. The document is
+ * parsed into {@link Bucket}s available via the {@link #getBuckets()}
+ * method.
+ */
+ public static class ListAllMyBucketsHandler extends AbstractHandler {
+
+ private final List<Bucket> buckets = new ArrayList<Bucket>();
+ private Owner bucketsOwner = null;
+
+ private Bucket currentBucket = null;
+
+ /**
+ * @return the buckets listed in the document.
+ */
+ public List<Bucket> getBuckets() {
+ return buckets;
+ }
+
+ /**
+ * @return the owner of the buckets.
+ */
+ public Owner getOwner() {
+ return bucketsOwner;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListAllMyBucketsResult")) {
+ if (name.equals("Owner")) {
+ bucketsOwner = new Owner();
+ }
+ } else if (in("ListAllMyBucketsResult", "Buckets")) {
+ if (name.equals("Bucket")) {
+ currentBucket = new Bucket();
+ currentBucket.setOwner(bucketsOwner);
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("ListAllMyBucketsResult", "Owner")) {
+ if (name.equals("ID")) {
+ bucketsOwner.setId(getText());
+
+ } else if (name.equals("DisplayName")) {
+ bucketsOwner.setDisplayName(getText());
+ }
+ }
+
+ else if (in("ListAllMyBucketsResult", "Buckets")) {
+ if (name.equals("Bucket")) {
+ buckets.add(currentBucket);
+ currentBucket = null;
+ }
+ }
+
+ else if (in("ListAllMyBucketsResult", "Buckets", "Bucket")) {
+ if (name.equals("Name")) {
+ currentBucket.setName(getText());
+
+ } else if (name.equals("CreationDate")) {
+ Date creationDate = DateUtils.parseISO8601Date(getText());
+ currentBucket.setCreationDate(creationDate);
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for AccessControlList response XML documents. The document is
+ * parsed into an {@link AccessControlList} object available via the
+ * {@link #getAccessControlList()} method.
+ */
+ public static class AccessControlListHandler extends AbstractHandler {
+
+ private final AccessControlList accessControlList =
+ new AccessControlList();
+
+ private Grantee currentGrantee = null;
+ private Permission currentPermission = null;
+
+ /**
+ * @return an object representing the ACL document.
+ */
+ public AccessControlList getAccessControlList() {
+ return accessControlList;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("AccessControlPolicy")) {
+ if (name.equals("Owner")) {
+ accessControlList.setOwner(new Owner());
+
+ }
+ }
+
+ else if (in("AccessControlPolicy", "AccessControlList", "Grant")) {
+ if (name.equals("Grantee")) {
+ String type = XmlResponsesSaxParser
+ .findAttributeValue( "xsi:type", attrs );
+
+ if ("AmazonCustomerByEmail".equals(type)) {
+ currentGrantee = new EmailAddressGrantee(null);
+ } else if ("CanonicalUser".equals(type)) {
+ currentGrantee = new CanonicalGrantee(null);
+ } else if ("Group".equals(type)) {
+ /*
+ * Nothing to do for GroupGrantees here since we
+ * can't construct an empty enum value early.
+ */
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("AccessControlPolicy", "Owner")) {
+ if (name.equals("ID")) {
+ accessControlList.getOwner().setId(getText());
+ } else if (name.equals("DisplayName")) {
+ accessControlList.getOwner().setDisplayName(getText());
+ }
+ }
+
+ else if (in("AccessControlPolicy", "AccessControlList")) {
+ if (name.equals("Grant")) {
+ accessControlList.grantPermission(
+ currentGrantee, currentPermission);
+
+ currentGrantee = null;
+ currentPermission = null;
+ }
+ }
+
+ else if (in("AccessControlPolicy", "AccessControlList", "Grant")) {
+ if (name.equals("Permission")) {
+ currentPermission = Permission.parsePermission(getText());
+ }
+ }
+
+ else if (in("AccessControlPolicy", "AccessControlList", "Grant", "Grantee")) {
+ if (name.equals("ID")) {
+ currentGrantee.setIdentifier(getText());
+
+ } else if (name.equals("EmailAddress")) {
+ currentGrantee.setIdentifier(getText());
+
+ } else if (name.equals("URI")) {
+ /*
+ * Only GroupGrantees contain an URI element in them, and we
+ * can't construct currentGrantee during startElement for a
+ * GroupGrantee since it's an enum.
+ */
+ currentGrantee = GroupGrantee.parseGroupGrantee(getText());
+
+ } else if (name.equals("DisplayName")) {
+ ((CanonicalGrantee) currentGrantee)
+ .setDisplayName(getText());
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for LoggingStatus response XML documents for a bucket. The
+ * document is parsed into an {@link BucketLoggingConfiguration} object available
+ * via the {@link #getBucketLoggingConfiguration()} method.
+ */
+ public static class BucketLoggingConfigurationHandler extends AbstractHandler {
+
+ private final BucketLoggingConfiguration bucketLoggingConfiguration =
+ new BucketLoggingConfiguration();
+
+ /**
+ * @return
+ * an object representing the bucket's LoggingStatus document.
+ */
+ public BucketLoggingConfiguration getBucketLoggingConfiguration() {
+ return bucketLoggingConfiguration;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("BucketLoggingStatus", "LoggingEnabled")) {
+ if (name.equals("TargetBucket")) {
+ bucketLoggingConfiguration
+ .setDestinationBucketName(getText());
+
+ } else if (name.equals("TargetPrefix")) {
+ bucketLoggingConfiguration
+ .setLogFilePrefix(getText());
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for CreateBucketConfiguration response XML documents for a
+ * bucket. The document is parsed into a String representing the bucket's
+ * location, available via the {@link #getLocation()} method.
+ */
+ public static class BucketLocationHandler extends AbstractHandler {
+
+ private String location = null;
+
+ /**
+ * @return
+ * the bucket's location.
+ */
+ public String getLocation() {
+ return location;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (atTopLevel()) {
+ if (name.equals("LocationConstraint")) {
+ String elementText = getText();
+ if (elementText.length() == 0) {
+ location = null;
+ } else {
+ location = elementText;
+ }
+ }
+ }
+ }
+ }
+
+ public static class CopyObjectResultHandler extends AbstractSSEHandler
+ implements ObjectExpirationResult, S3RequesterChargedResult, S3VersionResult {
+
+ // Data items for successful copy
+ private final CopyObjectResult result = new CopyObjectResult();
+
+ // Data items for failed copy
+ private String errorCode = null;
+ private String errorMessage = null;
+ private String errorRequestId = null;
+ private String errorHostId = null;
+ private boolean receivedErrorResponse = false;
+
+ @Override
+ protected ServerSideEncryptionResult sseResult() {
+ return result;
+ }
+
+ public Date getLastModified() {
+ return result.getLastModifiedDate();
+ }
+
+ @Override
+ public String getVersionId() {
+ return result.getVersionId();
+ }
+
+ @Override
+ public void setVersionId(String versionId) {
+ result.setVersionId(versionId);
+ }
+
+ @Override
+ public Date getExpirationTime() {
+ return result.getExpirationTime();
+ }
+
+ @Override
+ public void setExpirationTime(Date expirationTime) {
+ result.setExpirationTime(expirationTime);
+ }
+
+ @Override
+ public String getExpirationTimeRuleId() {
+ return result.getExpirationTimeRuleId();
+ }
+
+ @Override
+ public void setExpirationTimeRuleId(String expirationTimeRuleId) {
+ result.setExpirationTimeRuleId(expirationTimeRuleId);
+ }
+
+ public String getETag() {
+ return result.getETag();
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public String getErrorHostId() {
+ return errorHostId;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public String getErrorRequestId() {
+ return errorRequestId;
+ }
+
+ public boolean isErrorResponse() {
+ return receivedErrorResponse;
+ }
+
+ public boolean isRequesterCharged() {
+ return result.isRequesterCharged();
+ }
+
+ public void setRequesterCharged(boolean isRequesterCharged) {
+ result.setRequesterCharged(isRequesterCharged);
+ }
+
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (atTopLevel()) {
+ if (name.equals("CopyObjectResult") || name.equals("CopyPartResult")) {
+ receivedErrorResponse = false;
+ } else if (name.equals("Error")) {
+ receivedErrorResponse = true;
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("CopyObjectResult") || in ("CopyPartResult")) {
+ if (name.equals("LastModified")) {
+ result.setLastModifiedDate(ServiceUtils.parseIso8601Date(getText()));
+ } else if (name.equals("ETag")) {
+ result.setETag(ServiceUtils.removeQuotes(getText()));
+ }
+ }
+
+ else if (in("Error")) {
+ if (name.equals("Code")) {
+ errorCode = getText();
+ } else if (name.equals("Message")) {
+ errorMessage = getText();
+ } else if (name.equals("RequestId")) {
+ errorRequestId = getText();
+ } else if (name.equals("HostId")) {
+ errorHostId = getText();
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for parsing RequestPaymentConfiguration XML response associated
+ * with an Amazon S3 bucket. The XML response is parsed into a
+ * <code>RequestPaymentConfiguration</code> object.
+ */
+ public static class RequestPaymentConfigurationHandler extends AbstractHandler {
+
+ private String payer = null;
+
+ public RequestPaymentConfiguration getConfiguration(){
+ return new RequestPaymentConfiguration(Payer.valueOf(payer));
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("RequestPaymentConfiguration")) {
+ if (name.equals("Payer")) {
+ payer = getText();
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for ListVersionsResult XML document.
+ */
+ public static class ListVersionsHandler extends AbstractHandler {
+
+ private final VersionListing versionListing = new VersionListing();
+ private final boolean shouldSDKDecodeResponse;
+
+ private S3VersionSummary currentVersionSummary;
+ private Owner currentOwner;
+
+ public ListVersionsHandler(final boolean shouldSDKDecodeResponse) {
+ this.shouldSDKDecodeResponse = shouldSDKDecodeResponse;
+ }
+
+ public VersionListing getListing() {
+ return versionListing;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListVersionsResult")) {
+ if (name.equals("Version")) {
+ currentVersionSummary = new S3VersionSummary();
+ currentVersionSummary.setBucketName(
+ versionListing.getBucketName());
+
+ } else if (name.equals("DeleteMarker")) {
+ currentVersionSummary = new S3VersionSummary();
+ currentVersionSummary.setBucketName(
+ versionListing.getBucketName());
+ currentVersionSummary.setIsDeleteMarker(true);
+ }
+ }
+
+ else if (in("ListVersionsResult", "Version")
+ || in("ListVersionsResult", "DeleteMarker")) {
+ if (name.equals("Owner")) {
+ currentOwner = new Owner();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(
+ String uri,
+ String name,
+ String qName) {
+
+ if (in("ListVersionsResult")) {
+ if (name.equals("Name")) {
+ versionListing.setBucketName(getText());
+
+ } else if (name.equals("Prefix")) {
+ versionListing.setPrefix(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+ } else if (name.equals("KeyMarker")) {
+ versionListing.setKeyMarker(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+ } else if (name.equals("VersionIdMarker")) {
+ versionListing.setVersionIdMarker(checkForEmptyString(
+ getText()));
+
+ } else if (name.equals("MaxKeys")) {
+ versionListing.setMaxKeys(Integer.parseInt(getText()));
+
+ } else if (name.equals("Delimiter")) {
+ versionListing.setDelimiter(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("EncodingType")) {
+ versionListing.setEncodingType(shouldSDKDecodeResponse ?
+ null : checkForEmptyString(getText()));
+ } else if (name.equals("NextKeyMarker")) {
+ versionListing.setNextKeyMarker(decodeIfSpecified
+ (checkForEmptyString(getText()), shouldSDKDecodeResponse));
+
+ } else if (name.equals("NextVersionIdMarker")) {
+ versionListing.setNextVersionIdMarker(getText());
+
+ } else if (name.equals("IsTruncated")) {
+ versionListing.setTruncated("true".equals(getText()));
+
+ } else if (name.equals("Version")
+ || name.equals("DeleteMarker")) {
+
+ versionListing.getVersionSummaries()
+ .add(currentVersionSummary);
+
+ currentVersionSummary = null;
+ }
+ }
+
+ else if (in("ListVersionsResult", "CommonPrefixes")) {
+ if (name.equals("Prefix")) {
+ final String commonPrefix = checkForEmptyString(getText());
+ versionListing.getCommonPrefixes()
+ .add(shouldSDKDecodeResponse ?
+ SdkHttpUtils.urlDecode(commonPrefix) : commonPrefix);
+ }
+ }
+
+ else if (in("ListVersionsResult", "Version")
+ || in("ListVersionsResult", "DeleteMarker")) {
+
+ if (name.equals("Key")) {
+ currentVersionSummary.setKey(decodeIfSpecified(getText(), shouldSDKDecodeResponse));
+
+ } else if (name.equals("VersionId")) {
+ currentVersionSummary.setVersionId(getText());
+
+ } else if (name.equals("IsLatest")) {
+ currentVersionSummary.setIsLatest("true".equals(getText()));
+
+ } else if (name.equals("LastModified")) {
+ currentVersionSummary.setLastModified(
+ ServiceUtils.parseIso8601Date(getText()));
+
+ } else if (name.equals("ETag")) {
+ currentVersionSummary.setETag(
+ ServiceUtils.removeQuotes(getText()));
+
+ } else if (name.equals("Size")) {
+ currentVersionSummary.setSize(Long.parseLong(getText()));
+
+ } else if (name.equals("Owner")) {
+ currentVersionSummary.setOwner(currentOwner);
+ currentOwner = null;
+
+ } else if (name.equals("StorageClass")) {
+ currentVersionSummary.setStorageClass(getText());
+ }
+ }
+
+ else if (in("ListVersionsResult", "Version", "Owner")
+ || in("ListVersionsResult", "DeleteMarker", "Owner")) {
+
+ if (name.equals("ID")) {
+ currentOwner.setId(getText());
+ } else if (name.equals("DisplayName")) {
+ currentOwner.setDisplayName(getText());
+ }
+ }
+ }
+ }
+
+ public static class BucketWebsiteConfigurationHandler extends AbstractHandler {
+
+ private final BucketWebsiteConfiguration configuration =
+ new BucketWebsiteConfiguration(null);
+
+ private RoutingRuleCondition currentCondition = null;
+ private RedirectRule currentRedirectRule = null;
+ private RoutingRule currentRoutingRule = null;
+
+ public BucketWebsiteConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("WebsiteConfiguration")) {
+ if (name.equals("RedirectAllRequestsTo")) {
+ currentRedirectRule = new RedirectRule();
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RoutingRules")) {
+ if (name.equals("RoutingRule")) {
+ currentRoutingRule = new RoutingRule();
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RoutingRules", "RoutingRule")) {
+ if (name.equals("Condition")) {
+ currentCondition = new RoutingRuleCondition();
+ } else if (name.equals("Redirect")) {
+ currentRedirectRule = new RedirectRule();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("WebsiteConfiguration")) {
+ if (name.equals("RedirectAllRequestsTo")) {
+ configuration.setRedirectAllRequestsTo(currentRedirectRule);
+ currentRedirectRule = null;
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "IndexDocument")) {
+ if (name.equals("Suffix")) {
+ configuration.setIndexDocumentSuffix(getText());
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "ErrorDocument")) {
+ if (name.equals("Key")) {
+ configuration.setErrorDocument(getText());
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RoutingRules")) {
+ if (name.equals("RoutingRule")) {
+ configuration.getRoutingRules().add(currentRoutingRule);
+ currentRoutingRule = null;
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RoutingRules", "RoutingRule")) {
+ if (name.equals("Condition")) {
+ currentRoutingRule.setCondition(currentCondition);
+ currentCondition = null;
+ } else if (name.equals("Redirect")) {
+ currentRoutingRule.setRedirect(currentRedirectRule);
+ currentRedirectRule = null;
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RoutingRules", "RoutingRule", "Condition")) {
+ if (name.equals("KeyPrefixEquals")) {
+ currentCondition.setKeyPrefixEquals(getText());
+ } else if (name.equals("HttpErrorCodeReturnedEquals")) {
+ currentCondition.setHttpErrorCodeReturnedEquals(getText());
+ }
+ }
+
+ else if (in("WebsiteConfiguration", "RedirectAllRequestsTo")
+ || in("WebsiteConfiguration", "RoutingRules", "RoutingRule", "Redirect")) {
+
+ if (name.equals("Protocol")) {
+ currentRedirectRule.setProtocol(getText());
+
+ } else if (name.equals("HostName")) {
+ currentRedirectRule.setHostName(getText());
+
+ } else if (name.equals("ReplaceKeyPrefixWith")) {
+ currentRedirectRule.setReplaceKeyPrefixWith(getText());
+
+ } else if (name.equals("ReplaceKeyWith")) {
+ currentRedirectRule.setReplaceKeyWith(getText());
+
+ } else if (name.equals("HttpRedirectCode")) {
+ currentRedirectRule.setHttpRedirectCode(getText());
+ }
+ }
+ }
+ }
+
+ public static class BucketVersioningConfigurationHandler extends AbstractHandler {
+
+ private final BucketVersioningConfiguration configuration =
+ new BucketVersioningConfiguration();
+
+ public BucketVersioningConfiguration getConfiguration() { return configuration; }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("VersioningConfiguration")) {
+ if (name.equals("Status")) {
+ configuration.setStatus(getText());
+
+ } else if (name.equals("MfaDelete")) {
+ String mfaDeleteStatus = getText();
+
+ if (mfaDeleteStatus.equals("Disabled")) {
+ configuration.setMfaDeleteEnabled(false);
+ } else if (mfaDeleteStatus.equals("Enabled")) {
+ configuration.setMfaDeleteEnabled(true);
+ } else {
+ configuration.setMfaDeleteEnabled(null);
+ }
+ }
+ }
+ }
+ }
+
+ public static class BucketAccelerateConfigurationHandler extends AbstractHandler {
+
+ private final BucketAccelerateConfiguration configuration = new BucketAccelerateConfiguration((String) null);
+
+ public BucketAccelerateConfiguration getConfiguration() { return configuration; }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("AccelerateConfiguration")) {
+ if (name.equals("Status")) {
+ configuration.setStatus(getText());
+ }
+ }
+ }
+ }
+
+ /*
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <CompleteMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ * <Location>http://Example-Bucket.s3.amazonaws.com/Example-Object</Location>
+ * <Bucket>Example-Bucket</Bucket>
+ * <Key>Example-Object</Key>
+ * <ETag>"3858f62230ac3c915f300c664312c11f-9"</ETag>
+ * </CompleteMultipartUploadResult>
+ *
+ * Or if an error occurred while completing:
+ *
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <Error>
+ * <Code>InternalError</Code>
+ * <Message>We encountered an internal error. Please try again.</Message>
+ * <RequestId>656c76696e6727732072657175657374</RequestId>
+ * <HostId>Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==</HostId>
+ * </Error>
+ */
+ public static class CompleteMultipartUploadHandler extends AbstractSSEHandler
+ implements ObjectExpirationResult, S3VersionResult, S3RequesterChargedResult {
+ // Successful completion
+ private CompleteMultipartUploadResult result;
+
+ // Error during completion
+ private AmazonS3Exception ase;
+ private String hostId;
+ private String requestId;
+ private String errorCode;
+
+ @Override
+ protected ServerSideEncryptionResult sseResult() {
+ return result;
+ }
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#getExpirationTime()
+ */
+ @Override
+ public Date getExpirationTime() {
+ return result == null ? null : result.getExpirationTime();
+ }
+
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#setExpirationTime(java.util.Date)
+ */
+ @Override
+ public void setExpirationTime(Date expirationTime) {
+ if (result != null) {
+ result.setExpirationTime(expirationTime);
+ }
+ }
+
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#getExpirationTimeRuleId()
+ */
+ @Override
+ public String getExpirationTimeRuleId() {
+ return result == null ? null : result.getExpirationTimeRuleId();
+ }
+
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#setExpirationTimeRuleId(java.lang.String)
+ */
+ @Override
+ public void setExpirationTimeRuleId(String expirationTimeRuleId) {
+ if (result != null) {
+ result.setExpirationTimeRuleId(expirationTimeRuleId);
+ }
+ }
+
+ @Override
+ public void setVersionId(String versionId) {
+ if (result != null) {
+ result.setVersionId(versionId);
+ }
+ }
+
+ @Override
+ public String getVersionId() {
+ return result == null ? null : result.getVersionId();
+ }
+
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#isRequesterCharged()
+ */
+ public boolean isRequesterCharged() {
+ return result == null ? false : result.isRequesterCharged();
+ }
+
+ /**
+ * @see com.amazonaws.services.s3.model.CompleteMultipartUploadResult#setRequesterCharged(boolean)
+ */
+ public void setRequesterCharged(boolean isRequesterCharged) {
+ if (result != null) {
+ result.setRequesterCharged(isRequesterCharged);
+ }
+ }
+
+ public CompleteMultipartUploadResult getCompleteMultipartUploadResult() {
+ return result;
+ }
+
+ public AmazonS3Exception getAmazonS3Exception() {
+ return ase;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (atTopLevel()) {
+ if (name.equals("CompleteMultipartUploadResult")) {
+ result = new CompleteMultipartUploadResult();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (atTopLevel()) {
+ if (name.equals("Error")) {
+ if (ase != null) {
+ ase.setErrorCode(errorCode);
+ ase.setRequestId(requestId);
+ ase.setExtendedRequestId(hostId);
+ }
+ }
+ }
+
+ else if (in("CompleteMultipartUploadResult")) {
+ if (name.equals("Location")) {
+ result.setLocation(getText());
+ } else if (name.equals("Bucket")) {
+ result.setBucketName(getText());
+ } else if (name.equals("Key")) {
+ result.setKey(getText());
+ } else if (name.equals("ETag")) {
+ result.setETag(ServiceUtils.removeQuotes(getText()));
+ }
+ }
+
+ else if (in("Error")) {
+ if (name.equals("Code")) {
+ errorCode = getText();
+ } else if (name.equals("Message")) {
+ ase = new AmazonS3Exception(getText());
+ } else if (name.equals("RequestId")) {
+ requestId = getText();
+ } else if (name.equals("HostId")) {
+ hostId = getText();
+ }
+ }
+ }
+ }
+
+ /*
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ * <Bucket>example-bucket</Bucket>
+ * <Key>example-object</Key>
+ * <UploadId>VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA</UploadId>
+ * </InitiateMultipartUploadResult>
+ */
+ public static class InitiateMultipartUploadHandler extends AbstractHandler {
+
+ private final InitiateMultipartUploadResult result =
+ new InitiateMultipartUploadResult();
+
+ public InitiateMultipartUploadResult getInitiateMultipartUploadResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("InitiateMultipartUploadResult")) {
+ if (name.equals("Bucket")) {
+ result.setBucketName(getText());
+
+ } else if (name.equals("Key")) {
+ result.setKey(getText());
+
+ } else if (name.equals("UploadId")) {
+ result.setUploadId(getText());
+ }
+ }
+ }
+ }
+
+ /*
+ * HTTP/1.1 200 OK
+ * x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ * x-amz-request-id: 656c76696e6727732072657175657374
+ * Date: Tue, 16 Feb 2010 20:34:56 GMT
+ * Content-Length: 1330
+ * Connection: keep-alive
+ * Server: AmazonS3
+ *
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <ListMultipartUploadsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ * <Bucket>bucket</Bucket>
+ * <KeyMarker></KeyMarker>
+ * <Delimiter>/</Delimiter>
+ * <Prefix/>
+ * <UploadIdMarker></UploadIdMarker>
+ * <NextKeyMarker>my-movie.m2ts</NextKeyMarker>
+ * <NextUploadIdMarker>YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ</NextUploadIdMarker>
+ * <MaxUploads>3</MaxUploads>
+ * <IsTruncated>true</IsTruncated>
+ * <Upload>
+ * <Key>my-divisor</Key>
+ * <UploadId>XMgbGlrZSBlbHZpbmcncyBub3QgaGF2aW5nIG11Y2ggbHVjaw</UploadId>
+ * <Owner>
+ * <ID>b1d16700c70b0b05597d7acd6a3f92be</ID>
+ * <DisplayName>delving</DisplayName>
+ * </Owner>
+ * <StorageClass>STANDARD</StorageClass>
+ * <Initiated>Tue, 26 Jan 2010 19:42:19 GMT</Initiated>
+ * </Upload>
+ * <Upload>
+ * <Key>my-movie.m2ts</Key>
+ * <UploadId>VXBsb2FkIElEIGZvciBlbHZpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA</UploadId>
+ * <Owner>
+ * <ID>b1d16700c70b0b05597d7acd6a3f92be</ID>
+ * <DisplayName>delving</DisplayName>
+ * </Owner>
+ * <StorageClass>STANDARD</StorageClass>
+ * <Initiated>Tue, 16 Feb 2010 20:34:56 GMT</Initiated>
+ * </Upload>
+ * <Upload>
+ * <Key>my-movie.m2ts</Key>
+ * <UploadId>YW55IGlkZWEgd2h5IGVsdmluZydzIHVwbG9hZCBmYWlsZWQ</UploadId>
+ * <Owner>
+ * <ID>b1d16700c70b0b05597d7acd6a3f92be</ID>
+ * <DisplayName>delving</DisplayName>
+ * </Owner>
+ * <StorageClass>STANDARD</StorageClass>
+ * <Initiated>Wed, 27 Jan 2010 03:02:01 GMT</Initiated>
+ * </Upload>
+ * <CommonPrefixes>
+ * <Prefix>photos/</Prefix>
+ * </CommonPrefixes>
+ * <CommonPrefixes>
+ * <Prefix>videos/</Prefix>
+ * </CommonPrefixes>
+ * </ListMultipartUploadsResult>
+ */
+ public static class ListMultipartUploadsHandler extends AbstractHandler {
+
+ private final MultipartUploadListing result =
+ new MultipartUploadListing();
+
+ private MultipartUpload currentMultipartUpload;
+ private Owner currentOwner;
+
+ public MultipartUploadListing getListMultipartUploadsResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListMultipartUploadsResult")) {
+ if (name.equals("Upload")) {
+ currentMultipartUpload = new MultipartUpload();
+ }
+ } else if (in("ListMultipartUploadsResult", "Upload")) {
+ if (name.equals("Owner") || name.equals("Initiator")) {
+ currentOwner = new Owner();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("ListMultipartUploadsResult")) {
+ if (name.equals("Bucket")) {
+ result.setBucketName(getText());
+ } else if (name.equals("KeyMarker")) {
+ result.setKeyMarker(checkForEmptyString(getText()));
+ } else if (name.equals("Delimiter")) {
+ result.setDelimiter(checkForEmptyString(getText()));
+ } else if (name.equals("Prefix")) {
+ result.setPrefix(checkForEmptyString(getText()));
+ } else if (name.equals("UploadIdMarker")) {
+ result.setUploadIdMarker(checkForEmptyString(getText()));
+ } else if (name.equals("NextKeyMarker")) {
+ result.setNextKeyMarker(checkForEmptyString(getText()));
+ } else if (name.equals("NextUploadIdMarker")) {
+ result.setNextUploadIdMarker(checkForEmptyString(getText()));
+ } else if (name.equals("MaxUploads")) {
+ result.setMaxUploads(Integer.parseInt(getText()));
+ } else if (name.equals("EncodingType")) {
+ result.setEncodingType(checkForEmptyString(getText()));
+ } else if (name.equals("IsTruncated")) {
+ result.setTruncated(Boolean.parseBoolean(getText()));
+ } else if (name.equals("Upload")) {
+ result.getMultipartUploads().add(currentMultipartUpload);
+ currentMultipartUpload = null;
+ }
+ }
+
+ else if (in("ListMultipartUploadsResult", "CommonPrefixes")) {
+ if (name.equals("Prefix")) {
+ result.getCommonPrefixes().add(getText());
+ }
+ }
+
+ else if (in("ListMultipartUploadsResult", "Upload")) {
+ if (name.equals("Key")) {
+ currentMultipartUpload.setKey(getText());
+ } else if (name.equals("UploadId")) {
+ currentMultipartUpload.setUploadId(getText());
+ } else if (name.equals("Owner")) {
+ currentMultipartUpload.setOwner(currentOwner);
+ currentOwner = null;
+ } else if (name.equals("Initiator")) {
+ currentMultipartUpload.setInitiator(currentOwner);
+ currentOwner = null;
+ } else if (name.equals("StorageClass")) {
+ currentMultipartUpload.setStorageClass(getText());
+ } else if (name.equals("Initiated")) {
+ currentMultipartUpload.setInitiated(
+ ServiceUtils.parseIso8601Date(getText()));
+ }
+ }
+
+ else if (in("ListMultipartUploadsResult", "Upload", "Owner")
+ || in("ListMultipartUploadsResult", "Upload", "Initiator")) {
+
+ if (name.equals("ID")) {
+ currentOwner.setId(checkForEmptyString(getText()));
+ } else if (name.equals("DisplayName")) {
+ currentOwner.setDisplayName(checkForEmptyString(getText()));
+ }
+ }
+ }
+ }
+
+ /*
+ * HTTP/1.1 200 OK
+ * x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ * x-amz-request-id: 656c76696e6727732072657175657374
+ * Date: Tue, 16 Feb 2010 20:34:56 GMT
+ * Content-Length: 985
+ * Connection: keep-alive
+ * Server: AmazonS3
+ *
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <ListPartsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ * <Bucket>example-bucket</Bucket>
+ * <Key>example-object</Key>
+ * <UploadId>XXBsb2FkIElEIGZvciBlbHZpbmcncyVcdS1tb3ZpZS5tMnRzEEEwbG9hZA</UploadId>
+ * <Owner>
+ * <ID>x1x16700c70b0b05597d7ecd6a3f92be</ID>
+ * <DisplayName>username</DisplayName>
+ * </Owner>
+ * <Initiator>
+ * <ID>x1x16700c70b0b05597d7ecd6a3f92be</ID>
+ * <DisplayName>username</DisplayName>
+ * </Initiator>
+ * <StorageClass>STANDARD</StorageClass>
+ * <PartNumberMarker>1</PartNumberMarker>
+ * <NextPartNumberMarker>3</NextPartNumberMarker>
+ * <MaxParts>2</MaxParts>
+ * <IsTruncated>true</IsTruncated>
+ * <Part>
+ * <PartNumber>2</PartNumber>
+ * <LastModified>Wed, 27 Jan 2010 03:02:03 GMT</LastModified>
+ * <ETag>"7778aef83f66abc1fa1e8477f296d394"</ETag>
+ * <Size>10485760</Size>
+ * </Part>
+ * <Part>
+ * <PartNumber>3</PartNumber>
+ * <LastModified>Wed, 27 Jan 2010 03:02:02 GMT</LastModified>
+ * <ETag>"aaaa18db4cc2f85cedef654fccc4a4x8"</ETag>
+ * <Size>10485760</Size>
+ * </Part>
+ * </ListPartsResult>
+ */
+ public static class ListPartsHandler extends AbstractHandler {
+
+ private final PartListing result = new PartListing();
+
+ private PartSummary currentPart;
+ private Owner currentOwner;
+
+ public PartListing getListPartsResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListPartsResult")) {
+ if (name.equals("Part")) {
+ currentPart = new PartSummary();
+ } else if (name.equals("Owner") || name.equals("Initiator")) {
+ currentOwner = new Owner();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("ListPartsResult")) {
+ if (name.equals("Bucket")) {
+ result.setBucketName(getText());
+ } else if (name.equals("Key")) {
+ result.setKey(getText());
+ } else if (name.equals("UploadId")) {
+ result.setUploadId(getText());
+ } else if (name.equals("Owner")) {
+ result.setOwner(currentOwner);
+ currentOwner = null;
+ } else if (name.equals("Initiator")) {
+ result.setInitiator(currentOwner);
+ currentOwner = null;
+ } else if (name.equals("StorageClass")) {
+ result.setStorageClass(getText());
+ } else if (name.equals("PartNumberMarker")) {
+ result.setPartNumberMarker(parseInteger(getText()));
+ } else if (name.equals("NextPartNumberMarker")) {
+ result.setNextPartNumberMarker(parseInteger(getText()));
+ } else if (name.equals("MaxParts")) {
+ result.setMaxParts(parseInteger(getText()));
+ } else if (name.equals("EncodingType")) {
+ result.setEncodingType(checkForEmptyString(getText()));
+ } else if (name.equals("IsTruncated")) {
+ result.setTruncated(Boolean.parseBoolean(getText()));
+ } else if (name.equals("Part")) {
+ result.getParts().add(currentPart);
+ currentPart = null;
+ }
+ }
+
+ else if (in("ListPartsResult", "Part")) {
+ if (name.equals("PartNumber")) {
+ currentPart.setPartNumber(Integer.parseInt(getText()));
+ } else if (name.equals("LastModified")) {
+ currentPart.setLastModified(
+ ServiceUtils.parseIso8601Date(getText()));
+ } else if (name.equals("ETag")) {
+ currentPart.setETag(ServiceUtils.removeQuotes(getText()));
+ } else if (name.equals("Size")) {
+ currentPart.setSize(Long.parseLong(getText()));
+ }
+ }
+
+ else if (in("ListPartsResult", "Owner")
+ || in("ListPartsResult", "Initiator")) {
+
+ if (name.equals("ID")) {
+ currentOwner.setId(checkForEmptyString(getText()));
+ } else if (name.equals("DisplayName")) {
+ currentOwner.setDisplayName(checkForEmptyString(getText()));
+ }
+ }
+ }
+
+ private Integer parseInteger(String text) {
+ text = checkForEmptyString(getText());
+ if (text == null) return null;
+ return Integer.parseInt(text);
+ }
+ }
+
+ /**
+ * Handler for parsing the get replication configuration response from
+ * Amazon S3. Sample HTTP response is given below.
+ *
+ * <pre>
+ * <ReplicationConfiguration>
+ * <Rule>
+ * <ID>replication-rule-1-1421862858808</ID>
+ * <Prefix>testPrefix1</Prefix>
+ * <Status>Enabled</Status>
+ * <Destination>
+ * <Bucket>bucketARN</Bucket>
+ * </Destination>
+ * </Rule>
+ * <Rule>
+ * <ID>replication-rule-2-1421862858808</ID>
+ * <Prefix>testPrefix2</Prefix>
+ * <Status>Disabled</Status>
+ * <Destination>
+ * <Bucket>arn:aws:s3:::bucket-dest-replication-integ-test-1421862858808</Bucket>
+ * </Destination>
+ * </Rule>
+ * </ReplicationConfiguration>
+ * </pre>
+ */
+ public static class BucketReplicationConfigurationHandler extends
+ AbstractHandler {
+
+ private final BucketReplicationConfiguration bucketReplicationConfiguration = new BucketReplicationConfiguration();
+ private String currentRuleId;
+ private ReplicationRule currentRule;
+ private ReplicationDestinationConfig destinationConfig;
+ private AccessControlTranslation accessControlTranslation;
+ private EncryptionConfiguration encryptionConfiguration;
+ private SourceSelectionCriteria sourceSelectionCriteria;
+ private SseKmsEncryptedObjects sseKmsEncryptedObjects;
+ private static final String REPLICATION_CONFIG = "ReplicationConfiguration";
+ private static final String ROLE = "Role";
+ private static final String RULE = "Rule";
+ private static final String DESTINATION = "Destination";
+ private static final String ID = "ID";
+ private static final String PREFIX = "Prefix";
+ private static final String STATUS = "Status";
+ private static final String BUCKET = "Bucket";
+ private static final String STORAGECLASS = "StorageClass";
+ private static final String ACCOUNT = "Account";
+ private static final String ACCESS_CONTROL_TRANSLATION = "AccessControlTranslation";
+ private static final String OWNER = "Owner";
+ private static final String ENCRYPTION_CONFIGURATION = "EncryptionConfiguration";
+ private static final String REPLICA_KMS_KEY_ID = "ReplicaKmsKeyID";
+ private static final String SOURCE_SELECTION_CRITERIA = "SourceSelectionCriteria";
+ private static final String SSE_KMS_ENCRYPTED_OBJECTS = "SseKmsEncryptedObjects";
+
+ public BucketReplicationConfiguration getConfiguration() {
+ return bucketReplicationConfiguration;
+ }
+
+ @Override
+ protected void doStartElement(String uri, String name, String qName,
+ Attributes attrs) {
+
+ if (in(REPLICATION_CONFIG)) {
+ if (name.equals(RULE)) {
+ currentRule = new ReplicationRule();
+ }
+ } else if (in(REPLICATION_CONFIG, RULE)) {
+ if (name.equals(DESTINATION)) {
+ destinationConfig = new ReplicationDestinationConfig();
+ } else if (name.equals(SOURCE_SELECTION_CRITERIA)) {
+ sourceSelectionCriteria = new SourceSelectionCriteria();
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, DESTINATION)) {
+ if (name.equals(ACCESS_CONTROL_TRANSLATION)) {
+ accessControlTranslation = new AccessControlTranslation();
+ } else if (name.equals(ENCRYPTION_CONFIGURATION)) {
+ encryptionConfiguration = new EncryptionConfiguration();
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, SOURCE_SELECTION_CRITERIA)) {
+ if (name.equals(SSE_KMS_ENCRYPTED_OBJECTS)) {
+ sseKmsEncryptedObjects = new SseKmsEncryptedObjects();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in(REPLICATION_CONFIG)) {
+ if (name.equals(RULE)) {
+ bucketReplicationConfiguration.addRule(currentRuleId,
+ currentRule);
+ currentRule = null;
+ currentRuleId = null;
+ destinationConfig = null;
+ sseKmsEncryptedObjects = null;
+ accessControlTranslation = null;
+ encryptionConfiguration = null;
+ } else if (name.equals(ROLE)) {
+ bucketReplicationConfiguration.setRoleARN(getText());
+ }
+ } else if (in(REPLICATION_CONFIG, RULE)) {
+ if (name.equals(ID)) {
+ currentRuleId = getText();
+ } else if (name.equals(PREFIX)) {
+ currentRule.setPrefix(getText());
+ } else if (name.equals(SOURCE_SELECTION_CRITERIA)) {
+ currentRule.setSourceSelectionCriteria(sourceSelectionCriteria);
+ } else {
+ if (name.equals(STATUS)) {
+ currentRule.setStatus(getText());
+
+ } else if (name.equals(DESTINATION)) {
+ currentRule.setDestinationConfig(destinationConfig);
+ }
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, SOURCE_SELECTION_CRITERIA)) {
+ if (name.equals(SSE_KMS_ENCRYPTED_OBJECTS)) {
+ sourceSelectionCriteria.setSseKmsEncryptedObjects(sseKmsEncryptedObjects);
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, SOURCE_SELECTION_CRITERIA, SSE_KMS_ENCRYPTED_OBJECTS)) {
+ if (name.equals(STATUS)) {
+ sseKmsEncryptedObjects.setStatus(getText());
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, DESTINATION)) {
+ if (name.equals(BUCKET)) {
+ destinationConfig.setBucketARN(getText());
+ } else if (name.equals(STORAGECLASS)) {
+ destinationConfig.setStorageClass(getText());
+ } else if (name.equals(ACCOUNT)) {
+ destinationConfig.setAccount(getText());
+ } else if (name.equals(ACCESS_CONTROL_TRANSLATION)) {
+ destinationConfig.setAccessControlTranslation(accessControlTranslation);
+ } else if (name.equals(ENCRYPTION_CONFIGURATION)) {
+ destinationConfig.setEncryptionConfiguration(encryptionConfiguration);
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, DESTINATION, ACCESS_CONTROL_TRANSLATION)) {
+ if (name.equals(OWNER)) {
+ accessControlTranslation.setOwner(getText());
+ }
+ } else if (in(REPLICATION_CONFIG, RULE, DESTINATION, ENCRYPTION_CONFIGURATION)) {
+ if (name.equals(REPLICA_KMS_KEY_ID)) {
+ encryptionConfiguration.setReplicaKmsKeyID(getText());
+ }
+ }
+ }
+ }
+
+ public static class BucketTaggingConfigurationHandler extends AbstractHandler {
+
+ private final BucketTaggingConfiguration configuration =
+ new BucketTaggingConfiguration();
+
+ private Map<String, String> currentTagSet;
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public BucketTaggingConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("Tagging")) {
+ if (name.equals("TagSet")) {
+ currentTagSet = new HashMap<String, String>();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("Tagging")) {
+ if (name.equals("TagSet")) {
+ configuration.getAllTagSets()
+ .add(new TagSet(currentTagSet));
+ currentTagSet = null;
+ }
+ }
+
+ else if (in("Tagging", "TagSet")) {
+ if (name.equals("Tag")) {
+ if (currentTagKey != null && currentTagValue != null) {
+ currentTagSet.put(currentTagKey, currentTagValue);
+ }
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("Tagging", "TagSet", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+ }
+ }
+
+ /**
+ * Handler for unmarshalling the response from GET Object Tagging.
+ *
+ * <Tagging>
+ * <TagSet>
+ * <Tag>
+ * <Key>Foo</Key>
+ * <Value>1</Value>
+ * </Tag>
+ * <Tag>
+ * <Key>Bar</Key>
+ * <Value>2</Value>
+ * </Tag>
+ * <Tag>
+ * <Key>Baz</Key>
+ * <Value>3</Value>
+ * </Tag>
+ * </TagSet>
+ * </Tagging>
+ */
+ public static class GetObjectTaggingHandler extends AbstractHandler {
+ private GetObjectTaggingResult getObjectTaggingResult;
+ private List<Tag> tagSet;
+ private String currentTagValue;
+ private String currentTagKey;
+
+ public GetObjectTaggingResult getResult() {
+ return getObjectTaggingResult;
+ }
+
+
+ @Override
+ protected void doStartElement(String uri, String name, String qName, Attributes attrs) {
+ if (in("Tagging")) {
+ if (name.equals("TagSet")) {
+ tagSet = new ArrayList<Tag>();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("Tagging")) {
+ if (name.equals("TagSet")) {
+ getObjectTaggingResult = new GetObjectTaggingResult(tagSet);
+ tagSet = null;
+ }
+ }
+ if (in("Tagging", "TagSet")) {
+ if (name.equals("Tag")) {
+ tagSet.add(new Tag(currentTagKey, currentTagValue));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ } else if (in("Tagging", "TagSet", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+ }
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ x-amz-request-id: 656c76696e6727732072657175657374
+ Date: Tue, 20 Sep 2012 20:34:56 GMT
+ Content-Type: application/xml
+ Transfer-Encoding: chunked
+ Connection: keep-alive
+ Server: AmazonS3
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <DeleteResult>
+ <Deleted>
+ <Key>Key</Key>
+ <VersionId>Version</VersionId>
+ </Deleted>
+ <Error>
+ <Key>Key</Key>
+ <VersionId>Version</VersionId>
+ <Code>Code</Code>
+ <Message>Message</Message>
+ </Error>
+ <Deleted>
+ <Key>Key</Key>
+ <DeleteMarker>true</DeleteMarker>
+ <DeleteMarkerVersionId>Version</DeleteMarkerVersionId>
+ </Deleted>
+ </DeleteResult>
+ */
+ public static class DeleteObjectsHandler extends AbstractHandler {
+
+ private final DeleteObjectsResponse response =
+ new DeleteObjectsResponse();
+
+ private DeletedObject currentDeletedObject = null;
+ private DeleteError currentError = null;
+
+ public DeleteObjectsResponse getDeleteObjectResult() {
+ return response;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("DeleteResult")) {
+ if (name.equals("Deleted")) {
+ currentDeletedObject = new DeletedObject();
+ } else if (name.equals("Error")) {
+ currentError = new DeleteError();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("DeleteResult")) {
+ if (name.equals("Deleted")) {
+ response.getDeletedObjects().add(currentDeletedObject);
+ currentDeletedObject = null;
+ } else if (name.equals("Error")) {
+ response.getErrors().add(currentError);
+ currentError = null;
+ }
+ }
+
+ else if (in("DeleteResult", "Deleted")) {
+ if (name.equals("Key")) {
+ currentDeletedObject.setKey(getText());
+
+ } else if (name.equals("VersionId")) {
+ currentDeletedObject.setVersionId(getText());
+
+ } else if (name.equals("DeleteMarker")) {
+ currentDeletedObject.setDeleteMarker(
+ getText().equals("true"));
+
+ } else if (name.equals("DeleteMarkerVersionId")) {
+ currentDeletedObject.setDeleteMarkerVersionId(getText());
+ }
+ }
+
+ else if (in("DeleteResult", "Error")) {
+ if (name.equals("Key")) {
+ currentError.setKey(getText());
+
+ } else if (name.equals("VersionId")) {
+ currentError.setVersionId(getText());
+
+ } else if (name.equals("Code")) {
+ currentError.setCode(getText());
+
+ } else if (name.equals("Message")) {
+ currentError.setMessage(getText());
+ }
+ }
+ }
+ }
+
+ /**
+ * HTTP/1.1 200 OK
+ x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ x-amz-request-id: 656c76696e6727732072657175657374
+ Date: Tue, 20 Sep 2012 20:34:56 GMT
+ Content-Length: xxx
+ Connection: keep-alive
+ Server: AmazonS3
+
+ <LifecycleConfiguration>
+ <Rule>
+ <ID>logs-rule</ID>
+ <Prefix>logs/</Prefix>
+ <Status>Enabled</Status>
+ <Filter>
+ <Prefix>logs/</Prefix>
+ <Tag>
+ <Key>key1</Key>
+ <Value>value1</Value>
+ </Tag>
+ <And>
+ <Prefix>logs/</Prefix>
+ <Tag>
+ <Key>key1</Key>
+ <Value>value1</Value>
+ </Tag>
+ <Tag>
+ <Key>key1</Key>
+ <Value>value1</Value>
+ </Tag>
+ </And>
+ </Filter>
+ <Transition>
+ <Days>30</Days>
+ <StorageClass>STANDARD_IA</StorageClass>
+ </Transition>
+ <Transition>
+ <Days>90</Days>
+ <StorageClass>GLACIER</StorageClass>
+ </Transition>
+ <Expiration>
+ <Days>365</Days>
+ </Expiration>
+ <NoncurrentVersionTransition>
+ <NoncurrentDays>7</NoncurrentDays>
+ <StorageClass>STANDARD_IA</StorageClass>
+ </NoncurrentVersionTransition>
+ <NoncurrentVersionTransition>
+ <NoncurrentDays>14</NoncurrentDays>
+ <StorageClass>GLACIER</StorageClass>
+ </NoncurrentVersionTransition>
+ <NoncurrentVersionExpiration>
+ <NoncurrentDays>365</NoncurrentDays>
+ </NoncurrentVersionExpiration>
+ </Rule>
+ <Rule>
+ <ID>image-rule</ID>
+ <Prefix>image/</Prefix>
+ <Status>Enabled</Status>
+ <Transition>
+ <Date>2012-12-31T00:00:00.000Z</Date>
+ <StorageClass>GLACIER</StorageClass>
+ </Transition>
+ <Expiration>
+ <Date>2020-12-31T00:00:00.000Z</Date>
+ </Expiration>
+ <AbortIncompleteMultipartUpload>
+ <DaysAfterInitiation>10</DaysAfterInitiation>
+ </AbortIncompleteMultipartUpload>
+ </Rule>
+ </LifecycleConfiguration>
+ */
+ public static class BucketLifecycleConfigurationHandler extends AbstractHandler {
+
+ private final BucketLifecycleConfiguration configuration =
+ new BucketLifecycleConfiguration(new ArrayList<Rule>());
+
+ private Rule currentRule;
+ private Transition currentTransition;
+ private NoncurrentVersionTransition currentNcvTransition;
+ private AbortIncompleteMultipartUpload abortIncompleteMultipartUpload;
+ private LifecycleFilter currentFilter;
+ private List<LifecycleFilterPredicate> andOperandsList;
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public BucketLifecycleConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("LifecycleConfiguration")) {
+ if (name.equals("Rule")) {
+ currentRule = new Rule();
+ }
+ } else if (in("LifecycleConfiguration", "Rule")) {
+ if (name.equals("Transition")) {
+ currentTransition = new Transition();
+ } else if (name.equals("NoncurrentVersionTransition")) {
+ currentNcvTransition = new NoncurrentVersionTransition();
+ } else if (name.equals("AbortIncompleteMultipartUpload")) {
+ abortIncompleteMultipartUpload = new
+ AbortIncompleteMultipartUpload();
+ } else if (name.equals("Filter")) {
+ currentFilter = new LifecycleFilter();
+ }
+ } else if (in("LifecycleConfiguration", "Rule", "Filter")) {
+ if (name.equals("And")) {
+ andOperandsList = new ArrayList<LifecycleFilterPredicate>();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("LifecycleConfiguration")) {
+ if (name.equals("Rule")) {
+ configuration.getRules().add(currentRule);
+ currentRule = null;
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule")) {
+ if ( name.equals("ID") ) {
+ currentRule.setId(getText());
+
+ } else if ( name.equals("Prefix") ) {
+ currentRule.setPrefix(getText());
+
+ } else if ( name.equals("Status") ) {
+ currentRule.setStatus(getText());
+
+ } else if (name.equals("Transition")) {
+ currentRule.addTransition(currentTransition);
+ currentTransition = null;
+
+ } else if (name.equals("NoncurrentVersionTransition")) {
+ currentRule.addNoncurrentVersionTransition(
+ currentNcvTransition);
+ currentNcvTransition = null;
+ } else if (name.equals("AbortIncompleteMultipartUpload")) {
+ currentRule.setAbortIncompleteMultipartUpload(abortIncompleteMultipartUpload);
+ abortIncompleteMultipartUpload = null;
+ } else if (name.equals("Filter")) {
+ currentRule.setFilter(currentFilter);
+ currentFilter = null;
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Expiration")) {
+ if (name.equals("Date")) {
+ currentRule.setExpirationDate(ServiceUtils.parseIso8601Date(getText()));
+ } else if (name.equals("Days")) {
+ currentRule.setExpirationInDays(Integer.parseInt(getText()));
+ } else if (name.equals("ExpiredObjectDeleteMarker")) {
+ if ("true".equals(getText())) {
+ currentRule.setExpiredObjectDeleteMarker(true);
+ }
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Transition")) {
+ if (name.equals("StorageClass")) {
+ currentTransition.setStorageClass(getText());
+ } else if (name.equals("Date")) {
+ currentTransition.setDate(
+ ServiceUtils.parseIso8601Date(getText()));
+
+ } else if (name.equals("Days")) {
+ currentTransition.setDays(Integer.parseInt(getText()));
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "NoncurrentVersionExpiration")) {
+ if (name.equals("NoncurrentDays")) {
+ currentRule.setNoncurrentVersionExpirationInDays(
+ Integer.parseInt(getText()));
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "NoncurrentVersionTransition")) {
+ if (name.equals("StorageClass")) {
+ currentNcvTransition.setStorageClass(getText());
+ } else if (name.equals("NoncurrentDays")) {
+ currentNcvTransition.setDays(Integer.parseInt(getText()));
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "AbortIncompleteMultipartUpload")) {
+ if (name.equals("DaysAfterInitiation")) {
+ abortIncompleteMultipartUpload.setDaysAfterInitiation
+ (Integer.parseInt(getText()));
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Filter")) {
+ if (name.equals("Prefix")) {
+ currentFilter.setPredicate(new LifecyclePrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ currentFilter.setPredicate(new LifecycleTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ } else if (name.equals("And")) {
+ currentFilter.setPredicate(new LifecycleAndOperator(andOperandsList));
+ andOperandsList = null;
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Filter", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Filter", "And")) {
+ if (name.equals("Prefix")) {
+ andOperandsList.add(new LifecyclePrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ andOperandsList.add(new LifecycleTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("LifecycleConfiguration", "Rule", "Filter", "And", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ }
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ x-amz-request-id: 656c76696e6727732072657175657374
+ Date: Tue, 20 Sep 2011 20:34:56 GMT
+ Content-Length: Some Length
+ Connection: keep-alive
+ Server: AmazonS3
+ <CORSConfiguration>
+ <CORSRule>
+ <AllowedOrigin>http://www.foobar.com</AllowedOrigin>
+ <AllowedMethod>GET</AllowedMethod>
+ <MaxAgeSeconds>3000</MaxAgeSec>
+ <ExposeHeader>x-amz-server-side-encryption</ExposeHeader>
+ </CORSRule>
+ </CORSConfiguration>
+ */
+ public static class BucketCrossOriginConfigurationHandler extends AbstractHandler {
+
+ private final BucketCrossOriginConfiguration configuration =
+ new BucketCrossOriginConfiguration(new ArrayList<CORSRule>());
+
+ private CORSRule currentRule;
+ private List<AllowedMethods> allowedMethods = null;
+ private List<String> allowedOrigins = null;
+ private List<String> exposedHeaders = null;
+ private List<String> allowedHeaders = null;
+
+ public BucketCrossOriginConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("CORSConfiguration")) {
+ if (name.equals("CORSRule")) {
+ currentRule = new CORSRule();
+ }
+ } else if (in("CORSConfiguration", "CORSRule")) {
+ if (name.equals("AllowedOrigin")) {
+ if (allowedOrigins == null) {
+ allowedOrigins = new ArrayList<String>();
+ }
+ } else if (name.equals("AllowedMethod")) {
+ if (allowedMethods == null) {
+ allowedMethods = new ArrayList<AllowedMethods>();
+ }
+ } else if (name.equals("ExposeHeader")) {
+ if (exposedHeaders == null) {
+ exposedHeaders = new ArrayList<String>();
+ }
+ } else if (name.equals("AllowedHeader")) {
+ if (allowedHeaders == null) {
+ allowedHeaders = new LinkedList<String>();
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("CORSConfiguration")) {
+ if (name.equals("CORSRule")) {
+ currentRule.setAllowedHeaders(allowedHeaders);
+ currentRule.setAllowedMethods(allowedMethods);
+ currentRule.setAllowedOrigins(allowedOrigins);
+ currentRule.setExposedHeaders(exposedHeaders);
+ allowedHeaders = null;
+ allowedMethods = null;
+ allowedOrigins = null;
+ exposedHeaders = null;
+
+ configuration.getRules().add(currentRule);
+ currentRule = null;
+ }
+ } else if (in("CORSConfiguration", "CORSRule")) {
+ if (name.equals("ID")) {
+ currentRule.setId(getText());
+
+ } else if (name.equals("AllowedOrigin")) {
+ allowedOrigins.add(getText());
+
+ } else if (name.equals("AllowedMethod")) {
+ allowedMethods.add(AllowedMethods.fromValue(getText()));
+
+ } else if (name.equals("MaxAgeSeconds")) {
+ currentRule.setMaxAgeSeconds(Integer.parseInt(getText()));
+
+ } else if (name.equals("ExposeHeader")) {
+ exposedHeaders.add(getText());
+
+ } else if (name.equals("AllowedHeader")) {
+ allowedHeaders.add(getText());
+ }
+ }
+ }
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: ITnGT1y4RyTmXa3rPi4hklTXouTf0hccUjo0iCPjz6FnfIutBj3M7fPGlWO2SEWp
+ x-amz-request-id: 51991C342C575321
+ Date: Wed, 14 May 2014 02:11:22 GMT
+ Server: AmazonS3
+ Content-Length: ...
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <MetricsConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <Id>metrics-id</Id>
+ <Filter>
+ <!-- A filter should have only one of Prefix, Tag or And predicate. ->
+ <Prefix>prefix</Prefix>
+ <Tag>
+ <Key>Project</Key>
+ <Value>Foo</Value>
+ </Tag>
+ <And>
+ <Prefix>documents/</Prefix>
+ <Tag>
+ <Key>foo</Key>
+ <Value>bar</Value>
+ </Tag>
+ </And>
+ </Filter>
+ </MetricsConfiguration>
+ */
+ public static class GetBucketMetricsConfigurationHandler extends AbstractHandler {
+
+ private final MetricsConfiguration configuration = new MetricsConfiguration();
+
+ private MetricsFilter filter;
+ private List<MetricsFilterPredicate> andOperandsList;
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public GetBucketMetricsConfigurationResult getResult() {
+ return new GetBucketMetricsConfigurationResult().withMetricsConfiguration(configuration);
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("MetricsConfiguration")) {
+ if (name.equals("Filter")) {
+ filter = new MetricsFilter();
+ }
+
+ } else if (in("MetricsConfiguration", "Filter")) {
+ if (name.equals("And")) {
+ andOperandsList = new ArrayList<MetricsFilterPredicate>();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("MetricsConfiguration")) {
+ if (name.equals("Id")) {
+ configuration.setId(getText());
+ } else if (name.equals("Filter")) {
+ configuration.setFilter(filter);
+ filter = null;
+ }
+ }
+
+ else if (in("MetricsConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ filter.setPredicate(new MetricsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ filter.setPredicate(new MetricsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ } else if (name.equals("And")) {
+ filter.setPredicate(new MetricsAndOperator(andOperandsList));
+ andOperandsList = null;
+ }
+ }
+
+ else if (in("MetricsConfiguration", "Filter", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("MetricsConfiguration", "Filter", "And")) {
+ if (name.equals("Prefix")) {
+ andOperandsList.add(new MetricsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ andOperandsList.add(new MetricsTagPredicate(
+ new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("MetricsConfiguration", "Filter", "And", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+ }
+
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: ITnGT1y4RyTmXa3rPi4hklTXouTf0hccUjo0iCPjz6FnfIutBj3M7fPGlWO2SEWp
+ x-amz-request-id: 51991C342C575321
+ Date: Wed, 14 May 2014 02:11:22 GMT
+ Server: AmazonS3
+ Content-Length: ...
+
+ <ListMetricsConfigurationsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <MetricsConfiguration>
+ ...
+ </MetricsConfiguration>
+ <IsTruncated>true</IsTruncated>
+ <ContinuationToken>token1</ContinuationToken>
+ <NextContinuationToken>token2</NextContinuationToken>
+ </ListMetricsConfigurationsResult>
+ */
+ public static class ListBucketMetricsConfigurationsHandler extends AbstractHandler {
+
+ private final ListBucketMetricsConfigurationsResult result =
+ new ListBucketMetricsConfigurationsResult();
+
+ private MetricsConfiguration currentConfiguration;
+ private MetricsFilter currentFilter;
+ private List<MetricsFilterPredicate> andOperandsList;
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public ListBucketMetricsConfigurationsResult getResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListMetricsConfigurationsResult")) {
+ if (name.equals("MetricsConfiguration")) {
+ currentConfiguration = new MetricsConfiguration();
+ }
+
+ } else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration")) {
+ if (name.equals("Filter")) {
+ currentFilter = new MetricsFilter();
+ }
+
+ } else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration", "Filter")) {
+ if (name.equals("And")) {
+ andOperandsList = new ArrayList<MetricsFilterPredicate>();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+
+ if (in("ListMetricsConfigurationsResult")) {
+ if (name.equals("MetricsConfiguration")) {
+ if (result.getMetricsConfigurationList() == null) {
+ result.setMetricsConfigurationList(new ArrayList<MetricsConfiguration>());
+ }
+ result.getMetricsConfigurationList().add(currentConfiguration);
+ currentConfiguration = null;
+ } else if (name.equals("IsTruncated")) {
+ result.setTruncated("true".equals(getText()));
+ } else if (name.equals("ContinuationToken")) {
+ result.setContinuationToken(getText());
+ } else if (name.equals("NextContinuationToken")) {
+ result.setNextContinuationToken(getText());
+ }
+ }
+
+ else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration")) {
+ if (name.equals("Id")) {
+ currentConfiguration.setId(getText());
+ } else if (name.equals("Filter")) {
+ currentConfiguration.setFilter(currentFilter);
+ currentFilter = null;
+ }
+ }
+
+ else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ currentFilter.setPredicate(new MetricsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ currentFilter.setPredicate(new MetricsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ } else if (name.equals("And")) {
+ currentFilter.setPredicate(new MetricsAndOperator(andOperandsList));
+ andOperandsList = null;
+ }
+ }
+
+ else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration", "Filter", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration", "Filter", "And")) {
+ if (name.equals("Prefix")) {
+ andOperandsList.add(new MetricsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ andOperandsList.add(new MetricsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("ListMetricsConfigurationsResult", "MetricsConfiguration", "Filter", "And", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+ }
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: ITnGT1y4RyTmXa3rPi4hklTXouTf0hccUjo0iCPjz6FnfIutBj3M7fPGlWO2SEWp
+ x-amz-request-id: 51991C342C575321
+ Date: Wed, 14 May 2014 02:11:22 GMT
+ Server: AmazonS3
+ Content-Length: ...
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <AnalyticsConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <Id>XXX</Id>
+ <Filter>
+ <And>
+ <Prefix>documents/</Prefix>
+ <Tag>
+ <Key>foo</Key>
+ <Value>bar</Value>
+ </Tag>
+ </And>
+ </Filter>
+ <StorageClassAnalysis>
+ <DataExport>
+ <OutputSchemaVersion>1</OutputSchemaVersion>
+ <Destination>
+ <S3BucketDestination>
+ <Format>CSV</Format>
+ <BucketAccountId>123456789</BucketAccountId>
+ <Bucket>destination-bucket</Bucket>
+ <Prefix>destination-prefix</Prefix>
+ </S3BucketDestination>
+ </Destination>
+ </DataExport>
+ </StorageClassAnalysis>
+ </AnalyticsConfiguration>
+ */
+ public static class GetBucketAnalyticsConfigurationHandler extends AbstractHandler {
+
+ private final AnalyticsConfiguration configuration = new AnalyticsConfiguration();
+
+ private AnalyticsFilter filter;
+ private List<AnalyticsFilterPredicate> andOperandsList;
+ private StorageClassAnalysis storageClassAnalysis;
+ private StorageClassAnalysisDataExport dataExport;
+ private AnalyticsExportDestination destination;
+ private AnalyticsS3BucketDestination s3BucketDestination;
+
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public GetBucketAnalyticsConfigurationResult getResult() {
+ return new GetBucketAnalyticsConfigurationResult().withAnalyticsConfiguration(configuration);
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("AnalyticsConfiguration")) {
+ if (name.equals("Filter")) {
+ filter = new AnalyticsFilter();
+ } else if (name.equals("StorageClassAnalysis")) {
+ storageClassAnalysis = new StorageClassAnalysis();
+ }
+
+ } else if (in("AnalyticsConfiguration", "Filter")) {
+ if (name.equals("And")) {
+ andOperandsList = new ArrayList<AnalyticsFilterPredicate>();
+ }
+
+ } else if (in("AnalyticsConfiguration", "StorageClassAnalysis")) {
+ if (name.equals("DataExport")) {
+ dataExport = new StorageClassAnalysisDataExport();
+ }
+
+ } else if (in("AnalyticsConfiguration", "StorageClassAnalysis", "DataExport")) {
+ if (name.equals("Destination")) {
+ destination = new AnalyticsExportDestination();
+ }
+
+ } else if (in("AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ s3BucketDestination = new AnalyticsS3BucketDestination();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+ if (in("AnalyticsConfiguration")) {
+ if (name.equals("Id")) {
+ configuration.setId(getText());
+ } else if (name.equals("Filter")) {
+ configuration.setFilter(filter);
+ } else if (name.equals("StorageClassAnalysis")) {
+ configuration.setStorageClassAnalysis(storageClassAnalysis);
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ filter.setPredicate(new AnalyticsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ filter.setPredicate(new AnalyticsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ } else if (name.equals("And")) {
+ filter.setPredicate(new AnalyticsAndOperator(andOperandsList));
+ andOperandsList = null;
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "Filter", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "Filter", "And")) {
+ if (name.equals("Prefix")) {
+ andOperandsList.add(new AnalyticsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ andOperandsList.add(new AnalyticsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "Filter", "And", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "StorageClassAnalysis")) {
+ if (name.equals("DataExport")) {
+ storageClassAnalysis.setDataExport(dataExport);
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "StorageClassAnalysis", "DataExport")) {
+ if (name.equals("OutputSchemaVersion")) {
+ dataExport.setOutputSchemaVersion(getText());
+ } else if (name.equals("Destination")) {
+ dataExport.setDestination(destination);
+
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ destination.setS3BucketDestination(s3BucketDestination);
+ }
+ }
+
+ else if (in("AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination", "S3BucketDestination")) {
+ if (name.equals("Format")) {
+ s3BucketDestination.setFormat(getText());
+ } else if (name.equals("BucketAccountId")) {
+ s3BucketDestination.setBucketAccountId(getText());
+ } else if (name.equals("Bucket")) {
+ s3BucketDestination.setBucketArn(getText());
+ } else if (name.equals("Prefix")) {
+ s3BucketDestination.setPrefix(getText());
+ }
+ }
+ }
+
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: ITnGT1y4RyTmXa3rPi4hklTXouTf0hccUjo0iCPjz6FnfIutBj3M7fPGlWO2SEWp
+ x-amz-request-id: 51991C342C575321
+ Date: Wed, 14 May 2014 02:11:22 GMT
+ Server: AmazonS3
+ Content-Length: ...
+
+ <ListBucketAnalyticsConfigurationsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <AnalyticsConfiguration>
+ ...
+ </AnalyticsConfiguration>
+ <IsTruncated>true</IsTruncated>
+ <ContinuationToken>token1</ContinuationToken>
+ <NextContinuationToken>token2</NextContinuationToken>
+ </ListBucketAnalyticsConfigurationsResult>
+ */
+ public static class ListBucketAnalyticsConfigurationHandler extends AbstractHandler {
+
+ private final ListBucketAnalyticsConfigurationsResult result =
+ new ListBucketAnalyticsConfigurationsResult();
+
+ private AnalyticsConfiguration currentConfiguration;
+ private AnalyticsFilter currentFilter;
+ private List<AnalyticsFilterPredicate> andOperandsList;
+ private StorageClassAnalysis storageClassAnalysis;
+ private StorageClassAnalysisDataExport dataExport;
+ private AnalyticsExportDestination destination;
+ private AnalyticsS3BucketDestination s3BucketDestination;
+ private String currentTagKey;
+ private String currentTagValue;
+
+ public ListBucketAnalyticsConfigurationsResult getResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListBucketAnalyticsConfigurationsResult")) {
+ if (name.equals("AnalyticsConfiguration")) {
+ currentConfiguration = new AnalyticsConfiguration();
+ }
+
+ } else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration")) {
+ if (name.equals("Filter")) {
+ currentFilter = new AnalyticsFilter();
+ } else if (name.equals("StorageClassAnalysis")) {
+ storageClassAnalysis = new StorageClassAnalysis();
+ }
+
+ } else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "Filter")) {
+ if (name.equals("And")) {
+ andOperandsList = new ArrayList<AnalyticsFilterPredicate>();
+ }
+
+ } else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis")) {
+ if (name.equals("DataExport")) {
+ dataExport = new StorageClassAnalysisDataExport();
+ }
+
+ } else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis", "DataExport")) {
+ if (name.equals("Destination")) {
+ destination = new AnalyticsExportDestination();
+ }
+
+ } else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ s3BucketDestination = new AnalyticsS3BucketDestination();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+
+ if (in("ListBucketAnalyticsConfigurationsResult")) {
+ if (name.equals("AnalyticsConfiguration")) {
+ if (result.getAnalyticsConfigurationList() == null) {
+ result.setAnalyticsConfigurationList(new ArrayList<AnalyticsConfiguration>());
+ }
+ result.getAnalyticsConfigurationList().add(currentConfiguration);
+ currentConfiguration = null;
+ } else if (name.equals("IsTruncated")) {
+ result.setTruncated("true".equals(getText()));
+ } else if (name.equals("ContinuationToken")) {
+ result.setContinuationToken(getText());
+ } else if (name.equals("NextContinuationToken")) {
+ result.setNextContinuationToken(getText());
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration")) {
+ if (name.equals("Id")) {
+ currentConfiguration.setId(getText());
+ } else if (name.equals("Filter")) {
+ currentConfiguration.setFilter(currentFilter);
+ } else if (name.equals("StorageClassAnalysis")) {
+ currentConfiguration.setStorageClassAnalysis(storageClassAnalysis);
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ currentFilter.setPredicate(new AnalyticsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ currentFilter.setPredicate(new AnalyticsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ } else if (name.equals("And")) {
+ currentFilter.setPredicate(new AnalyticsAndOperator(andOperandsList));
+ andOperandsList = null;
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "Filter", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "Filter", "And")) {
+ if (name.equals("Prefix")) {
+ andOperandsList.add(new AnalyticsPrefixPredicate(getText()));
+ } else if (name.equals("Tag")) {
+ andOperandsList.add(new AnalyticsTagPredicate(new Tag(currentTagKey, currentTagValue)));
+ currentTagKey = null;
+ currentTagValue = null;
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "Filter", "And", "Tag")) {
+ if (name.equals("Key")) {
+ currentTagKey = getText();
+ } else if (name.equals("Value")) {
+ currentTagValue = getText();
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis")) {
+ if (name.equals("DataExport")) {
+ storageClassAnalysis.setDataExport(dataExport);
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis", "DataExport")) {
+ if (name.equals("OutputSchemaVersion")) {
+ dataExport.setOutputSchemaVersion(getText());
+ } else if (name.equals("Destination")) {
+ dataExport.setDestination(destination);
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ destination.setS3BucketDestination(s3BucketDestination);
+ }
+ }
+
+ else if (in("ListBucketAnalyticsConfigurationsResult", "AnalyticsConfiguration", "StorageClassAnalysis", "DataExport", "Destination", "S3BucketDestination")) {
+ if (name.equals("Format")) {
+ s3BucketDestination.setFormat(getText());
+ } else if (name.equals("BucketAccountId")) {
+ s3BucketDestination.setBucketAccountId(getText());
+ } else if (name.equals("Bucket")) {
+ s3BucketDestination.setBucketArn(getText());
+ } else if (name.equals("Prefix")) {
+ s3BucketDestination.setPrefix(getText());
+ }
+ }
+ }
+
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: Uuag1LuByRx9e6j5Onimru9pO4ZVKnJ2Qz7/C1NPcfTWAtRPfTaOFg==
+ x-amz-request-id: 656c76696e6727732072657175657374
+ Date: Tue, 20 Sep 2012 20:34:56 GMT
+ Content-Length: xxx
+ Connection: keep-alive
+ Server: AmazonS3
+
+ <InventoryConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <Destination>
+ <S3BucketDestination>
+ <AccountId>A2OCNCIEQW9MSG</AccountId>
+ <Bucket>s3-object-inventory-list-gamma-us-east-1</Bucket>
+ <Format>CSV</Format>
+ <Prefix>string</Prefix>
+ </S3BucketDestination>
+ </Destination>
+ <IsEnabled>true</IsEnabled>
+ <Filter>
+ <Prefix>string</Prefix>
+ </Filter>
+ <Id>configId</Id>
+ <IncludedObjectVersions>All</IncludedObjectVersions>
+ <OptionalFields>
+ <Field>Size</Field>
+ <Field>LastModifiedDate</Field>
+ <Field>StorageClass</Field>
+ <Field>ETag</Field>
+ <Field>IsMultipartUploaded</Field>
+ <Field>ReplicationStatus</Field>
+ </OptionalFields>
+ <Schedule>
+ <Frequency>Daily</Frequency>
+ </Schedule>
+ </InventoryConfiguration>
+ */
+ public static class GetBucketInventoryConfigurationHandler extends AbstractHandler {
+
+ public static final String SSE_S3 = "SSE-S3";
+ public static final String SSE_KMS = "SSE-KMS";
+ private final GetBucketInventoryConfigurationResult result = new GetBucketInventoryConfigurationResult();
+ private final InventoryConfiguration configuration = new InventoryConfiguration();
+
+ private List<String> optionalFields;
+ private InventoryDestination inventoryDestination;
+ private InventoryFilter filter;
+ private InventoryS3BucketDestination s3BucketDestination;
+ private InventorySchedule inventorySchedule;
+
+ public GetBucketInventoryConfigurationResult getResult() {
+ return result.withInventoryConfiguration(configuration);
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("InventoryConfiguration")) {
+ if (name.equals("Destination")) {
+ inventoryDestination = new InventoryDestination();
+ } else if(name.equals("Filter")) {
+ filter = new InventoryFilter();
+ } else if(name.equals("Schedule")) {
+ inventorySchedule = new InventorySchedule();
+ } else if(name.equals("OptionalFields")) {
+ optionalFields = new ArrayList<String>();
+ }
+
+ } else if (in("InventoryConfiguration", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ s3BucketDestination = new InventoryS3BucketDestination();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+
+ if (in("InventoryConfiguration")) {
+ if (name.equals("Id")) {
+ configuration.setId(getText());
+
+ } else if (name.equals("Destination")) {
+ configuration.setDestination(inventoryDestination);
+ inventoryDestination = null;
+
+ } else if (name.equals("IsEnabled")) {
+ configuration.setEnabled("true".equals(getText()));
+
+ } else if (name.equals("Filter")) {
+ configuration.setInventoryFilter(filter);
+ filter = null;
+
+ } else if (name.equals("IncludedObjectVersions")) {
+ configuration.setIncludedObjectVersions(getText());
+
+ } else if (name.equals("Schedule")) {
+ configuration.setSchedule(inventorySchedule);
+ inventorySchedule = null;
+
+ } else if (name.equals("OptionalFields")) {
+ configuration.setOptionalFields(optionalFields);
+ optionalFields = null;
+ }
+
+ } else if (in("InventoryConfiguration", "Destination")) {
+ if ( name.equals("S3BucketDestination") ) {
+ inventoryDestination.setS3BucketDestination(s3BucketDestination);
+ s3BucketDestination = null;
+ }
+
+ } else if (in("InventoryConfiguration", "Destination", "S3BucketDestination")) {
+ if (name.equals("AccountId")) {
+ s3BucketDestination.setAccountId(getText());
+ } else if (name.equals("Bucket")) {
+ s3BucketDestination.setBucketArn(getText());
+ } else if (name.equals("Format")) {
+ s3BucketDestination.setFormat(getText());
+ } else if (name.equals("Prefix")) {
+ s3BucketDestination.setPrefix(getText());
+ }
+ } else if (in("InventoryConfiguration", "Destination", "S3BucketDestination", "Encryption")) {
+ if (name.equals(SSE_S3)) {
+ s3BucketDestination.setEncryption(new ServerSideEncryptionS3());
+ } else if (name.equals(SSE_KMS)) {
+ ServerSideEncryptionKMS kmsEncryption = new ServerSideEncryptionKMS().withKeyId(getText());
+ s3BucketDestination.setEncryption(kmsEncryption);
+ }
+ } else if (in("InventoryConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ filter.setPredicate(new InventoryPrefixPredicate(getText()));
+ }
+
+ } else if (in("InventoryConfiguration", "Schedule")) {
+ if (name.equals("Frequency")) {
+ inventorySchedule.setFrequency(getText());
+ }
+
+ } else if (in("InventoryConfiguration", "OptionalFields")) {
+ if (name.equals("Field")) {
+ optionalFields.add(getText());
+ }
+ }
+ }
+
+ }
+
+ /*
+ HTTP/1.1 200 OK
+ x-amz-id-2: ITnGT1y4RyTmXa3rPi4hklTXouTf0hccUjo0iCPjz6FnfIutBj3M7fPGlWO2SEWp
+ x-amz-request-id: 51991C342C575321
+ Date: Wed, 14 May 2014 02:11:22 GMT
+ Server: AmazonS3
+ Content-Length: ...
+
+ <ListInventoryConfigurationsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+ <InventoryConfiguration>
+ ...
+ </InventoryConfiguration>
+ <InventoryConfiguration>
+ ...
+ </InventoryConfiguration>
+ <IsTruncated>true</IsTruncated>
+ <ContinuationToken>token1</ContinuationToken>
+ <NextContinuationToken>token2</NextContinuationToken>
+ </ListInventoryConfigurationsResult>
+ */
+ public static class ListBucketInventoryConfigurationsHandler extends AbstractHandler {
+
+ private final ListBucketInventoryConfigurationsResult result = new ListBucketInventoryConfigurationsResult();
+
+ private InventoryConfiguration currentConfiguration;
+ private List<String> currentOptionalFieldsList;
+ private InventoryDestination currentDestination;
+ private InventoryFilter currentFilter;
+ private InventoryS3BucketDestination currentS3BucketDestination;
+ private InventorySchedule currentSchedule;
+
+ public ListBucketInventoryConfigurationsResult getResult() {
+ return result;
+ }
+
+ @Override
+ protected void doStartElement(
+ String uri,
+ String name,
+ String qName,
+ Attributes attrs) {
+
+ if (in("ListInventoryConfigurationsResult")) {
+ if (name.equals("InventoryConfiguration")) {
+ currentConfiguration = new InventoryConfiguration();
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration")) {
+ if (name.equals("Destination")) {
+ currentDestination = new InventoryDestination();
+ } else if(name.equals("Filter")) {
+ currentFilter = new InventoryFilter();
+ } else if(name.equals("Schedule")) {
+ currentSchedule = new InventorySchedule();
+ } else if(name.equals("OptionalFields")) {
+ currentOptionalFieldsList = new ArrayList<String>();
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "Destination")) {
+ if (name.equals("S3BucketDestination")) {
+ currentS3BucketDestination = new InventoryS3BucketDestination();
+ }
+ }
+ }
+
+ @Override
+ protected void doEndElement(String uri, String name, String qName) {
+
+ if (in("ListInventoryConfigurationsResult")) {
+ if (name.equals("InventoryConfiguration")) {
+ if (result.getInventoryConfigurationList() == null) {
+ result.setInventoryConfigurationList(new ArrayList<InventoryConfiguration>());
+ }
+ result.getInventoryConfigurationList().add(currentConfiguration);
+ currentConfiguration = null;
+ } else if (name.equals("IsTruncated")) {
+ result.setTruncated("true".equals(getText()));
+ } else if (name.equals("ContinuationToken")) {
+ result.setContinuationToken(getText());
+ } else if (name.equals("NextContinuationToken")) {
+ result.setNextContinuationToken(getText());
+ }
+ }
+
+ else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration")) {
+ if (name.equals("Id")) {
+ currentConfiguration.setId(getText());
+
+ } else if (name.equals("Destination")) {
+ currentConfiguration.setDestination(currentDestination);
+ currentDestination = null;
+
+ } else if (name.equals("IsEnabled")) {
+ currentConfiguration.setEnabled("true".equals(getText()));
+
+ } else if (name.equals("Filter")) {
+ currentConfiguration.setInventoryFilter(currentFilter);
+ currentFilter = null;
+
+ } else if (name.equals("IncludedObjectVersions")) {
+ currentConfiguration.setIncludedObjectVersions(getText());
+
+ } else if (name.equals("Schedule")) {
+ currentConfiguration.setSchedule(currentSchedule);
+ currentSchedule = null;
+
+ } else if (name.equals("OptionalFields")) {
+ currentConfiguration.setOptionalFields(currentOptionalFieldsList);
+ currentOptionalFieldsList = null;
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "Destination")) {
+ if ( name.equals("S3BucketDestination") ) {
+ currentDestination.setS3BucketDestination(currentS3BucketDestination);
+ currentS3BucketDestination = null;
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "Destination", "S3BucketDestination")) {
+ if (name.equals("AccountId")) {
+ currentS3BucketDestination.setAccountId(getText());
+ } else if (name.equals("Bucket")) {
+ currentS3BucketDestination.setBucketArn(getText());
+ } else if (name.equals("Format")) {
+ currentS3BucketDestination.setFormat(getText());
+ } else if (name.equals("Prefix")) {
+ currentS3BucketDestination.setPrefix(getText());
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "Filter")) {
+ if (name.equals("Prefix")) {
+ currentFilter.setPredicate(new InventoryPrefixPredicate(getText()));
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "Schedule")) {
+ if (name.equals("Frequency")) {
+ currentSchedule.setFrequency(getText());
+ }
+
+ } else if (in("ListInventoryConfigurationsResult", "InventoryConfiguration", "OptionalFields")) {
+ if (name.equals("Field")) {
+ currentOptionalFieldsList.add(getText());
+ }
+ }
+ }
+
+ }
+
+ private static String findAttributeValue(
+ String qnameToFind,
+ Attributes attrs) {
+
+ for (int i = 0; i < attrs.getLength(); i++) {
+ String qname = attrs.getQName(i);
+ if (qname.trim().equalsIgnoreCase(qnameToFind.trim())) {
+ return attrs.getValue(i);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/flink-filesystems/flink-s3-fs-hadoop/pom.xml b/flink-filesystems/flink-s3-fs-hadoop/pom.xml
index cded6b5..cf8efa4 100644
--- a/flink-filesystems/flink-s3-fs-hadoop/pom.xml
+++ b/flink-filesystems/flink-s3-fs-hadoop/pom.xml
@@ -204,6 +204,15 @@ under the License.
<exclude>META-INF/LICENSE.txt</exclude>
</excludes>
</filter>
+ <filter>
+ <artifact>com.amazonaws:aws-java-sdk-s3</artifact>
+ <!-- Make sure we are using the overridden XmlResponsesSaxParser of flink-s3-fs-base.
+ Filter must be removed as soon as XmlResponsesSaxParser of this module is
+ dropped, for example when discontinuing support for Java 8. -->
+ <excludes>
+ <exclude>com/amazonaws/services/s3/model/transform/XmlResponsesSaxParser**</exclude>
+ </excludes>
+ </filter>
</filters>
</configuration>
</execution>
diff --git a/flink-filesystems/flink-s3-fs-presto/pom.xml b/flink-filesystems/flink-s3-fs-presto/pom.xml
index 1365a89..8fbce42 100644
--- a/flink-filesystems/flink-s3-fs-presto/pom.xml
+++ b/flink-filesystems/flink-s3-fs-presto/pom.xml
@@ -376,6 +376,15 @@ under the License.
<include>com/facebook/presto/hadoop/**</include>
</includes>
</filter>
+ <filter>
+ <artifact>com.amazonaws:aws-java-sdk-s3</artifact>
+ <!-- Make sure we are using the overridden XmlResponsesSaxParser of flink-s3-fs-base.
+ Filter must be removed as soon as XmlResponsesSaxParser of this module is
+ dropped, for example when discontinuing support for Java 8. -->
+ <excludes>
+ <exclude>com/amazonaws/services/s3/model/transform/XmlResponsesSaxParser**</exclude>
+ </excludes>
+ </filter>
</filters>
</configuration>
</execution>
diff --git a/tools/maven/suppressions.xml b/tools/maven/suppressions.xml
index 82d7a91..0a18753 100644
--- a/tools/maven/suppressions.xml
+++ b/tools/maven/suppressions.xml
@@ -69,4 +69,8 @@ under the License.
<suppress
files="generated-sources[\\/]org[\\/]apache[\\/]flink[\\/]fnexecution[\\/].*.java"
checks=".*"/>
+ <!-- Classes copied from AWS -->
+ <suppress
+ files="com[\\/]amazonaws[\\/]services[\\/]s3[\\/]model[\\/]transform[\\/]XmlResponsesSaxParser.java"
+ checks=".*"/>
</suppressions>