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.core; 17 18 import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; 19 20 import java.io.InputStream; 21 import java.io.UncheckedIOException; 22 import java.util.Arrays; 23 import software.amazon.awssdk.annotations.SdkPublicApi; 24 import software.amazon.awssdk.core.async.AsyncResponseTransformer; 25 import software.amazon.awssdk.core.sync.ResponseTransformer; 26 import software.amazon.awssdk.utils.IoUtils; 27 import software.amazon.awssdk.utils.ToString; 28 import software.amazon.awssdk.utils.Validate; 29 30 /** 31 * An in-memory representation of the service's response from a streaming operation. This usually obtained by calling the "bytes" 32 * form of a streaming operation, like S3's {@code getObjectBytes}. Can also be retrieved by passing 33 * {@link ResponseTransformer#toBytes()} or {@link AsyncResponseTransformer#toBytes()} to a streaming output operation. 34 */ 35 @SdkPublicApi 36 public final class ResponseBytes<ResponseT> extends BytesWrapper { 37 private final ResponseT response; 38 ResponseBytes(ResponseT response, byte[] bytes)39 private ResponseBytes(ResponseT response, byte[] bytes) { 40 super(bytes); 41 this.response = Validate.paramNotNull(response, "response"); 42 } 43 44 /** 45 * Create {@link ResponseBytes} from a Byte array. This will copy the contents of the byte array. 46 */ fromInputStream(ResponseT response, InputStream stream)47 public static <ResponseT> ResponseBytes<ResponseT> fromInputStream(ResponseT response, InputStream stream) 48 throws UncheckedIOException { 49 return new ResponseBytes<>(response, invokeSafely(() -> IoUtils.toByteArray(stream))); 50 } 51 52 /** 53 * Create {@link ResponseBytes} from a Byte array. This will copy the contents of the byte array. 54 */ fromByteArray(ResponseT response, byte[] bytes)55 public static <ResponseT> ResponseBytes<ResponseT> fromByteArray(ResponseT response, byte[] bytes) { 56 return new ResponseBytes<>(response, Arrays.copyOf(bytes, bytes.length)); 57 } 58 59 /** 60 * Create {@link ResponseBytes} from a Byte array <b>without</b> copying the contents of the byte array. This introduces 61 * concurrency risks, allowing: (1) the caller to modify the byte array stored in this {@code SdkBytes} implementation AND 62 * (2) any users of {@link #asByteArrayUnsafe()} to modify the byte array passed into this {@code SdkBytes} implementation. 63 * 64 * <p>As the method name implies, this is unsafe. Use {@link #fromByteArray(Object, byte[])} unless you're sure you know the 65 * risks. 66 */ fromByteArrayUnsafe(ResponseT response, byte[] bytes)67 public static <ResponseT> ResponseBytes<ResponseT> fromByteArrayUnsafe(ResponseT response, byte[] bytes) { 68 return new ResponseBytes<>(response, bytes); 69 } 70 71 /** 72 * @return the unmarshalled response object from the service. 73 */ response()74 public ResponseT response() { 75 return response; 76 } 77 78 @Override toString()79 public String toString() { 80 return ToString.builder("ResponseBytes") 81 .add("response", response) 82 .add("bytes", asByteArrayUnsafe()) 83 .build(); 84 } 85 86 @Override equals(Object o)87 public boolean equals(Object o) { 88 if (this == o) { 89 return true; 90 } 91 if (o == null || getClass() != o.getClass()) { 92 return false; 93 } 94 if (!super.equals(o)) { 95 return false; 96 } 97 98 ResponseBytes<?> that = (ResponseBytes<?>) o; 99 100 return response != null ? response.equals(that.response) : that.response == null; 101 } 102 103 @Override hashCode()104 public int hashCode() { 105 int result = super.hashCode(); 106 result = 31 * result + (response != null ? response.hashCode() : 0); 107 return result; 108 } 109 } 110