// Path: credentials/java/com/google/auth/ServiceAccountSigner.java
// class SigningException extends RuntimeException {
// 
//   private static final long serialVersionUID = -6503954300538947223L;
// 
//   public SigningException(String message, Exception cause) {
//     super(message, cause);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this) {
//       return true;
//     }
//     if (!(obj instanceof SigningException)) {
//       return false;
//     }
//     SigningException other = (SigningException) obj;
//     return Objects.equals(getCause(), other.getCause())
//         && Objects.equals(getMessage(), other.getMessage());
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hash(getMessage(), getCause());
//   }
// }


import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.auth.ServiceAccountSigner.SigningException;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.io.BaseEncoding;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
    Map<String, String> headers = new HashMap<>();
    headers.put("host", uri.getHost());

    // Only add the date if it hasn't been specified through the "date" header.
    if (!additionalHeaders.containsKey("date")) {
      headers.put("x-amz-date", defaultDate);
    }

    if (awsSecurityCredentials.getToken() != null && !awsSecurityCredentials.getToken().isEmpty()) {
      headers.put("x-amz-security-token", awsSecurityCredentials.getToken());
    }

    // Add all additional headers.
    for (String key : additionalHeaders.keySet()) {
      // Header keys need to be lowercase.
      headers.put(key.toLowerCase(Locale.US), additionalHeaders.get(key));
    }
    return headers;
  }

  private static byte[] sign(byte[] key, byte[] value) {
    try {
      String algorithm = "HmacSHA256";
      Mac mac = Mac.getInstance(algorithm);
      mac.init(new SecretKeySpec(key, algorithm));
      return mac.doFinal(value);
    } catch (NoSuchAlgorithmException e) {
      // Will not occur as HmacSHA256 is supported. We may allow other algorithms in the future.
      throw new RuntimeException("HmacSHA256 must be supported by the JVM.", e);
    } catch (InvalidKeyException e) {
// Path: credentials/java/com/google/auth/ServiceAccountSigner.java
// class SigningException extends RuntimeException {
// 
//   private static final long serialVersionUID = -6503954300538947223L;
// 
//   public SigningException(String message, Exception cause) {
//     super(message, cause);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj == this) {
//       return true;
//     }
//     if (!(obj instanceof SigningException)) {
//       return false;
//     }
//     SigningException other = (SigningException) obj;
//     return Objects.equals(getCause(), other.getCause())
//         && Objects.equals(getMessage(), other.getMessage());
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hash(getMessage(), getCause());
//   }
// }


// Path: oauth2_http/java/com/google/auth/oauth2/AwsRequestSigner.java
import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.auth.ServiceAccountSigner.SigningException;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.io.BaseEncoding;
import java.net.URI;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

    Map<String, String> headers = new HashMap<>();
    headers.put("host", uri.getHost());

    // Only add the date if it hasn't been specified through the "date" header.
    if (!additionalHeaders.containsKey("date")) {
      headers.put("x-amz-date", defaultDate);
    }

    if (awsSecurityCredentials.getToken() != null && !awsSecurityCredentials.getToken().isEmpty()) {
      headers.put("x-amz-security-token", awsSecurityCredentials.getToken());
    }

    // Add all additional headers.
    for (String key : additionalHeaders.keySet()) {
      // Header keys need to be lowercase.
      headers.put(key.toLowerCase(Locale.US), additionalHeaders.get(key));
    }
    return headers;
  }

  private static byte[] sign(byte[] key, byte[] value) {
    try {
      String algorithm = "HmacSHA256";
      Mac mac = Mac.getInstance(algorithm);
      mac.init(new SecretKeySpec(key, algorithm));
      return mac.doFinal(value);
    } catch (NoSuchAlgorithmException e) {
      // Will not occur as HmacSHA256 is supported. We may allow other algorithms in the future.
      throw new RuntimeException("HmacSHA256 must be supported by the JVM.", e);
    } catch (InvalidKeyException e) {
      throw new SigningException("Invalid key used when calculating the AWS V4 Signature", e);