Skip to content

Commit d867703

Browse files
committed
Move Stax parser classes and AWS speicifc JSON Unmarshaller/Mashaller to aws-core
1 parent c12a09c commit d867703

File tree

94 files changed

+2049
-653
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+2049
-653
lines changed

aws-core/src/main/java/software/amazon/awssdk/awscore/client/handler/AwsClientHandlerUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import software.amazon.awssdk.utils.Validate;
3434

3535
@SdkInternalApi
36-
class AwsClientHandlerUtils {
36+
final class AwsClientHandlerUtils {
3737

3838
private AwsClientHandlerUtils() {
3939

core/src/main/java/software/amazon/awssdk/core/internal/http/response/JsonErrorResponseHandler.java renamed to aws-core/src/main/java/software/amazon/awssdk/awscore/http/response/AwsJsonErrorResponseHandler.java

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,42 +13,37 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
package software.amazon.awssdk.core.internal.http.response;
16+
package software.amazon.awssdk.awscore.http.response;
1717

1818
import com.fasterxml.jackson.core.JsonFactory;
1919
import java.util.List;
20-
import java.util.Map;
21-
import java.util.Map.Entry;
22-
import org.slf4j.Logger;
23-
import org.slf4j.LoggerFactory;
2420
import software.amazon.awssdk.annotations.SdkInternalApi;
25-
import software.amazon.awssdk.core.exception.ErrorType;
21+
import software.amazon.awssdk.awscore.protocol.json.AwsJsonErrorUnmarshaller;
22+
import software.amazon.awssdk.awscore.protocol.json.ErrorCodeParser;
2623
import software.amazon.awssdk.core.exception.SdkServiceException;
2724
import software.amazon.awssdk.core.http.HttpResponse;
28-
import software.amazon.awssdk.core.http.HttpResponseHandler;
2925
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
3026
import software.amazon.awssdk.core.interceptor.SdkExecutionAttributes;
31-
import software.amazon.awssdk.core.internal.http.ErrorCodeParser;
27+
import software.amazon.awssdk.core.protocol.json.ErrorMessageParser;
3228
import software.amazon.awssdk.core.protocol.json.JsonContent;
33-
import software.amazon.awssdk.core.runtime.http.JsonErrorMessageParser;
34-
import software.amazon.awssdk.core.runtime.transform.JsonErrorUnmarshaller;
35-
import software.amazon.awssdk.http.HttpStatusFamily;
29+
import software.amazon.awssdk.core.runtime.http.response.JsonErrorResponseHandler;
3630

31+
/**
32+
* Implementation of HttpResponseHandler that handles a error response from AWS
33+
* services and unmarshalls the result using a JSON unmarshaller.
34+
*/
3735
@SdkInternalApi
38-
public class JsonErrorResponseHandler implements HttpResponseHandler<SdkServiceException> {
39-
40-
private static final Logger log = LoggerFactory.getLogger(JsonErrorResponseHandler.class);
36+
public class AwsJsonErrorResponseHandler extends JsonErrorResponseHandler {
4137

42-
private final List<JsonErrorUnmarshaller> unmarshallers;
38+
private final List<AwsJsonErrorUnmarshaller> unmarshallers;
4339
private final ErrorCodeParser errorCodeParser;
44-
private final JsonErrorMessageParser errorMessageParser;
40+
private final ErrorMessageParser errorMessageParser;
4541
private final JsonFactory jsonFactory;
4642

47-
public JsonErrorResponseHandler(
48-
List<JsonErrorUnmarshaller> errorUnmarshallers,
49-
ErrorCodeParser errorCodeParser,
50-
JsonErrorMessageParser errorMessageParser,
51-
JsonFactory jsonFactory) {
43+
public AwsJsonErrorResponseHandler(List<AwsJsonErrorUnmarshaller> errorUnmarshallers,
44+
ErrorCodeParser errorCodeParser,
45+
ErrorMessageParser errorMessageParser,
46+
JsonFactory jsonFactory) {
5247
this.unmarshallers = errorUnmarshallers;
5348
this.errorCodeParser = errorCodeParser;
5449
this.errorMessageParser = errorMessageParser;
@@ -88,44 +83,15 @@ public SdkServiceException handle(HttpResponse response,
8883
* Create an SdkServiceException using the chain of unmarshallers. This method will never
8984
* return null, it will always return a valid SdkServiceException
9085
*
91-
* @param errorCode Error code to find an appropriate unmarshaller
86+
* @param errorCode Error code to find an appropriate unmarshaller
9287
* @param jsonContent JsonContent of HTTP response
9388
* @return SdkServiceException
9489
*/
9590
private SdkServiceException createException(String errorCode, JsonContent jsonContent) {
96-
SdkServiceException exception = unmarshallException(errorCode, jsonContent);
97-
if (exception == null) {
98-
exception = new SdkServiceException(
99-
"Unable to unmarshall exception response with the unmarshallers provided");
100-
}
101-
return exception;
102-
}
103-
104-
private SdkServiceException unmarshallException(String errorCode, JsonContent jsonContent) {
105-
for (JsonErrorUnmarshaller unmarshaller : unmarshallers) {
106-
if (unmarshaller.matchErrorCode(errorCode)) {
107-
try {
108-
return unmarshaller.unmarshall(jsonContent.getJsonNode());
109-
} catch (Exception e) {
110-
log.debug("Unable to unmarshall exception content", e);
111-
return null;
112-
}
113-
}
114-
}
115-
return null;
91+
return unmarshallers.stream()
92+
.filter(u -> u.matchErrorCode(errorCode))
93+
.findFirst()
94+
.map(u -> safeUnmarshall(jsonContent, u))
95+
.orElseGet(this::createUnknownException);
11696
}
117-
118-
private ErrorType getErrorType(int statusCode) {
119-
return HttpStatusFamily.of(statusCode) == HttpStatusFamily.SERVER_ERROR ? ErrorType.SERVICE : ErrorType.CLIENT;
120-
}
121-
122-
private String getRequestIdFromHeaders(Map<String, String> headers) {
123-
for (Entry<String, String> headerEntry : headers.entrySet()) {
124-
if (headerEntry.getKey().equalsIgnoreCase(X_AMZN_REQUEST_ID_HEADER)) {
125-
return headerEntry.getValue();
126-
}
127-
}
128-
return null;
129-
}
130-
13197
}

aws-core/src/main/java/software/amazon/awssdk/awscore/http/DefaultErrorResponseHandler.java renamed to aws-core/src/main/java/software/amazon/awssdk/awscore/http/response/DefaultErrorResponseHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
package software.amazon.awssdk.awscore.http;
16+
package software.amazon.awssdk.awscore.http.response;
1717

1818
import java.io.IOException;
1919
import java.io.InputStream;

core/src/main/java/software/amazon/awssdk/core/http/StaxResponseHandler.java renamed to aws-core/src/main/java/software/amazon/awssdk/awscore/http/response/StaxResponseHandler.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
package software.amazon.awssdk.core.http;
16+
package software.amazon.awssdk.awscore.http.response;
1717

1818
import java.io.ByteArrayInputStream;
1919
import java.io.InputStream;
@@ -22,12 +22,16 @@
2222
import javax.xml.stream.XMLStreamException;
2323
import software.amazon.awssdk.annotations.ReviewBeforeRelease;
2424
import software.amazon.awssdk.annotations.SdkProtectedApi;
25+
import software.amazon.awssdk.awscore.protocol.xml.StaxUnmarshallerContext;
26+
import software.amazon.awssdk.awscore.protocol.xml.VoidStaxUnmarshaller;
2527
import software.amazon.awssdk.core.ResponseMetadata;
2628
import software.amazon.awssdk.core.SdkStandardLoggers;
29+
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
30+
import software.amazon.awssdk.core.http.HttpResponse;
31+
import software.amazon.awssdk.core.http.HttpResponseHandler;
2732
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
28-
import software.amazon.awssdk.core.runtime.transform.StaxUnmarshallerContext;
2933
import software.amazon.awssdk.core.runtime.transform.Unmarshaller;
30-
import software.amazon.awssdk.core.runtime.transform.VoidStaxUnmarshaller;
34+
import software.amazon.awssdk.core.sync.ResponseTransformer;
3135
import software.amazon.awssdk.core.util.StringUtils;
3236
import software.amazon.awssdk.utils.FunctionalUtils.UnsafeFunction;
3337
import software.amazon.awssdk.utils.Logger;
@@ -137,7 +141,7 @@ public boolean needsConnectionLeftOpen() {
137141

138142
/**
139143
* Creates an synchronous {@link HttpResponseHandler} that unmarshalls into the response POJO while leaving the
140-
* connection open for further processing (by a {@link StreamingResponseHandler} or {@link AsyncResponseHandler}
144+
* connection open for further processing (by a {@link ResponseTransformer} or {@link AsyncResponseTransformer}
141145
* for example).
142146
*
143147
* @param unmarshaller Unmarshaller for response POJO.
@@ -161,7 +165,7 @@ public boolean needsConnectionLeftOpen() {
161165

162166
/**
163167
* Unmarshalls a streaming HTTP response into a POJO. Does not touch the content since that's consumed by the response
164-
* handler (either {@link StreamingResponseHandler} or {@link AsyncResponseHandler}).
168+
* handler (either {@link ResponseTransformer} or {@link AsyncResponseTransformer}).
165169
*
166170
* @param unmarshaller Unmarshaller for resposne type.
167171
* @param response HTTP response
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.awscore.protocol.json;
17+
18+
import com.fasterxml.jackson.databind.JsonNode;
19+
import software.amazon.awssdk.annotations.SdkProtectedApi;
20+
import software.amazon.awssdk.core.http.HttpResponse;
21+
import software.amazon.awssdk.core.protocol.json.ErrorMessageParser;
22+
import software.amazon.awssdk.core.protocol.json.SdkJsonErrorMessageParser;
23+
24+
@SdkProtectedApi
25+
public class AwsJsonErrorMessageParser implements ErrorMessageParser {
26+
27+
static final ErrorMessageParser DEFAULT_ERROR_MESSAGE_PARSER =
28+
new AwsJsonErrorMessageParser(SdkJsonErrorMessageParser.DEFAULT_ERROR_MESSAGE_PARSER);
29+
30+
/**
31+
* x-amzn-error-message may be returned by RESTFUL services that do not send a response
32+
* payload (like in a HEAD request).
33+
*/
34+
private static final String X_AMZN_ERROR_MESSAGE = "x-amzn-error-message";
35+
36+
private SdkJsonErrorMessageParser errorMessageParser;
37+
38+
/**
39+
* @param errorMessageJsonLocations JSON field locations where the parser will attempt to
40+
* extract the error message from.
41+
*/
42+
public AwsJsonErrorMessageParser(SdkJsonErrorMessageParser errorMessageJsonLocations) {
43+
this.errorMessageParser = errorMessageJsonLocations;
44+
}
45+
46+
/**
47+
* Parse the error message from the response.
48+
*
49+
* @return Error Code of exceptional response or null if it can't be determined
50+
*/
51+
@Override
52+
public String parseErrorMessage(HttpResponse httpResponse, JsonNode jsonNode) {
53+
// If X_AMZN_ERROR_MESSAGE is present, prefer that. Otherwise check the JSON body.
54+
final String headerMessage = httpResponse.getHeader(X_AMZN_ERROR_MESSAGE);
55+
if (headerMessage != null) {
56+
return headerMessage;
57+
}
58+
return errorMessageParser.parseErrorMessage(httpResponse, jsonNode);
59+
}
60+
61+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.awscore.protocol.json;
17+
18+
import static com.fasterxml.jackson.databind.PropertyNamingStrategy.UPPER_CAMEL_CASE;
19+
20+
import com.fasterxml.jackson.databind.DeserializationFeature;
21+
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import software.amazon.awssdk.annotations.SdkInternalApi;
23+
import software.amazon.awssdk.annotations.ThreadSafe;
24+
import software.amazon.awssdk.core.exception.SdkServiceException;
25+
import software.amazon.awssdk.core.protocol.json.JsonErrorUnmarshaller;
26+
27+
/**
28+
* Unmarshaller for JSON error responses from AWS services.
29+
*/
30+
@SdkInternalApi
31+
@ThreadSafe
32+
public class AwsJsonErrorUnmarshaller extends JsonErrorUnmarshaller {
33+
34+
public static final AwsJsonErrorUnmarshaller DEFAULT_UNMARSHALLER = new AwsJsonErrorUnmarshaller(
35+
SdkServiceException.class, null);
36+
37+
private static final ObjectMapper MAPPER = new ObjectMapper().configure(
38+
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).setPropertyNamingStrategy(UPPER_CAMEL_CASE);
39+
40+
private final String handledErrorCode;
41+
42+
/**
43+
* @param exceptionClass Exception class this unmarshaller will attempt to deserialize error response into
44+
* @param handledErrorCode AWS error code that this unmarshaller handles. Pass null to handle all exceptions
45+
*/
46+
public AwsJsonErrorUnmarshaller(Class<? extends SdkServiceException> exceptionClass, String handledErrorCode) {
47+
super(exceptionClass);
48+
this.handledErrorCode = handledErrorCode;
49+
}
50+
51+
/**
52+
* @param actualErrorCode Actual AWS error code found in the error response.
53+
* @return True if the actualErrorCode can be handled by this unmarshaller, false otherwise
54+
*/
55+
public boolean matchErrorCode(String actualErrorCode) {
56+
return handledErrorCode == null || handledErrorCode.equals(actualErrorCode);
57+
}
58+
59+
}

core/src/main/java/software/amazon/awssdk/core/protocol/Protocol.java renamed to aws-core/src/main/java/software/amazon/awssdk/awscore/protocol/json/AwsJsonProtocol.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
* permissions and limitations under the License.
1414
*/
1515

16-
package software.amazon.awssdk.core.protocol;
16+
package software.amazon.awssdk.awscore.protocol.json;
17+
18+
import software.amazon.awssdk.annotations.SdkInternalApi;
1719

1820
/**
1921
* Supported protocols for the new marshalling style. Currently only includes JSON based services.
2022
*/
21-
public enum Protocol {
23+
@SdkInternalApi
24+
public enum AwsJsonProtocol {
2225

2326
/**
2427
* RPC protocol that sends all data in the payload as JSON and sends the X-Amz-Target header to indicate the
@@ -31,9 +34,4 @@ public enum Protocol {
3134
* binary and streaming data. Operation is identified by HTTP verb and resource path combination.
3235
*/
3336
REST_JSON,
34-
35-
/**
36-
* A variation of REST_JSON for externally generated, API Gateway clients.
37-
*/
38-
API_GATEWAY
3937
}

0 commit comments

Comments
 (0)