1
15
16 package software.amazon.awssdk.core.internal.handler;
17
18 import java.util.Optional;
19 import software.amazon.awssdk.annotations.SdkInternalApi;
20 import software.amazon.awssdk.core.Response;
21 import software.amazon.awssdk.core.SdkRequest;
22 import software.amazon.awssdk.core.SdkResponse;
23 import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
24 import software.amazon.awssdk.core.client.handler.ClientExecutionParams;
25 import software.amazon.awssdk.core.client.handler.SyncClientHandler;
26 import software.amazon.awssdk.core.exception.AbortedException;
27 import software.amazon.awssdk.core.exception.NonRetryableException;
28 import software.amazon.awssdk.core.exception.RetryableException;
29 import software.amazon.awssdk.core.http.ExecutionContext;
30 import software.amazon.awssdk.core.http.HttpResponseHandler;
31 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
32 import software.amazon.awssdk.core.interceptor.InterceptorContext;
33 import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient;
34 import software.amazon.awssdk.core.internal.http.CombinedResponseHandler;
35 import software.amazon.awssdk.core.internal.http.InterruptMonitor;
36 import software.amazon.awssdk.core.sync.RequestBody;
37 import software.amazon.awssdk.core.sync.ResponseTransformer;
38 import software.amazon.awssdk.http.AbortableInputStream;
39 import software.amazon.awssdk.http.SdkHttpFullRequest;
40 import software.amazon.awssdk.http.SdkHttpFullResponse;
41
42 @SdkInternalApi
43 public abstract class BaseSyncClientHandler extends BaseClientHandler implements SyncClientHandler {
44 private final SdkClientConfiguration clientConfiguration;
45 private final AmazonSyncHttpClient client;
46
47 protected BaseSyncClientHandler(SdkClientConfiguration clientConfiguration,
48 AmazonSyncHttpClient client) {
49 super(clientConfiguration);
50 this.clientConfiguration = clientConfiguration;
51 this.client = client;
52 }
53
54 @Override
55 public <InputT extends SdkRequest, OutputT extends SdkResponse, ReturnT> ReturnT execute(
56 ClientExecutionParams<InputT, OutputT> executionParams,
57 ResponseTransformer<OutputT, ReturnT> responseTransformer) {
58
59 validateExecutionParams(executionParams);
60
61 if (executionParams.getCombinedResponseHandler() != null) {
62
63 throw new IllegalArgumentException("A streaming 'responseTransformer' may not be used when a "
64 + "'combinedResponseHandler' has been specified in a "
65 + "ClientExecutionParams object.");
66 }
67
68 ExecutionContext executionContext = createExecutionContext(executionParams, createInitialExecutionAttributes());
69
70 HttpResponseHandler<OutputT> decoratedResponseHandlers =
71 decorateResponseHandlers(executionParams.getResponseHandler(), executionContext);
72
73 HttpResponseHandler<ReturnT> httpResponseHandler =
74 new HttpResponseHandlerAdapter<>(decoratedResponseHandlers, responseTransformer);
75
76 return doExecute(
77 executionParams,
78 executionContext,
79 new CombinedResponseHandler<>(httpResponseHandler, executionParams.getErrorResponseHandler()));
80 }
81
82 @Override
83 public <InputT extends SdkRequest, OutputT extends SdkResponse> OutputT execute(
84 ClientExecutionParams<InputT, OutputT> executionParams) {
85
86 validateExecutionParams(executionParams);
87 ExecutionContext executionContext = createExecutionContext(executionParams, createInitialExecutionAttributes());
88 HttpResponseHandler<Response<OutputT>> combinedResponseHandler;
89
90 if (executionParams.getCombinedResponseHandler() != null) {
91 combinedResponseHandler = decorateSuccessResponseHandlers(executionParams.getCombinedResponseHandler(),
92 executionContext);
93 } else {
94 HttpResponseHandler<OutputT> decoratedResponseHandlers =
95 decorateResponseHandlers(executionParams.getResponseHandler(), executionContext);
96
97 combinedResponseHandler = new CombinedResponseHandler<>(decoratedResponseHandlers,
98 executionParams.getErrorResponseHandler());
99 }
100
101 return doExecute(executionParams, executionContext, combinedResponseHandler);
102 }
103
104 @Override
105 public void close() {
106 client.close();
107 }
108
109
113 private <OutputT> OutputT invoke(SdkHttpFullRequest request,
114 SdkRequest originalRequest,
115 ExecutionContext executionContext,
116 HttpResponseHandler<Response<OutputT>> responseHandler) {
117 return client.requestExecutionBuilder()
118 .request(request)
119 .originalRequest(originalRequest)
120 .executionContext(executionContext)
121 .execute(responseHandler);
122 }
123
124 private <InputT extends SdkRequest, OutputT, ReturnT> ReturnT doExecute(
125 ClientExecutionParams<InputT, OutputT> executionParams,
126 ExecutionContext executionContext,
127 HttpResponseHandler<Response<ReturnT>> responseHandler) {
128
129 InputT inputT = (InputT) finalizeSdkRequest(executionContext).request();
130
131 InterceptorContext sdkHttpFullRequestContext = finalizeSdkHttpFullRequest(executionParams,
132 executionContext,
133 inputT,
134 clientConfiguration);
135
136 SdkHttpFullRequest marshalled = (SdkHttpFullRequest) sdkHttpFullRequestContext.httpRequest();
137
138
139 Optional<RequestBody> requestBody = sdkHttpFullRequestContext.requestBody();
140
141 if (requestBody.isPresent()) {
142 marshalled = marshalled.toBuilder()
143 .contentStreamProvider(requestBody.get().contentStreamProvider())
144 .build();
145 }
146
147 return invoke(marshalled,
148 inputT,
149 executionContext,
150 responseHandler);
151 }
152
153 private static class HttpResponseHandlerAdapter<ReturnT, OutputT extends SdkResponse>
154 implements HttpResponseHandler<ReturnT> {
155
156 private final HttpResponseHandler<OutputT> httpResponseHandler;
157 private final ResponseTransformer<OutputT, ReturnT> responseTransformer;
158
159 private HttpResponseHandlerAdapter(HttpResponseHandler<OutputT> httpResponseHandler,
160 ResponseTransformer<OutputT, ReturnT> responseTransformer) {
161 this.httpResponseHandler = httpResponseHandler;
162 this.responseTransformer = responseTransformer;
163 }
164
165 @Override
166 public ReturnT handle(SdkHttpFullResponse response, ExecutionAttributes executionAttributes) throws Exception {
167 OutputT resp = httpResponseHandler.handle(response, executionAttributes);
168 return transformResponse(resp, response.content().orElse(null));
169 }
170
171 @Override
172 public boolean needsConnectionLeftOpen() {
173 return responseTransformer.needsConnectionLeftOpen();
174 }
175
176
177 private ReturnT transformResponse(OutputT resp, AbortableInputStream inputStream) throws Exception {
178 try {
179 InterruptMonitor.checkInterrupted();
180 ReturnT result = responseTransformer.transform(resp, inputStream);
181 InterruptMonitor.checkInterrupted();
182 return result;
183 } catch (RetryableException | InterruptedException | AbortedException e) {
184 throw e;
185 } catch (Exception e) {
186 InterruptMonitor.checkInterrupted();
187 throw NonRetryableException.builder().cause(e).build();
188 }
189 }
190 }
191 }
192