1 /* 2 * Copyright 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.protocols.json.internal.unmarshall; 17 18 import java.nio.charset.StandardCharsets; 19 import java.time.Instant; 20 import java.util.List; 21 import software.amazon.awssdk.annotations.SdkInternalApi; 22 import software.amazon.awssdk.core.SdkField; 23 import software.amazon.awssdk.core.traits.JsonValueTrait; 24 import software.amazon.awssdk.protocols.core.StringToValueConverter; 25 import software.amazon.awssdk.protocols.jsoncore.JsonNode; 26 import software.amazon.awssdk.utils.BinaryUtils; 27 28 /** 29 * Header unmarshallers for all the simple types we support. 30 */ 31 @SdkInternalApi 32 final class HeaderUnmarshaller { 33 34 public static final JsonUnmarshaller<String> STRING = 35 new SimpleHeaderUnmarshaller<>(HeaderUnmarshaller::unmarshallStringHeader); 36 public static final JsonUnmarshaller<Integer> INTEGER = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_INTEGER); 37 public static final JsonUnmarshaller<Long> LONG = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_LONG); 38 public static final JsonUnmarshaller<Short> SHORT = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_SHORT); 39 public static final JsonUnmarshaller<Double> DOUBLE = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_DOUBLE); 40 public static final JsonUnmarshaller<Boolean> BOOLEAN = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_BOOLEAN); 41 public static final JsonUnmarshaller<Float> FLOAT = new SimpleHeaderUnmarshaller<>(StringToValueConverter.TO_FLOAT); 42 43 // Only supports string value type 44 public static final JsonUnmarshaller<List<?>> LIST = 45 (context, jsonContent, field) -> context.response().matchingHeaders(field.locationName()); 46 HeaderUnmarshaller()47 private HeaderUnmarshaller() { 48 } 49 50 /** 51 * Unmarshalls a string header, taking into account whether it's a Base 64 encoded JSON value. 52 * <p> 53 * <em>Note:</em> This code does no attempt to validate whether the unmarshalled string does, in fact, represent valid 54 * JSON values. The string value is returned as-is, and it's up to the user to validate the results. 55 * 56 * @param value Value to unmarshall 57 * @param field {@link SdkField} containing metadata about member being unmarshalled. 58 * @return Unmarshalled value. 59 */ unmarshallStringHeader(String value, SdkField<String> field)60 private static String unmarshallStringHeader(String value, 61 SdkField<String> field) { 62 return field.containsTrait(JsonValueTrait.class) ? 63 new String(BinaryUtils.fromBase64(value), StandardCharsets.UTF_8) : value; 64 } 65 createInstantHeaderUnmarshaller( StringToValueConverter.StringToValue<Instant> instantStringToValue)66 public static JsonUnmarshaller<Instant> createInstantHeaderUnmarshaller( 67 StringToValueConverter.StringToValue<Instant> instantStringToValue) { 68 return new SimpleHeaderUnmarshaller<>(instantStringToValue); 69 } 70 71 /** 72 * Simple unmarshaller implementation that calls a {@link StringToValueConverter} with the header value if it's present. 73 * 74 * @param <T> Type to unmarshall into. 75 */ 76 private static class SimpleHeaderUnmarshaller<T> implements JsonUnmarshaller<T> { 77 78 private final StringToValueConverter.StringToValue<T> stringToValue; 79 SimpleHeaderUnmarshaller(StringToValueConverter.StringToValue<T> stringToValue)80 private SimpleHeaderUnmarshaller(StringToValueConverter.StringToValue<T> stringToValue) { 81 this.stringToValue = stringToValue; 82 } 83 84 @Override unmarshall(JsonUnmarshallerContext context, JsonNode jsonContent, SdkField<T> field)85 public T unmarshall(JsonUnmarshallerContext context, 86 JsonNode jsonContent, 87 SdkField<T> field) { 88 return context.response().firstMatchingHeader(field.locationName()) 89 .map(s -> stringToValue.convert(s, field)) 90 .orElse(null); 91 } 92 } 93 } 94