package com.google.auth;

import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;

/**
 * Represents an abstract authorized identity instance.
 */
public abstract class Credentials {

  /**
   * A constant string name describing the authentication technology.
   *
   * <p>E.g. “OAuth2”, “SSL”. For use by the transport layer to determine whether it supports the
   * type of authentication in the case where {@link Credentials#hasRequestMetadataOnly} is false.
   * Also serves as a debugging helper.
   */
  public abstract String getAuthenticationType();

  /**
   * Get the current request metadata, refreshing tokens if required.
   *
   * <p>This should be called by the transport layer on each request, and the data should be
   * populated in headers or other context. The operation can block and fail to complete and may do
   * things such as refreshing access tokens.
   *
   * <p>The convention for handling binary data is for the key in the returned map to end with
   * {@code "-bin"} and for the corresponding values to be base64 encoded.
   *
   * @throws IOException if there was an error getting up-to-date access.
   */
  public Map<String, List<String>> getRequestMetadata() throws IOException {
    return getRequestMetadata(null);
  }

  /**
   * Get the current request metadata, refreshing tokens if required.
   *
   * <p>This should be called by the transport layer on each request, and the data should be
   * populated in headers or other context. The operation can block and fail to complete and may do
   * things such as refreshing access tokens.
   *
   * <p>The convention for handling binary data is for the key in the returned map to end with
   * {@code "-bin"} and for the corresponding values to be base64 encoded.
   *
   * @param uri URI of the entry point for the request.
   * @throws IOException if there was an error getting up-to-date access.
   */
  public abstract Map<String, List<String>> getRequestMetadata(URI uri) throws IOException;

  /**
   * Whether the credentials have metadata entries that should be added to each request.
   *
   * <p>This should be called by the transport layer to see if
   * {@link Credentials#getRequestMetadata} should be used for each request.
   */
  public abstract boolean hasRequestMetadata();

  /**
   * Indicates whether or not the Auth mechanism works purely by including request metadata.
   *
   * <p>This is meant for the transport layer. If this is true a transport does not need to take
   * actions other than including the request metadata. If this is false, a transport must
   * specifically know about the authentication technology to support it, and should fail to
   * accept the credentials otherwise.
   */
  public abstract boolean hasRequestMetadataOnly();

  /**
   * Refresh the authorization data, discarding any cached state.
   *
   * <p> For use by the transport to allow retry after getting an error indicating there may be
   * invalid tokens or other cached state.
   *
   * @throws IOException if there was an error getting up-to-date access.
   */
  public abstract void refresh() throws IOException;
}

@@ -112,16 +112,54 @@
 til.Map;
+%0Aimport java.util.concurrent.Executor;
 %0A%0A/**%0A *
@@ -1327,16 +1327,1126 @@
 );%0A  %7D%0A%0A
+  /**%0A   * Get the current request metadata without blocking.%0A   *%0A   * %3Cp%3EThis should be called by the transport layer on each request, and the data should be%0A   * populated in headers or other context. The implementation can either call the callback inline,%0A   * or from the given executor asynchronously. Either way it should %3Cstrong%3Enever block%3C/strong%3E in%0A   * this method.%0A   *%0A   * %3Cp%3EThe default implementation will just call %7B@link #getRequestMetadata(URI)%7D then the callback%0A   * from the given executor.%0A   *%0A   * %3Cp%3EThe convention for handling binary data is for the key in the returned map to end with%0A   * %7B@code %22-bin%22%7D and for the corresponding values to be base64 encoded.%0A   */%0A  public void getRequestMetadata(final URI uri, Executor executor, final Callback callback) %7B%0A    executor.execute(new Runnable() %7B%0A        @Override%0A        public void run() %7B%0A          try %7B%0A            Map%3CString, List%3CString%3E%3E result = getRequestMetadata(uri);%0A            callback.onSuccess(result);%0A          %7D catch (IOException e) %7B%0A            callback.onFailure(e);%0A          %7D%0A        %7D%0A      %7D);%0A  %7D%0A%0A
   /**%0A  
@@ -4237,32 +4237,32 @@
 e access.%0A   */%0A
-
   public abstrac
@@ -4297,11 +4297,450 @@
 ception;
+%0A%0A  /**%0A   * The callback that receives the result of the asynchronous %7B@link #getRequestMetadata(URI,%0A   * Executor, Callback)%7D. Exactly one method should be called.%0A   */%0A  public interface Callback %7B%0A    /**%0A     * Called when metadata is successfully produced.%0A     */%0A    void onSuccess(Map%3CString, List%3CString%3E%3E metadata);%0A%0A    /**%0A     * Called when metadata generation failed.%0A     */%0A    void onFailure(IOException exception);%0A  %7D
 %0A%7D%0A

Add asynchronous getRequestMetadata.