
com.hubrick.vertx.s3.client.S3Client Maven / Gradle / Ivy
/**
* Copyright (C) 2016 Etaia AS ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hubrick.vertx.s3.client;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.hubrick.vertx.s3.S3Headers;
import com.hubrick.vertx.s3.exception.HttpErrorException;
import com.hubrick.vertx.s3.model.CommonPrefixes;
import com.hubrick.vertx.s3.model.Contents;
import com.hubrick.vertx.s3.model.CopyObjectRequest;
import com.hubrick.vertx.s3.model.DeleteObjectRequest;
import com.hubrick.vertx.s3.model.ErrorResponse;
import com.hubrick.vertx.s3.model.GetBucketRequest;
import com.hubrick.vertx.s3.model.GetBucketRespone;
import com.hubrick.vertx.s3.model.GetObjectRequest;
import com.hubrick.vertx.s3.model.HeadObjectRequest;
import com.hubrick.vertx.s3.model.Owner;
import com.hubrick.vertx.s3.model.PutObjectRequest;
import com.hubrick.vertx.s3.model.filter.NamespaceFilter;
import com.hubrick.vertx.s3.util.UrlEncodingUtils;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.sax.SAXSource;
import java.io.ByteArrayInputStream;
import java.text.MessageFormat;
import java.time.Clock;
import java.util.HashMap;
import java.util.Map;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class S3Client {
private static final Logger log = LoggerFactory.getLogger(S3Client.class);
public static final String DEFAULT_REGION = "us-east-1";
public static final String DEFAULT_ENDPOINT = "s3.amazonaws.com";
private static final String ENDPOINT_PATTERN = "s3-{0}.amazonaws.com";
private final Marshaller jaxbMarshaller;
private final Unmarshaller jaxbUnmarshaller;
private final Long globalTimeout;
private final String awsRegion;
private final String hostname;
private final Clock clock;
private final HttpClient client;
private final String awsAccessKey;
private final String awsSecretKey;
private final String awsServiceName;
private final boolean signPayload;
public S3Client(Vertx vertx, S3ClientOptions s3ClientOptions) {
this(vertx, s3ClientOptions, Clock.systemUTC());
}
public S3Client(Vertx vertx, S3ClientOptions s3ClientOptions, Clock clock) {
checkNotNull(vertx, "vertx must not be null");
checkNotNull(isNotBlank(s3ClientOptions.getAwsRegion()), "AWS region must be set");
checkNotNull(isNotBlank(s3ClientOptions.getAwsServiceName()), "AWS service name must be set");
checkNotNull(clock, "Clock must not be null");
checkNotNull(s3ClientOptions.getGlobalTimeoutMs(), "global timeout must be null");
checkArgument(s3ClientOptions.getGlobalTimeoutMs() > 0, "global timeout must be more than zero ms");
this.jaxbMarshaller = createJaxbMarshaller();
this.jaxbUnmarshaller = createJaxbUnmarshaller();
this.clock = clock;
this.awsServiceName = s3ClientOptions.getAwsServiceName();
this.awsRegion = s3ClientOptions.getAwsRegion();
this.awsAccessKey = s3ClientOptions.getAwsAccessKey();
this.awsSecretKey = s3ClientOptions.getAwsSecretKey();
this.globalTimeout = s3ClientOptions.getGlobalTimeoutMs();
this.signPayload = s3ClientOptions.isSignPayload();
final String hostnameOverride = s3ClientOptions.getHostnameOverride();
if (!Strings.isNullOrEmpty(hostnameOverride)) {
hostname = hostnameOverride;
} else {
if (DEFAULT_REGION.equals(s3ClientOptions.getAwsRegion())) {
hostname = DEFAULT_ENDPOINT;
} else {
hostname = MessageFormat.format(ENDPOINT_PATTERN, awsRegion);
}
}
final S3ClientOptions options = new S3ClientOptions(s3ClientOptions);
options.setDefaultHost(hostname);
this.client = vertx.createHttpClient(options);
}
public String getAwsRegion() {
return awsRegion;
}
public String getAwsServiceName() {
return awsServiceName;
}
public String getHostname() {
return hostname;
}
public void close() {
client.close();
}
public Long getGlobalTimeout() {
return globalTimeout;
}
public void getObject(String bucket,
String key,
GetObjectRequest getObjectRequest,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(bucket), "bucket must not be null");
checkNotNull(StringUtils.trimToNull(key), "bucket must not be null");
checkNotNull(getObjectRequest, "getObjectRequest must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createGetRequest(bucket, key, getObjectRequest, new StreamResponseHandler("getObject", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end();
}
public void headObject(String bucket,
String key,
HeadObjectRequest headObjectRequest,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(bucket), "bucket must not be null");
checkNotNull(StringUtils.trimToNull(key), "bucket must not be null");
checkNotNull(headObjectRequest, "headObjectRequest must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createHeadRequest(bucket, key, headObjectRequest, new HeadersResponseHandler("headObject", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end();
}
public void putObject(String bucket,
String key,
PutObjectRequest putObjectRequest,
Buffer data,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(bucket), "bucket must not be null");
checkNotNull(StringUtils.trimToNull(key), "bucket must not be null");
checkNotNull(putObjectRequest, "putObjectRequest must not be null");
checkNotNull(data, "data must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createPutRequest(bucket, key, putObjectRequest, new StreamResponseHandler("putObject", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end(data);
}
public void copyObject(String sourceBucket,
String sourceKey,
String destinationBucket,
String destinationKey,
CopyObjectRequest copyObjectRequest,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(sourceBucket), "sourceBucket must not be null");
checkNotNull(StringUtils.trimToNull(sourceKey), "sourceKey must not be null");
checkNotNull(StringUtils.trimToNull(destinationBucket), "destinationBucket must not be null");
checkNotNull(StringUtils.trimToNull(destinationKey), "destinationKey must not be null");
checkNotNull(copyObjectRequest, "copyObjectRequest must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createCopyRequest(sourceBucket, sourceKey, destinationBucket, destinationKey, copyObjectRequest, new StreamResponseHandler("copyObject", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end();
}
public void deleteObject(String bucket,
String key,
DeleteObjectRequest deleteObjectRequest,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(bucket), "bucket must not be null");
checkNotNull(StringUtils.trimToNull(key), "bucket must not be null");
checkNotNull(deleteObjectRequest, "deleteObjectRequest must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createDeleteRequest(bucket, key, deleteObjectRequest, new StreamResponseHandler("deleteObject", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end();
}
public void getBucket(String bucket,
GetBucketRequest getBucketRequest,
Handler handler,
Handler exceptionHandler) {
checkNotNull(StringUtils.trimToNull(bucket), "bucket must not be null");
checkNotNull(getBucketRequest, "getBucketRequest must not be null");
checkNotNull(handler, "handler must not be null");
checkNotNull(exceptionHandler, "exceptionHandler must not be null");
final S3ClientRequest request = createGetBucketRequest(bucket, getBucketRequest, new BodyResponseHandler<>("getBucket", jaxbUnmarshaller, handler, exceptionHandler));
request.exceptionHandler(exceptionHandler);
request.end();
}
private S3ClientRequest createPutRequest(String bucket,
String key,
PutObjectRequest putObjectRequest,
Handler handler) {
HttpClientRequest httpRequest = client.put("/" + bucket + "/" + key,
handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"PUT",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
s3ClientRequest.headers().addAll(populatePutObjectHeaders(putObjectRequest));
return s3ClientRequest;
}
private MultiMap populatePutObjectHeaders(PutObjectRequest putObjectRequest) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
if (StringUtils.trimToNull(putObjectRequest.getCacheControl()) != null) {
headers.add("Cache-Control", StringUtils.trim(putObjectRequest.getCacheControl()));
}
if (StringUtils.trimToNull(putObjectRequest.getContentDisposition()) != null) {
headers.add("Content-Disposition", StringUtils.trim(putObjectRequest.getContentDisposition()));
}
if (StringUtils.trimToNull(putObjectRequest.getContentEncoding()) != null) {
headers.add("Content-Encoding", StringUtils.trim(putObjectRequest.getContentEncoding()));
}
if (StringUtils.trimToNull(putObjectRequest.getContentMD5()) != null) {
headers.add("Content-MD5", StringUtils.trim(putObjectRequest.getContentMD5()));
}
if (StringUtils.trimToNull(putObjectRequest.getContentType()) != null) {
headers.add("Content-Type", StringUtils.trim(putObjectRequest.getContentType()));
}
if (StringUtils.trimToNull(putObjectRequest.getExpect()) != null) {
headers.add("Expect", StringUtils.trim(putObjectRequest.getExpect()));
}
if (StringUtils.trimToNull(putObjectRequest.getExpires()) != null) {
headers.add("Expires", StringUtils.trim(putObjectRequest.getExpires()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzStorageClass()) != null) {
headers.add("x-amz-storage-class", StringUtils.trim(putObjectRequest.getAmzStorageClass()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzTagging()) != null) {
headers.add("x-amz-tagging", StringUtils.trim(putObjectRequest.getAmzTagging()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzWebsiteRedirectLocation()) != null) {
headers.add("x-amz-website-redirect-location", StringUtils.trim(putObjectRequest.getAmzWebsiteRedirectLocation()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzAcl()) != null) {
headers.add("x-amz-acl", StringUtils.trim(putObjectRequest.getAmzAcl()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantRead()) != null) {
headers.add("x-amz-grant-read", StringUtils.trim(putObjectRequest.getAmzGrantRead()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantWrite()) != null) {
headers.add("x-amz-grant-write", StringUtils.trim(putObjectRequest.getAmzGrantWrite()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantWrite()) != null) {
headers.add("x-amz-grant-write", StringUtils.trim(putObjectRequest.getAmzGrantWrite()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantReadAcp()) != null) {
headers.add("x-amz-grant-read-acp", StringUtils.trim(putObjectRequest.getAmzGrantReadAcp()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantWriteAcp()) != null) {
headers.add("x-amz-grant-write-acp", StringUtils.trim(putObjectRequest.getAmzGrantWriteAcp()));
}
if (StringUtils.trimToNull(putObjectRequest.getAmzGrantFullControl()) != null) {
headers.add("x-amz-grant-full-control", StringUtils.trim(putObjectRequest.getAmzGrantFullControl()));
}
return headers;
}
private S3ClientRequest createCopyRequest(String sourceBucket,
String sourceKey,
String destinationBucket,
String destinationKey,
CopyObjectRequest copyObjectRequest,
Handler handler) {
final HttpClientRequest httpRequest = client.put("/" + destinationBucket + "/" + destinationKey, handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"PUT",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
s3ClientRequest.putHeader(S3Headers.COPY_SOURCE_HEADER.getValue(), "/" + sourceBucket + "/" + sourceKey);
s3ClientRequest.headers().addAll(populateCopyObjectHeaders(copyObjectRequest));
return s3ClientRequest;
}
private MultiMap populateCopyObjectHeaders(CopyObjectRequest copyObjectRequest) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
if (StringUtils.trimToNull(copyObjectRequest.getAmzMetadataDirective()) != null) {
headers.add("x-amz-metadata-directive", StringUtils.trim(copyObjectRequest.getAmzMetadataDirective()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzCopySourceIfMatch()) != null) {
headers.add("x-amz-copy-source-if-match", StringUtils.trim(copyObjectRequest.getAmzCopySourceIfMatch()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzCopySourceIfNoneMatch()) != null) {
headers.add("x-amz-copy-source-if-none-match", StringUtils.trim(copyObjectRequest.getAmzCopySourceIfNoneMatch()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzCopySourceIfUnmodifiedSince()) != null) {
headers.add("x-amz-copy-source-if-unmodified-since", StringUtils.trim(copyObjectRequest.getAmzCopySourceIfUnmodifiedSince()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzCopySourceIfModifiedSince()) != null) {
headers.add("x-amz-copy-source-if-modified-since", StringUtils.trim(copyObjectRequest.getAmzCopySourceIfModifiedSince()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzStorageClass()) != null) {
headers.add("x-amz-storage-class", StringUtils.trim(copyObjectRequest.getAmzStorageClass()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzTaggingDirective()) != null) {
headers.add("x-amz-tagging-directive", StringUtils.trim(copyObjectRequest.getAmzTaggingDirective()));
}
if (StringUtils.trimToNull(copyObjectRequest.getAmzWebsiteRedirectLocation()) != null) {
headers.add("x-amz-website-redirect-location", StringUtils.trim(copyObjectRequest.getAmzWebsiteRedirectLocation()));
}
return headers;
}
private S3ClientRequest createGetRequest(String bucket,
String key,
GetObjectRequest getObjectRequest,
Handler handler) {
final HttpClientRequest httpRequest = client.get(UrlEncodingUtils.addParamsSortedToUrl("/" + bucket + "/" + key, populateGetObjectQueryParams(getObjectRequest)), handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"GET",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
s3ClientRequest.headers().addAll(populateGetObjectHeaders(getObjectRequest));
return s3ClientRequest;
}
private Map populateGetObjectQueryParams(GetObjectRequest getObjectRequest) {
final Map queryParams = new HashMap<>();
if (StringUtils.trimToNull(getObjectRequest.getResponseCacheControl()) != null) {
queryParams.put("response-cache-control", StringUtils.trim(getObjectRequest.getResponseCacheControl()));
}
if (StringUtils.trimToNull(getObjectRequest.getResponseContentDisposition()) != null) {
queryParams.put("response-content-disposition", StringUtils.trim(getObjectRequest.getResponseContentDisposition()));
}
if (StringUtils.trimToNull(getObjectRequest.getResponseContentEncoding()) != null) {
queryParams.put("response-content-encoding", StringUtils.trim(getObjectRequest.getResponseContentEncoding()));
}
if (StringUtils.trimToNull(getObjectRequest.getResponseContentLanguage()) != null) {
queryParams.put("response-content-language", StringUtils.trim(getObjectRequest.getResponseContentLanguage()));
}
if (StringUtils.trimToNull(getObjectRequest.getResponseContentType()) != null) {
queryParams.put("response-content-type", StringUtils.trim(getObjectRequest.getResponseContentType()));
}
if (StringUtils.trimToNull(getObjectRequest.getResponseExpires()) != null) {
queryParams.put("response-expires", StringUtils.trim(getObjectRequest.getResponseExpires()));
}
return queryParams;
}
private MultiMap populateGetObjectHeaders(GetObjectRequest getObjectRequest) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
if (StringUtils.trimToNull(getObjectRequest.getRange()) != null) {
headers.add("Range", StringUtils.trim(getObjectRequest.getRange()));
}
if (StringUtils.trimToNull(getObjectRequest.getIfModifiedSince()) != null) {
headers.add("If-Modified-Since", StringUtils.trim(getObjectRequest.getIfModifiedSince()));
}
if (StringUtils.trimToNull(getObjectRequest.getIfUnmodifiedSince()) != null) {
headers.add("If-Unmodified-Since", StringUtils.trim(getObjectRequest.getIfUnmodifiedSince()));
}
if (StringUtils.trimToNull(getObjectRequest.getIfMatch()) != null) {
headers.add("If-Match", StringUtils.trim(getObjectRequest.getIfMatch()));
}
if (StringUtils.trimToNull(getObjectRequest.getIfNoneMatch()) != null) {
headers.add("If-None-Match", StringUtils.trim(getObjectRequest.getIfNoneMatch()));
}
return headers;
}
private S3ClientRequest createHeadRequest(String bucket,
String key,
HeadObjectRequest headObjectRequest,
Handler handler) {
final HttpClientRequest httpRequest = client.head("/" + bucket + "/" + key, handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"HEAD",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
s3ClientRequest.headers().addAll(populateHeadObjectHeaders(headObjectRequest));
return s3ClientRequest;
}
private MultiMap populateHeadObjectHeaders(HeadObjectRequest headObjectRequest) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
if (StringUtils.trimToNull(headObjectRequest.getRange()) != null) {
headers.add("Range", StringUtils.trim(headObjectRequest.getRange()));
}
if (StringUtils.trimToNull(headObjectRequest.getIfModifiedSince()) != null) {
headers.add("If-Modified-Since", StringUtils.trim(headObjectRequest.getIfModifiedSince()));
}
if (StringUtils.trimToNull(headObjectRequest.getIfUnmodifiedSince()) != null) {
headers.add("If-Unmodified-Since", StringUtils.trim(headObjectRequest.getIfUnmodifiedSince()));
}
if (StringUtils.trimToNull(headObjectRequest.getIfMatch()) != null) {
headers.add("If-Match", StringUtils.trim(headObjectRequest.getIfMatch()));
}
if (StringUtils.trimToNull(headObjectRequest.getIfNoneMatch()) != null) {
headers.add("If-None-Match", StringUtils.trim(headObjectRequest.getIfNoneMatch()));
}
return headers;
}
private S3ClientRequest createGetBucketRequest(String bucket,
GetBucketRequest getBucketRequest,
Handler handler) {
final HttpClientRequest httpRequest = client.get(UrlEncodingUtils.addParamsSortedToUrl("/" + bucket, populateGetBucketQueryParams(getBucketRequest)), handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"GET",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
return s3ClientRequest;
}
private Map populateGetBucketQueryParams(GetBucketRequest listObjectsRequest) {
final Map queryParams = new HashMap<>();
queryParams.put("list-type", "2");
if (StringUtils.trimToNull(listObjectsRequest.getContinuationToken()) != null) {
queryParams.put("continuation-token", StringUtils.trim(listObjectsRequest.getContinuationToken()));
}
if (StringUtils.trimToNull(listObjectsRequest.getDelimiter()) != null) {
queryParams.put("delimiter", StringUtils.trim(listObjectsRequest.getDelimiter()));
}
if (StringUtils.trimToNull(listObjectsRequest.getEncodingType()) != null) {
queryParams.put("encoding-type", StringUtils.trim(listObjectsRequest.getEncodingType()));
}
if (StringUtils.trimToNull(listObjectsRequest.getFetchOwner()) != null) {
queryParams.put("fetch-owner", StringUtils.trim(listObjectsRequest.getFetchOwner()));
}
if (listObjectsRequest.getMaxKeys() != null) {
queryParams.put("max-keys", StringUtils.trim(listObjectsRequest.getMaxKeys().toString()));
}
if (StringUtils.trimToNull(listObjectsRequest.getPrefix()) != null) {
queryParams.put("prefix", StringUtils.trim(listObjectsRequest.getPrefix()));
}
if (StringUtils.trimToNull(listObjectsRequest.getStartAfter()) != null) {
queryParams.put("start-after", StringUtils.trim(listObjectsRequest.getStartAfter()));
}
return queryParams;
}
private S3ClientRequest createDeleteRequest(String bucket,
String key,
DeleteObjectRequest deleteObjectRequest,
Handler handler) {
final HttpClientRequest httpRequest = client.delete("/" + bucket + "/" + key, handler);
final S3ClientRequest s3ClientRequest = new S3ClientRequest(
"DELETE",
awsRegion,
awsServiceName,
httpRequest,
awsAccessKey,
awsSecretKey,
clock,
signPayload
)
.setTimeout(globalTimeout)
.putHeader("Host", hostname);
s3ClientRequest.headers().addAll(populateDeleteObjectHeaders(deleteObjectRequest));
return s3ClientRequest;
}
private MultiMap populateDeleteObjectHeaders(DeleteObjectRequest deleteObjectRequest) {
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
if (StringUtils.trimToNull(deleteObjectRequest.getAmzMfa()) != null) {
headers.add("x-amz-mfa", StringUtils.trim(deleteObjectRequest.getAmzMfa()));
}
return headers;
}
private JAXBContext createJAXBContext() {
try {
return JAXBContext.newInstance(
Contents.class,
CommonPrefixes.class,
GetBucketRespone.class,
Owner.class,
ErrorResponse.class
);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Marshaller createJaxbMarshaller() {
try {
final JAXBContext jaxbContext = createJAXBContext();
final Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
return jaxbMarshaller;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Unmarshaller createJaxbUnmarshaller() {
try {
final JAXBContext jaxbContext = createJAXBContext();
return jaxbContext.createUnmarshaller();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private SAXSource convertToSaxSource(byte[] payload) throws SAXException {
//Create an XMLReader to use with our filter
final XMLReader reader = XMLReaderFactory.createXMLReader();
//Create the filter to remove all namespaces and set the xmlReader as its parent.
final NamespaceFilter inFilter = new NamespaceFilter(null, false);
inFilter.setParent(reader);
final InputSource inputSource = new InputSource(new ByteArrayInputStream(payload));
//Create a SAXSource specifying the filter
return new SAXSource(inFilter, inputSource);
}
private class StreamResponseHandler implements Handler {
private final String action;
private final Unmarshaller jaxbUnmarshaller;
private final Handler successHandler;
private final Handler exceptionHandler;
private StreamResponseHandler(String action, Unmarshaller jaxbUnmarshaller, Handler successHandler, Handler exceptionHandler) {
this.action = action;
this.jaxbUnmarshaller = jaxbUnmarshaller;
this.successHandler = successHandler;
this.exceptionHandler = exceptionHandler;
}
@Override
public void handle(HttpClientResponse event) {
if (event.statusCode() / 100 != 2) {
event.bodyHandler(buffer -> {
try {
log.warn("Error occurred. Status: {}, Message: {}", event.statusCode(), event.statusMessage());
if (log.isDebugEnabled()) {
log.debug("Response: {}", new String(buffer.getBytes(), Charsets.UTF_8));
}
exceptionHandler.handle(
new HttpErrorException(
event.statusCode(),
event.statusMessage(),
(ErrorResponse) jaxbUnmarshaller.unmarshal(convertToSaxSource(buffer.getBytes())),
"Error occurred during on '" + action + "'"
)
);
} catch (Exception e) {
exceptionHandler.handle(e);
}
});
} else {
successHandler.handle(event);
}
}
}
private class BodyResponseHandler implements Handler {
private final String action;
private final Unmarshaller jaxbUnmarshaller;
private final Handler successHandler;
private final Handler exceptionHandler;
private BodyResponseHandler(String action, Unmarshaller jaxbUnmarshaller, Handler successHandler, Handler exceptionHandler) {
this.action = action;
this.jaxbUnmarshaller = jaxbUnmarshaller;
this.successHandler = successHandler;
this.exceptionHandler = exceptionHandler;
}
@Override
public void handle(HttpClientResponse event) {
event.bodyHandler(buffer -> {
try {
if (event.statusCode() / 100 != 2) {
log.warn("Error occurred. Status: {}, Message: {}", event.statusCode(), event.statusMessage());
if (log.isDebugEnabled()) {
log.debug("Response: {}", new String(buffer.getBytes(), Charsets.UTF_8));
}
exceptionHandler.handle(
new HttpErrorException(
event.statusCode(),
event.statusMessage(),
(ErrorResponse) jaxbUnmarshaller.unmarshal(convertToSaxSource(buffer.getBytes())),
"Error occurred on '" + action + "'"
)
);
} else {
if (log.isDebugEnabled()) {
log.debug("Request successful. Status: {}, Message: {}", event.statusCode(), event.statusMessage());
log.debug("Response: {}", new String(buffer.getBytes(), Charsets.UTF_8));
}
successHandler.handle((T) jaxbUnmarshaller.unmarshal(convertToSaxSource(buffer.getBytes())));
}
} catch (Exception e) {
exceptionHandler.handle(e);
}
});
}
}
private class HeadersResponseHandler implements Handler {
private final String action;
private final Unmarshaller jaxbUnmarshaller;
private final Handler successHandler;
private final Handler exceptionHandler;
private HeadersResponseHandler(String action, Unmarshaller jaxbUnmarshaller, Handler successHandler, Handler exceptionHandler) {
this.action = action;
this.jaxbUnmarshaller = jaxbUnmarshaller;
this.successHandler = successHandler;
this.exceptionHandler = exceptionHandler;
}
@Override
public void handle(HttpClientResponse event) {
event.bodyHandler(buffer -> {
try {
if (event.statusCode() / 100 != 2) {
log.warn("Error occurred. Status: {}, Message: {}", event.statusCode(), event.statusMessage());
if (log.isDebugEnabled()) {
log.debug("Response: {}", new String(buffer.getBytes(), Charsets.UTF_8));
}
exceptionHandler.handle(
new HttpErrorException(
event.statusCode(),
event.statusMessage(),
(ErrorResponse) jaxbUnmarshaller.unmarshal(convertToSaxSource(buffer.getBytes())),
"Error occurred on '" + action + "'"
)
);
} else {
if (log.isDebugEnabled()) {
log.debug("Request successful. Status: {}, Message: {}", event.statusCode(), event.statusMessage());
log.debug("Response: {}", new String(buffer.getBytes(), Charsets.UTF_8));
}
successHandler.handle(event.headers());
}
} catch (Exception e) {
exceptionHandler.handle(e);
}
});
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy