/** * Validates a specified template. * * @param validateTemplateRequest The input for <a>ValidateTemplate</a> action. * @return Result of the ValidateTemplate operation returned by the service. * @sample AmazonCloudFormation.ValidateTemplate */ @Override public ValidateTemplateResult validateTemplate(ValidateTemplateRequest validateTemplateRequest) { ExecutionContext executionContext = createExecutionContext(validateTemplateRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); awsRequestMetrics.startEvent(Field.ClientExecuteTime); Request<ValidateTemplateRequest> request = null; Response<ValidateTemplateResult> response = null; try { awsRequestMetrics.startEvent(Field.RequestMarshallTime); try { request = new ValidateTemplateRequestMarshaller() .marshall(super.beforeMarshalling(validateTemplateRequest)); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); } finally { awsRequestMetrics.endEvent(Field.RequestMarshallTime); } StaxResponseHandler<ValidateTemplateResult> responseHandler = new StaxResponseHandler<ValidateTemplateResult>( new ValidateTemplateResultStaxUnmarshaller()); response = invoke(request, responseHandler, executionContext); return response.getAwsResponse(); } finally { endClientExecution(awsRequestMetrics, request, response); } }
private <X, Y extends AmazonWebServiceRequest> Response<X> invoke( Request<Y> request, HttpResponseHandler<AmazonWebServiceResponse<X>> responseHandler, ExecutionContext executionContext) { request.setEndpoint(endpoint); request.setTimeOffset(timeOffset); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); AWSCredentials credentials; awsRequestMetrics.startEvent(Field.CredentialsRequestTime); try { credentials = awsCredentialsProvider.getCredentials(); } finally { awsRequestMetrics.endEvent(Field.CredentialsRequestTime); } AmazonWebServiceRequest originalRequest = request.getOriginalRequest(); if (originalRequest != null && originalRequest.getRequestCredentials() != null) { credentials = originalRequest.getRequestCredentials(); } executionContext.setCredentials(credentials); DefaultErrorResponseHandler errorResponseHandler = new DefaultErrorResponseHandler(exceptionUnmarshallers); return client.execute(request, responseHandler, errorResponseHandler, executionContext); }
/** * Sends a signal to the specified resource with a success or failure status. You can use the * SignalResource API in conjunction with a creation policy or update policy. AWS CloudFormation * doesn't proceed with a stack creation or update until resources receive the required number of * signals or the timeout period is exceeded. The SignalResource API is useful in cases where you * want to send signals from anywhere other than an Amazon EC2 instance. * * @param signalResourceRequest The input for the <a>SignalResource</a> action. * @sample AmazonCloudFormation.SignalResource */ @Override public void signalResource(SignalResourceRequest signalResourceRequest) { ExecutionContext executionContext = createExecutionContext(signalResourceRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); awsRequestMetrics.startEvent(Field.ClientExecuteTime); Request<SignalResourceRequest> request = null; Response<Void> response = null; try { awsRequestMetrics.startEvent(Field.RequestMarshallTime); try { request = new SignalResourceRequestMarshaller() .marshall(super.beforeMarshalling(signalResourceRequest)); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); } finally { awsRequestMetrics.endEvent(Field.RequestMarshallTime); } StaxResponseHandler<Void> responseHandler = new StaxResponseHandler<Void>(null); invoke(request, responseHandler, executionContext); } finally { endClientExecution(awsRequestMetrics, request, response); } }
/** * You use this operation to change the parameters specified in the original manifest file by * supplying a new manifest file. The manifest file attached to this request replaces the original * manifest file. You can only use the operation after a CreateJob request but before the data * transfer starts and you can only use it on jobs you own. * * @param updateJobRequest Container for the necessary parameters to execute the UpdateJob service * method on AmazonImportExport. * @return The response from the UpdateJob service method, as returned by AmazonImportExport. * @throws MalformedManifestException * @throws BucketPermissionException * @throws InvalidAddressException * @throws InvalidParameterException * @throws UnableToUpdateJobIdException * @throws MultipleRegionsException * @throws InvalidVersionException * @throws MissingParameterException * @throws InvalidFileSystemException * @throws CanceledJobIdException * @throws MissingCustomsException * @throws NoSuchBucketException * @throws ExpiredJobIdException * @throws InvalidAccessKeyIdException * @throws InvalidCustomsException * @throws InvalidManifestFieldException * @throws MissingManifestFieldException * @throws InvalidJobIdException * @throws AmazonClientException If any internal errors are encountered inside the client while * attempting to make the request or handle the response. For example if a network connection * is not available. * @throws AmazonServiceException If an error response is returned by AmazonImportExport * indicating either a problem with the data in the request, or a server side issue. */ public UpdateJobResult updateJob(UpdateJobRequest updateJobRequest) { ExecutionContext executionContext = createExecutionContext(updateJobRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); awsRequestMetrics.startEvent(Field.ClientExecuteTime); Request<UpdateJobRequest> request = null; Response<UpdateJobResult> response = null; try { awsRequestMetrics.startEvent(Field.RequestMarshallTime); try { request = new UpdateJobRequestMarshaller().marshall(super.beforeMarshalling(updateJobRequest)); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); } finally { awsRequestMetrics.endEvent(Field.RequestMarshallTime); } response = invoke(request, new UpdateJobResultStaxUnmarshaller(), executionContext); return response.getAwsResponse(); } finally { endClientExecution(awsRequestMetrics, request, response); } }
/** Captures the connection pool metrics. */ private void captureConnectionPoolMetrics( ClientConnectionManager connectionManager, AWSRequestMetrics awsRequestMetrics) { if (awsRequestMetrics.isEnabled() && connectionManager instanceof ConnPoolControl) { ConnPoolControl<?> control = (ConnPoolControl<?>) connectionManager; PoolStats stats = control.getTotalStats(); awsRequestMetrics.setCounter( AWSRequestMetrics.Field.HttpClientPoolAvailableCount, stats.getAvailable()); awsRequestMetrics.setCounter( AWSRequestMetrics.Field.HttpClientPoolLeasedCount, stats.getLeased()); awsRequestMetrics.setCounter( AWSRequestMetrics.Field.HttpClientPoolPendingCount, stats.getPending()); } }
/** * Returns a {@link Request} marshalled from the given AWS request using the specified marshaller, * recording the respective {@link Field#RequestMarshallTime} predefined metrics. */ private <T extends AmazonWebServiceRequest> Request<T> marshall( T awsRequest, Marshaller<Request<T>, T> marshaller, AWSRequestMetrics awsRequestMetrics) { awsRequestMetrics.startEvent(Field.RequestMarshallTime); try { return marshaller.marshall(awsRequest); } catch (AmazonClientException ex) { throw ex; } catch (Exception ex) { throw new AmazonClientException(ex.getMessage(), ex); } finally { awsRequestMetrics.endEvent(Field.RequestMarshallTime); } }
/** * Handles a successful response from a service call by unmarshalling the results using the * specified response handler. * * @param <T> The type of object expected in the response. * @param request The original request that generated the response being handled. * @param responseHandler The response unmarshaller used to interpret the contents of the * response. * @param method The HTTP method that was invoked, and contains the contents of the response. * @param executionContext Extra state information about the request currently being executed. * @return The contents of the response, unmarshalled using the specified response handler. * @throws IOException If any problems were encountered reading the response contents from the * HTTP method object. */ private <T> T handleResponse( Request<?> request, HttpResponseHandler<AmazonWebServiceResponse<T>> responseHandler, HttpRequestBase method, org.apache.http.HttpResponse apacheHttpResponse, ExecutionContext executionContext) throws IOException { HttpResponse httpResponse = createResponse(method, request, apacheHttpResponse); if (responseHandler.needsConnectionLeftOpen() && method instanceof HttpEntityEnclosingRequest) { HttpEntityEnclosingRequest httpEntityEnclosingRequest = (HttpEntityEnclosingRequest) method; httpResponse.setContent(new HttpMethodReleaseInputStream(httpEntityEnclosingRequest)); } try { CountingInputStream countingInputStream = null; if (System.getProperty(PROFILING_SYSTEM_PROPERTY) != null) { countingInputStream = new CountingInputStream(httpResponse.getContent()); httpResponse.setContent(countingInputStream); } AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); awsRequestMetrics.startEvent(Field.ResponseProcessingTime.name()); AmazonWebServiceResponse<? extends T> awsResponse = responseHandler.handle(httpResponse); awsRequestMetrics.endEvent(Field.ResponseProcessingTime.name()); if (countingInputStream != null) { awsRequestMetrics.setCounter( Field.BytesProcessed.name(), countingInputStream.getByteCount()); } if (awsResponse == null) throw new RuntimeException("Unable to unmarshall response metadata"); responseMetadataCache.add(request.getOriginalRequest(), awsResponse.getResponseMetadata()); if (requestLog.isDebugEnabled()) { requestLog.debug( "Received successful response: " + apacheHttpResponse.getStatusLine().getStatusCode() + ", AWS Request ID: " + awsResponse.getRequestId()); } awsRequestMetrics.addProperty(Field.AWSRequestID.name(), awsResponse.getRequestId()); return awsResponse.getResult(); } catch (CRC32MismatchException e) { throw e; } catch (Exception e) { String errorMessage = "Unable to unmarshall response (" + e.getMessage() + ")"; throw new AmazonClientException(errorMessage, e); } }
/** * Deletes a specified stack. Once the call completes successfully, stack deletion starts. Deleted * stacks do not show up in the DescribeStacks API if the deletion has been completed * successfully. * * @param deleteStackRequest Container for the necessary parameters to execute the DeleteStack * service method on AmazonCloudFormation. * @throws AmazonClientException If any internal errors are encountered inside the client while * attempting to make the request or handle the response. For example if a network connection * is not available. * @throws AmazonServiceException If an error response is returned by AmazonCloudFormation * indicating either a problem with the data in the request, or a server side issue. */ public void deleteStack(DeleteStackRequest deleteStackRequest) { ExecutionContext executionContext = createExecutionContext(deleteStackRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); Request<DeleteStackRequest> request = null; awsRequestMetrics.startEvent(Field.ClientExecuteTime); try { request = new DeleteStackRequestMarshaller().marshall(deleteStackRequest); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); invoke(request, null, executionContext); } finally { endClientExecution(awsRequestMetrics, request, null); } }
/** * Creates a stack as specified in the template. After the call completes successfully, the stack * creation starts. You can check the status of the stack via the DescribeStacks API. * * @param createStackRequest Container for the necessary parameters to execute the CreateStack * service method on AmazonCloudFormation. * @return The response from the CreateStack service method, as returned by AmazonCloudFormation. * @throws AlreadyExistsException * @throws LimitExceededException * @throws InsufficientCapabilitiesException * @throws AmazonClientException If any internal errors are encountered inside the client while * attempting to make the request or handle the response. For example if a network connection * is not available. * @throws AmazonServiceException If an error response is returned by AmazonCloudFormation * indicating either a problem with the data in the request, or a server side issue. */ public CreateStackResult createStack(CreateStackRequest createStackRequest) { ExecutionContext executionContext = createExecutionContext(createStackRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); Request<CreateStackRequest> request = null; Response<CreateStackResult> response = null; awsRequestMetrics.startEvent(Field.ClientExecuteTime); try { request = new CreateStackRequestMarshaller().marshall(createStackRequest); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); response = invoke(request, new CreateStackResultStaxUnmarshaller(), executionContext); return response.getAwsResponse(); } finally { endClientExecution(awsRequestMetrics, request, response); } }
/** * Returns a set of temporary security credentials for users who have been authenticated in a * mobile or web application with a web identity provider, such as Amazon Cognito, Login with * Amazon, Facebook, Google, or any OpenID Connect-compatible identity provider. * * <p><b>NOTE:</b> For mobile applications, we recommend that you use Amazon Cognito. You can use * Amazon Cognito with the AWS SDK for iOS and the AWS SDK for Android to uniquely identify a user * and supply the user with a consistent identity throughout the lifetime of an application. To * learn more about Amazon Cognito, see Amazon Cognito Overview in the AWS SDK for Android * Developer Guide guide and Amazon Cognito Overview in the AWS SDK for iOS Developer Guide. * * <p>Calling <code>AssumeRoleWithWebIdentity</code> does not require the use of AWS security * credentials. Therefore, you can distribute an application (for example, on mobile devices) that * requests temporary security credentials without including long-term AWS credentials in the * application, and without deploying server-based proxy services that use long-term AWS * credentials. Instead, the identity of the caller is validated by using a token from the web * identity provider. * * <p>The temporary security credentials returned by this API consist of an access key ID, a * secret access key, and a security token. Applications can use these temporary security * credentials to sign calls to AWS service APIs. The credentials are valid for the duration that * you specified when calling <code>AssumeRoleWithWebIdentity</code> , which can be from 900 * seconds (15 minutes) to 3600 seconds (1 hour). By default, the temporary security credentials * are valid for 1 hour. * * <p>Optionally, you can pass an IAM access policy to this operation. If you choose not to pass a * policy, the temporary security credentials that are returned by the operation have the * permissions that are defined in the access policy of the role that is being assumed. If you * pass a policy to this operation, the temporary security credentials that are returned by the * operation have the permissions that are allowed by both the access policy of the role that is * being assumed, <i> and </i> the policy that you pass. This gives you a way to further restrict * the permissions for the resulting temporary security credentials. You cannot use the passed * policy to grant permissions that are in excess of those allowed by the access policy of the * role that is being assumed. For more information, see <a * href="http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_assumerole.html"> * Permissions for AssumeRole, AssumeRoleWithSAML, and AssumeRoleWithWebIdentity </a> in the * <i>Using IAM</i> . * * <p>Before your application can call <code>AssumeRoleWithWebIdentity</code> , you must have an * identity token from a supported identity provider and create a role that the application can * assume. The role that your application assumes must trust the identity provider that is * associated with the identity token. In other words, the identity provider must be specified in * the role's trust policy. * * <p>For more information about how to use web identity federation and the <code> * AssumeRoleWithWebIdentity</code> API, see the following resources: * * <ul> * <li><a href="http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual"> * Using Web Identity Federation APIs for Mobile Apps </a> and <a * href="http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity"> * Federation Through a Web-based Identity Provider </a> . * <li><a href="https://web-identity-federation-playground.s3.amazonaws.com/index.html">Web * Identity Federation Playground </a> . This interactive website lets you walk through the * process of authenticating via Login with Amazon, Facebook, or Google, getting temporary * security credentials, and then using those credentials to make a request to AWS. * <li><a href="http://aws.amazon.com/sdkforios/">AWS SDK for iOS </a> and <a * href="http://aws.amazon.com/sdkforandroid/">AWS SDK for Android </a> . These toolkits * contain sample apps that show how to invoke the identity providers, and then how to use * the information from these providers to get and use temporary security credentials. * <li><a href="http://aws.amazon.com/articles/4617974389850313">Web Identity Federation with * Mobile Applications </a> . This article discusses web identity federation and shows an * example of how to use web identity federation to get access to content in Amazon S3. * </ul> * * @param assumeRoleWithWebIdentityRequest Container for the necessary parameters to execute the * AssumeRoleWithWebIdentity service method on AWSSecurityTokenService. * @return The response from the AssumeRoleWithWebIdentity service method, as returned by * AWSSecurityTokenService. * @throws PackedPolicyTooLargeException * @throws IDPRejectedClaimException * @throws MalformedPolicyDocumentException * @throws InvalidIdentityTokenException * @throws ExpiredTokenException * @throws IDPCommunicationErrorException * @throws AmazonClientException If any internal errors are encountered inside the client while * attempting to make the request or handle the response. For example if a network connection * is not available. * @throws AmazonServiceException If an error response is returned by AWSSecurityTokenService * indicating either a problem with the data in the request, or a server side issue. */ public AssumeRoleWithWebIdentityResult assumeRoleWithWebIdentity( AssumeRoleWithWebIdentityRequest assumeRoleWithWebIdentityRequest) { ExecutionContext executionContext = createExecutionContext(assumeRoleWithWebIdentityRequest); AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); Request<AssumeRoleWithWebIdentityRequest> request = null; Response<AssumeRoleWithWebIdentityResult> response = null; awsRequestMetrics.startEvent(Field.ClientExecuteTime); try { request = new AssumeRoleWithWebIdentityRequestMarshaller() .marshall(assumeRoleWithWebIdentityRequest); // Binds the request metrics to the current request. request.setAWSRequestMetrics(awsRequestMetrics); response = invoke(request, new AssumeRoleWithWebIdentityResultStaxUnmarshaller(), executionContext); return response.getAwsResponse(); } finally { endClientExecution(awsRequestMetrics, request, response); } }
/** * Executes the request and returns the result. * * @param request The AmazonWebServices request to send to the remote server * @param responseHandler A response handler to accept a successful response from the remote * server * @param errorResponseHandler A response handler to accept an unsuccessful response from the * remote server * @param executionContext Additional information about the context of this web service call */ public <T> Response<T> execute( Request<?> request, HttpResponseHandler<AmazonWebServiceResponse<T>> responseHandler, HttpResponseHandler<AmazonServiceException> errorResponseHandler, ExecutionContext executionContext) throws AmazonClientException, AmazonServiceException { if (executionContext == null) throw new AmazonClientException( "Internal SDK Error: No execution context parameter specified."); List<RequestHandler2> requestHandler2s = requestHandler2s(request, executionContext); final AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); Response<T> response = null; try { response = executeHelper(request, responseHandler, errorResponseHandler, executionContext); TimingInfo timingInfo = awsRequestMetrics.getTimingInfo().endTiming(); afterResponse(request, requestHandler2s, response, timingInfo); return response; } catch (AmazonClientException e) { afterError(request, response, requestHandler2s, e); throw e; } }
/** Handles an unexpected failure, returning the Throwable instance as given. */ private <T extends Throwable> T handleUnexpectedFailure( T t, AWSRequestMetrics awsRequestMetrics) { awsRequestMetrics.incrementCounter(Field.Exception); awsRequestMetrics.addProperty(Field.Exception, t); return t; }
/** * Internal method to execute the HTTP method given. * * @see AmazonHttpClient#execute(Request, HttpResponseHandler, HttpResponseHandler) * @see AmazonHttpClient#execute(Request, HttpResponseHandler, HttpResponseHandler, * ExecutionContext) */ private <T> Response<T> executeHelper( Request<?> request, HttpResponseHandler<AmazonWebServiceResponse<T>> responseHandler, HttpResponseHandler<AmazonServiceException> errorResponseHandler, ExecutionContext executionContext) throws AmazonClientException, AmazonServiceException { /* * Depending on which response handler we end up choosing to handle the * HTTP response, it might require us to leave the underlying HTTP * connection open, depending on whether or not it reads the complete * HTTP response stream from the HTTP connection, or if delays reading * any of the content until after a response is returned to the caller. */ boolean leaveHttpConnectionOpen = false; AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); /* add the service endpoint to the logs. You can infer service name from service endpoint */ awsRequestMetrics.addProperty(Field.ServiceName, request.getServiceName()); awsRequestMetrics.addProperty(Field.ServiceEndpoint, request.getEndpoint()); // Apply whatever request options we know how to handle, such as user-agent. setUserAgent(request); int requestCount = 0; URI redirectedURI = null; HttpEntity entity = null; AmazonClientException retriedException = null; // Make a copy of the original request params and headers so that we can // permute it in this loop and start over with the original every time. Map<String, String> originalParameters = new LinkedHashMap<String, String>(); originalParameters.putAll(request.getParameters()); Map<String, String> originalHeaders = new HashMap<String, String>(); originalHeaders.putAll(request.getHeaders()); final AWSCredentials credentials = executionContext.getCredentials(); Signer signer = null; while (true) { ++requestCount; awsRequestMetrics.setCounter(Field.RequestCount, requestCount); if (requestCount > 1) { // retry request.setParameters(originalParameters); request.setHeaders(originalHeaders); } HttpRequestBase httpRequest = null; org.apache.http.HttpResponse apacheResponse = null; try { // Sign the request if a signer was provided if (signer == null) signer = executionContext.getSignerByURI(request.getEndpoint()); if (signer != null && credentials != null) { awsRequestMetrics.startEvent(Field.RequestSigningTime); try { signer.sign(request, credentials); } finally { awsRequestMetrics.endEvent(Field.RequestSigningTime); } } if (requestLog.isDebugEnabled()) { requestLog.debug("Sending Request: " + request.toString()); } httpRequest = httpRequestFactory.createHttpRequest(request, config, executionContext); if (httpRequest instanceof HttpEntityEnclosingRequest) { entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity(); } if (redirectedURI != null) { httpRequest.setURI(redirectedURI); } if (requestCount > 1) { // retry awsRequestMetrics.startEvent(Field.RetryPauseTime); try { pauseBeforeNextRetry( request.getOriginalRequest(), retriedException, requestCount, config.getRetryPolicy()); } finally { awsRequestMetrics.endEvent(Field.RetryPauseTime); } } if (entity != null) { InputStream content = entity.getContent(); if (requestCount > 1) { // retry if (content.markSupported()) { content.reset(); content.mark(-1); } } else { if (content.markSupported()) { content.mark(-1); } } } captureConnectionPoolMetrics(httpClient.getConnectionManager(), awsRequestMetrics); HttpContext httpContext = new BasicHttpContext(); httpContext.setAttribute(AWSRequestMetrics.class.getSimpleName(), awsRequestMetrics); retriedException = null; awsRequestMetrics.startEvent(Field.HttpRequestTime); try { apacheResponse = httpClient.execute(httpRequest, httpContext); } finally { awsRequestMetrics.endEvent(Field.HttpRequestTime); } if (isRequestSuccessful(apacheResponse)) { awsRequestMetrics.addProperty( Field.StatusCode, apacheResponse.getStatusLine().getStatusCode()); /* * If we get back any 2xx status code, then we know we should * treat the service call as successful. */ leaveHttpConnectionOpen = responseHandler.needsConnectionLeftOpen(); HttpResponse httpResponse = createResponse(httpRequest, request, apacheResponse); T response = handleResponse( request, responseHandler, httpRequest, httpResponse, apacheResponse, executionContext); return new Response<T>(response, httpResponse); } else if (isTemporaryRedirect(apacheResponse)) { /* * S3 sends 307 Temporary Redirects if you try to delete an * EU bucket from the US endpoint. If we get a 307, we'll * point the HTTP method to the redirected location, and let * the next retry deliver the request to the right location. */ Header[] locationHeaders = apacheResponse.getHeaders("location"); String redirectedLocation = locationHeaders[0].getValue(); log.debug("Redirecting to: " + redirectedLocation); redirectedURI = URI.create(redirectedLocation); httpRequest.setURI(redirectedURI); awsRequestMetrics.addProperty( Field.StatusCode, apacheResponse.getStatusLine().getStatusCode()); awsRequestMetrics.addProperty(Field.RedirectLocation, redirectedLocation); awsRequestMetrics.addProperty(Field.AWSRequestID, null); } else { leaveHttpConnectionOpen = errorResponseHandler.needsConnectionLeftOpen(); AmazonServiceException ase = handleErrorResponse(request, errorResponseHandler, httpRequest, apacheResponse); awsRequestMetrics.addProperty(Field.AWSRequestID, ase.getRequestId()); awsRequestMetrics.addProperty(Field.AWSErrorCode, ase.getErrorCode()); awsRequestMetrics.addProperty(Field.StatusCode, ase.getStatusCode()); if (!shouldRetry( request.getOriginalRequest(), httpRequest, ase, requestCount, config.getRetryPolicy())) { throw ase; } // Cache the retryable exception retriedException = ase; /* * Checking for clock skew error again because we don't want to set the * global time offset for every service exception. */ if (RetryUtils.isClockSkewError(ase)) { int timeOffset = parseClockSkewOffset(apacheResponse, ase); SDKGlobalConfiguration.setGlobalTimeOffset(timeOffset); } resetRequestAfterError(request, ase); } } catch (IOException ioe) { if (log.isInfoEnabled()) { log.info("Unable to execute HTTP request: " + ioe.getMessage(), ioe); } awsRequestMetrics.incrementCounter(Field.Exception); awsRequestMetrics.addProperty(Field.Exception, ioe); awsRequestMetrics.addProperty(Field.AWSRequestID, null); AmazonClientException ace = new AmazonClientException("Unable to execute HTTP request: " + ioe.getMessage(), ioe); if (!shouldRetry( request.getOriginalRequest(), httpRequest, ace, requestCount, config.getRetryPolicy())) { throw ace; } // Cache the retryable exception retriedException = ace; resetRequestAfterError(request, ioe); } catch (RuntimeException e) { throw handleUnexpectedFailure(e, awsRequestMetrics); } catch (Error e) { throw handleUnexpectedFailure(e, awsRequestMetrics); } finally { /* * Some response handlers need to manually manage the HTTP * connection and will take care of releasing the connection on * their own, but if this response handler doesn't need the * connection left open, we go ahead and release the it to free * up resources. */ if (!leaveHttpConnectionOpen) { try { if (apacheResponse != null && apacheResponse.getEntity() != null && apacheResponse.getEntity().getContent() != null) { apacheResponse.getEntity().getContent().close(); } } catch (IOException e) { log.warn("Cannot close the response content.", e); } } } } /* end while (true) */ }
/** * Internal method to execute the HTTP method given. * * @see AmazonHttpClient#execute(Request, HttpResponseHandler, HttpResponseHandler) * @see AmazonHttpClient#execute(Request, HttpResponseHandler, HttpResponseHandler, * ExecutionContext) */ private <T extends Object> T executeHelper( Request<?> request, HttpResponseHandler<AmazonWebServiceResponse<T>> responseHandler, HttpResponseHandler<AmazonServiceException> errorResponseHandler, ExecutionContext executionContext) throws AmazonClientException, AmazonServiceException { /* * Depending on which response handler we end up choosing to handle the * HTTP response, it might require us to leave the underlying HTTP * connection open, depending on whether or not it reads the complete * HTTP response stream from the HTTP connection, or if delays reading * any of the content until after a response is returned to the caller. */ boolean leaveHttpConnectionOpen = false; AWSRequestMetrics awsRequestMetrics = executionContext.getAwsRequestMetrics(); /* add the service endpoint to the logs. You can infer service name from service endpoint */ awsRequestMetrics.addProperty(Field.ServiceName.name(), request.getServiceName()); awsRequestMetrics.addProperty(Field.ServiceEndpoint.name(), request.getEndpoint()); // Apply whatever request options we know how to handle, such as user-agent. applyRequestData(request); int retryCount = 0; URI redirectedURI = null; HttpEntity entity = null; AmazonServiceException exception = null; // Make a copy of the original request params and headers so that we can // permute it in this loop and start over with the original every time. Map<String, String> originalParameters = new HashMap<String, String>(); originalParameters.putAll(request.getParameters()); Map<String, String> originalHeaders = new HashMap<String, String>(); originalHeaders.putAll(request.getHeaders()); while (true) { awsRequestMetrics.setCounter(Field.AttemptCount.name(), retryCount + 1); if (retryCount > 0) { request.setParameters(originalParameters); request.setHeaders(originalHeaders); } HttpRequestBase httpRequest = null; org.apache.http.HttpResponse response = null; try { // Sign the request if a signer was provided if (executionContext.getSigner() != null && executionContext.getCredentials() != null) { awsRequestMetrics.startEvent(Field.RequestSigningTime.name()); executionContext.getSigner().sign(request, executionContext.getCredentials()); awsRequestMetrics.endEvent(Field.RequestSigningTime.name()); } if (requestLog.isDebugEnabled()) { requestLog.debug("Sending Request: " + request.toString()); } httpRequest = httpRequestFactory.createHttpRequest(request, config, entity, executionContext); if (httpRequest instanceof HttpEntityEnclosingRequest) { entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity(); } if (redirectedURI != null) { httpRequest.setURI(redirectedURI); } if (retryCount > 0) { awsRequestMetrics.startEvent(Field.RetryPauseTime.name()); pauseExponentially(retryCount, exception, executionContext.getCustomBackoffStrategy()); awsRequestMetrics.endEvent(Field.RetryPauseTime.name()); } if (entity != null) { InputStream content = entity.getContent(); if (retryCount > 0) { if (content.markSupported()) { content.reset(); content.mark(-1); } } else { if (content.markSupported()) { content.mark(-1); } } } exception = null; awsRequestMetrics.startEvent(Field.HttpRequestTime.name()); response = httpClient.execute(httpRequest); awsRequestMetrics.endEvent(Field.HttpRequestTime.name()); if (isRequestSuccessful(response)) { awsRequestMetrics.addProperty( Field.StatusCode.name(), response.getStatusLine().getStatusCode()); /* * If we get back any 2xx status code, then we know we should * treat the service call as successful. */ leaveHttpConnectionOpen = responseHandler.needsConnectionLeftOpen(); return handleResponse(request, responseHandler, httpRequest, response, executionContext); } else if (isTemporaryRedirect(response)) { /* * S3 sends 307 Temporary Redirects if you try to delete an * EU bucket from the US endpoint. If we get a 307, we'll * point the HTTP method to the redirected location, and let * the next retry deliver the request to the right location. */ Header[] locationHeaders = response.getHeaders("location"); String redirectedLocation = locationHeaders[0].getValue(); log.debug("Redirecting to: " + redirectedLocation); redirectedURI = URI.create(redirectedLocation); httpRequest.setURI(redirectedURI); awsRequestMetrics.addProperty( Field.StatusCode.name(), response.getStatusLine().getStatusCode()); awsRequestMetrics.addProperty(Field.RedirectLocation.name(), redirectedLocation); awsRequestMetrics.addProperty(Field.AWSRequestID.name(), null); } else { leaveHttpConnectionOpen = errorResponseHandler.needsConnectionLeftOpen(); exception = handleErrorResponse(request, errorResponseHandler, httpRequest, response); awsRequestMetrics.addProperty(Field.AWSRequestID.name(), exception.getRequestId()); awsRequestMetrics.addProperty(Field.AWSErrorCode.name(), exception.getErrorCode()); awsRequestMetrics.addProperty(Field.StatusCode.name(), exception.getStatusCode()); if (!shouldRetry(httpRequest, exception, retryCount)) { throw exception; } resetRequestAfterError(request, exception); } } catch (IOException ioe) { log.info("Unable to execute HTTP request: " + ioe.getMessage(), ioe); awsRequestMetrics.addProperty(Field.Exception.name(), ioe.toString()); awsRequestMetrics.addProperty(Field.AWSRequestID.name(), null); if (!shouldRetry(httpRequest, ioe, retryCount)) { throw new AmazonClientException( "Unable to execute HTTP request: " + ioe.getMessage(), ioe); } resetRequestAfterError(request, ioe); } finally { retryCount++; /* * Some response handlers need to manually manage the HTTP * connection and will take care of releasing the connection on * their own, but if this response handler doesn't need the * connection left open, we go ahead and release the it to free * up resources. */ if (!leaveHttpConnectionOpen) { try { response.getEntity().getContent().close(); } catch (Throwable t) { } } } } /* end while (true) */ }