/**
   * 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);
    }
  }
  /**
   * 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);
    }
  }
 /**
  * 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);
   }
 }
  @Override
  public void afterResponse(com.amazonaws.Request<?> request, com.amazonaws.Response<?> response) {
    try {
      if (response == null) {
        return;
      }

      Map<String, String> headers = response.getHttpResponse().getHeaders();
      String responseTimeStr = headers.get(REQUESTTIME_HEADER);
      long responseTime = startTime - System.currentTimeMillis();
      if (responseTimeStr != null && responseTimeStr.trim().length() > 0) {
        try {
          responseTime = Long.parseLong(responseTimeStr.trim());
        } catch (NumberFormatException e) {
        }
      }

      double responseDouble = -1;
      try {
        responseDouble = Double.valueOf(Long.toString(responseTime));
      } catch (NumberFormatException numberFormatException) {
        Log.e(TAG, "Couldn't convert response time to double format", numberFormatException);
      }
      String requestAttemptsStr = headers.get(REQUESTATTEMPTS_HEADER);
      double requestAttempts = 0;
      if (requestAttemptsStr != null && requestAttemptsStr.trim().length() > 0) {
        try {
          requestAttempts = Double.parseDouble(requestAttemptsStr.trim());
        } catch (NumberFormatException e) {
        }
      }

      String serverInfo = headers.get(SERVERINFO_HEADER);
      if (!StringUtil.isNullOrEmpty(responseTimeStr)) {
        if (eventClient == null) {
          return;
        }
        AnalyticsEvent recordEvent =
            eventClient
                .createEvent("_httpRequestTiming")
                .withAttribute("url", request.getEndpoint().toURL().toString())
                .withAttribute(
                    "responseCode", Integer.toString(response.getHttpResponse().getStatusCode()))
                .withAttribute("timeZone", getTimeZone())
                .withMetric("attempts", requestAttempts)
                .withMetric("totalTime", responseDouble)
                .withMetric("requestSize", (double) contentLength);

        String connectionType = "UNKNOWN";
        if (connectivity != null) {
          if (connectivity.hasWifi()) {
            connectionType = "WIFI";
          } else if (connectivity.hasWAN()) {
            connectionType = "WAN";
          }
        }

        recordEvent.withAttribute("network", connectionType);

        if (serverInfo != null) {
          recordEvent.withAttribute("serverInfo", serverInfo);
        }

        eventClient.recordEvent(recordEvent);
      }
    } catch (Exception e) {
      Log.e(TAG, "Unable to record _RequestTime event", e);
    }
  }