All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kohsuke.github.GitHubBuilder Maven / Gradle / Ivy

There is a newer version: 2.0.0-alpha-2
Show newest version
package org.kohsuke.github;

import org.apache.commons.io.IOUtils;
import org.kohsuke.github.authorization.AuthorizationProvider;
import org.kohsuke.github.authorization.ImmutableAuthorizationProvider;
import org.kohsuke.github.connector.GitHubConnector;
import org.kohsuke.github.connector.GitHubConnectorResponse;
import org.kohsuke.github.extras.ImpatientHttpConnector;
import org.kohsuke.github.internal.GitHubConnectorHttpConnectorAdapter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.Properties;

import javax.annotation.Nonnull;

// TODO: Auto-generated Javadoc
/**
 * Configures connection details and produces {@link GitHub}.
 *
 * @since 1.59
 */
public class GitHubBuilder implements Cloneable {

    /** The home directory. */
    // for testing
    static File HOME_DIRECTORY = null;

    // default scoped so unit tests can read them.
    /** The endpoint. */
    /* private */ String endpoint = GitHubClient.GITHUB_URL;

    private GitHubConnector connector;

    private GitHubRateLimitHandler rateLimitHandler = RateLimitHandler.WAIT;
    private GitHubAbuseLimitHandler abuseLimitHandler = AbuseLimitHandler.WAIT;
    private GitHubRateLimitChecker rateLimitChecker = new GitHubRateLimitChecker();

    /** The authorization provider. */
    /* private */ AuthorizationProvider authorizationProvider = AuthorizationProvider.ANONYMOUS;

    /**
     * Instantiates a new Git hub builder.
     */
    public GitHubBuilder() {
    }

    /**
     * First check if the credentials are configured in the environment. We use environment first because users are not
     * likely to give required (full) permissions to their default key.
     *
     * If no user is specified it means there is no configuration present, so try using the ~/.github properties file.
     **
     * If there is still no user it means there are no credentials defined and throw an IOException.
     *
     * @return the configured Builder from credentials defined on the system or in the environment. Otherwise returns
     *         null.
     *
     * @throws IOException
     *             If there are no credentials defined in the ~/.github properties file or the process environment.
     */
    static GitHubBuilder fromCredentials() throws IOException {
        Exception cause = null;
        GitHubBuilder builder = null;

        builder = fromEnvironment();

        if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS)
            return builder;

        try {
            builder = fromPropertyFile();

            if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS)
                return builder;
        } catch (FileNotFoundException e) {
            // fall through
            cause = e;
        }
        throw (IOException) new IOException("Failed to resolve credentials from ~/.github or the environment.")
                .initCause(cause);
    }

    /**
     * From environment git hub builder.
     *
     * @param loginVariableName
     *            the login variable name
     * @param passwordVariableName
     *            the password variable name
     * @param oauthVariableName
     *            the oauth variable name
     * @return the git hub builder
     * @throws IOException
     *             the io exception
     * @deprecated Use {@link #fromEnvironment()} to pick up standard set of environment variables, so that different
     *             clients of this library will all recognize one consistent set of coordinates.
     */
    @Deprecated
    public static GitHubBuilder fromEnvironment(String loginVariableName,
            String passwordVariableName,
            String oauthVariableName) throws IOException {
        return fromEnvironment(loginVariableName, passwordVariableName, oauthVariableName, "");
    }

    private static void loadIfSet(String envName, Properties p, String propName) {
        String v = System.getenv(envName);
        if (v != null)
            p.put(propName, v);
    }

    /**
     * From environment git hub builder.
     *
     * @param loginVariableName
     *            the login variable name
     * @param passwordVariableName
     *            the password variable name
     * @param oauthVariableName
     *            the oauth variable name
     * @param endpointVariableName
     *            the endpoint variable name
     * @return the git hub builder
     * @throws IOException
     *             the io exception
     * @deprecated Use {@link #fromEnvironment()} to pick up standard set of environment variables, so that different
     *             clients of this library will all recognize one consistent set of coordinates.
     */
    @Deprecated
    public static GitHubBuilder fromEnvironment(String loginVariableName,
            String passwordVariableName,
            String oauthVariableName,
            String endpointVariableName) throws IOException {
        Properties env = new Properties();
        loadIfSet(loginVariableName, env, "login");
        loadIfSet(passwordVariableName, env, "password");
        loadIfSet(oauthVariableName, env, "oauth");
        loadIfSet(endpointVariableName, env, "endpoint");
        return fromProperties(env);
    }

    /**
     * Creates {@link GitHubBuilder} by picking up coordinates from environment variables.
     *
     * 

* The following environment variables are recognized: * *

    *
  • GITHUB_LOGIN: username like 'kohsuke' *
  • GITHUB_PASSWORD: raw password *
  • GITHUB_OAUTH: OAuth token to login *
  • GITHUB_ENDPOINT: URL of the API endpoint *
  • GITHUB_JWT: JWT token to login *
* *

* See class javadoc for the relationship between these coordinates. * *

* For backward compatibility, the following environment variables are recognized but discouraged: login, password, * oauth * * @return the git hub builder * @throws IOException * the io exception */ public static GitHubBuilder fromEnvironment() throws IOException { Properties props = new Properties(); for (Entry e : System.getenv().entrySet()) { String name = e.getKey().toLowerCase(Locale.ENGLISH); if (name.startsWith("github_")) name = name.substring(7); props.put(name, e.getValue()); } return fromProperties(props); } /** * From property file git hub builder. * * @return the git hub builder * @throws IOException * the io exception */ public static GitHubBuilder fromPropertyFile() throws IOException { File homeDir = HOME_DIRECTORY != null ? HOME_DIRECTORY : new File(System.getProperty("user.home")); File propertyFile = new File(homeDir, ".github"); return fromPropertyFile(propertyFile.getPath()); } /** * From property file git hub builder. * * @param propertyFileName * the property file name * @return the git hub builder * @throws IOException * the io exception */ public static GitHubBuilder fromPropertyFile(String propertyFileName) throws IOException { Properties props = new Properties(); FileInputStream in = null; try { in = new FileInputStream(propertyFileName); props.load(in); } finally { IOUtils.closeQuietly(in); } return fromProperties(props); } /** * From properties git hub builder. * * @param props * the props * @return the git hub builder */ public static GitHubBuilder fromProperties(Properties props) { GitHubBuilder self = new GitHubBuilder(); String oauth = props.getProperty("oauth"); String jwt = props.getProperty("jwt"); String login = props.getProperty("login"); String password = props.getProperty("password"); if (oauth != null) { self.withOAuthToken(oauth, login); } if (jwt != null) { self.withJwtToken(jwt); } if (password != null) { self.withPassword(login, password); } self.withEndpoint(props.getProperty("endpoint", GitHubClient.GITHUB_URL)); return self; } /** * With endpoint git hub builder. * * @param endpoint * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or * "https://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For * historical reasons, this parameter still accepts the bare domain name, but that's considered * deprecated. * @return the git hub builder */ public GitHubBuilder withEndpoint(String endpoint) { this.endpoint = endpoint; return this; } /** * With password git hub builder. * * @param user * the user * @param password * the password * @return the git hub builder */ public GitHubBuilder withPassword(String user, String password) { return withAuthorizationProvider(ImmutableAuthorizationProvider.fromLoginAndPassword(user, password)); } /** * With o auth token git hub builder. * * @param oauthToken * the oauth token * @return the git hub builder */ public GitHubBuilder withOAuthToken(String oauthToken) { return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken)); } /** * With o auth token git hub builder. * * @param oauthToken * the oauth token * @param user * the user * @return the git hub builder */ public GitHubBuilder withOAuthToken(String oauthToken, String user) { return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken, user)); } /** * Configures a {@link AuthorizationProvider} for this builder * * There can be only one authorization provider per client instance. * * @param authorizationProvider * the authorization provider * @return the git hub builder * */ public GitHubBuilder withAuthorizationProvider(final AuthorizationProvider authorizationProvider) { this.authorizationProvider = authorizationProvider; return this; } /** * Configures {@link GitHubBuilder} with Installation Token generated by the GitHub Application. * * @param appInstallationToken * A string containing the GitHub App installation token * @return the configured Builder from given GitHub App installation token. * @see GHAppInstallation#createToken(java.util.Map) GHAppInstallation#createToken(java.util.Map) */ public GitHubBuilder withAppInstallationToken(String appInstallationToken) { return withAuthorizationProvider(ImmutableAuthorizationProvider.fromAppInstallationToken(appInstallationToken)); } /** * With jwt token git hub builder. * * @param jwtToken * the jwt token * @return the git hub builder */ public GitHubBuilder withJwtToken(String jwtToken) { return withAuthorizationProvider(ImmutableAuthorizationProvider.fromJwtToken(jwtToken)); } /** * With connector git hub builder. * * @param connector * the connector * @return the git hub builder */ @Deprecated public GitHubBuilder withConnector(@Nonnull HttpConnector connector) { return withConnector(GitHubConnectorHttpConnectorAdapter.adapt(connector)); } /** * With connector git hub builder. * * @param connector * the connector * @return the git hub builder */ public GitHubBuilder withConnector(GitHubConnector connector) { this.connector = connector; return this; } /** * Adds a {@link RateLimitHandler} to this {@link GitHubBuilder}. *

* GitHub allots a certain number of requests to each user or application per period of time (usually per hour). The * number of requests remaining is returned in the response header and can also be requested using * {@link GitHub#getRateLimit()}. This requests per interval is referred to as the "rate limit". *

*

* When the remaining number of requests reaches zero, the next request will return an error. If this happens, * {@link RateLimitHandler#onError(IOException, HttpURLConnection)} will be called. *

*

* NOTE: GitHub treats clients that exceed their rate limit very harshly. If possible, clients should avoid * exceeding their rate limit. Consider adding a {@link RateLimitChecker} to automatically check the rate limit for * each request and wait if needed. *

* * @param handler * the handler * @return the git hub builder * @see #withRateLimitChecker(RateLimitChecker) */ public GitHubBuilder withRateLimitHandler(RateLimitHandler handler) { return withRateLimitHandler((GitHubRateLimitHandler) handler); } /** * Adds a {@link GitHubRateLimitHandler} to this {@link GitHubBuilder}. *

* GitHub allots a certain number of requests to each user or application per period of time (usually per hour). The * number of requests remaining is returned in the response header and can also be requested using * {@link GitHub#getRateLimit()}. This requests per interval is referred to as the "rate limit". *

*

* When the remaining number of requests reaches zero, the next request will return an error. If this happens, * {@link GitHubRateLimitHandler#onError(GitHubConnectorResponse)} will be called. *

*

* NOTE: GitHub treats clients that exceed their rate limit very harshly. If possible, clients should avoid * exceeding their rate limit. Consider adding a {@link RateLimitChecker} to automatically check the rate limit for * each request and wait if needed. *

* * @param handler * the handler * @return the git hub builder * @see #withRateLimitChecker(RateLimitChecker) */ public GitHubBuilder withRateLimitHandler(GitHubRateLimitHandler handler) { this.rateLimitHandler = handler; return this; } /** * Adds a {@link AbuseLimitHandler} to this {@link GitHubBuilder}. *

* When a client sends too many requests in a short time span, GitHub may return an error and set a header telling * the client to not make any more request for some period of time. If this happens, * {@link AbuseLimitHandler#onError(IOException, HttpURLConnection)} will be called. *

* * @param handler * the handler * @return the git hub builder */ @Deprecated public GitHubBuilder withAbuseLimitHandler(AbuseLimitHandler handler) { return withAbuseLimitHandler((GitHubAbuseLimitHandler) handler); } /** * Adds a {@link GitHubAbuseLimitHandler} to this {@link GitHubBuilder}. *

* When a client sends too many requests in a short time span, GitHub may return an error and set a header telling * the client to not make any more request for some period of time. If this happens, * {@link GitHubAbuseLimitHandler#onError(GitHubConnectorResponse)} will be called. *

* * @param handler * the handler * @return the git hub builder */ public GitHubBuilder withAbuseLimitHandler(GitHubAbuseLimitHandler handler) { this.abuseLimitHandler = handler; return this; } /** * Adds a {@link RateLimitChecker} for the Core API for this {@link GitHubBuilder}. * * @param coreRateLimitChecker * the {@link RateLimitChecker} for core GitHub API requests * @return the git hub builder * @see #withRateLimitChecker(RateLimitChecker, RateLimitTarget) */ public GitHubBuilder withRateLimitChecker(@Nonnull RateLimitChecker coreRateLimitChecker) { return withRateLimitChecker(coreRateLimitChecker, RateLimitTarget.CORE); } /** * Adds a {@link RateLimitChecker} to this {@link GitHubBuilder}. *

* GitHub allots a certain number of requests to each user or application per period of time (usually per hour). The * number of requests remaining is returned in the response header and can also be requested using * {@link GitHub#getRateLimit()}. This requests per interval is referred to as the "rate limit". *

*

* GitHub prefers that clients stop before exceeding their rate limit rather than stopping after they exceed it. The * {@link RateLimitChecker} is called before each request to check the rate limit and wait if the checker criteria * are met. *

*

* Checking your rate limit using {@link GitHub#getRateLimit()} does not effect your rate limit, but each * {@link GitHub} instance will attempt to cache and reuse the last seen rate limit rather than making a new * request. *

* * @param rateLimitChecker * the {@link RateLimitChecker} for requests * @param rateLimitTarget * the {@link RateLimitTarget} specifying which rate limit record to check * @return the git hub builder */ public GitHubBuilder withRateLimitChecker(@Nonnull RateLimitChecker rateLimitChecker, @Nonnull RateLimitTarget rateLimitTarget) { this.rateLimitChecker = this.rateLimitChecker.with(rateLimitChecker, rateLimitTarget); return this; } /** * Configures {@linkplain #withConnector(HttpConnector) connector} that uses HTTP library in JRE but use a specific * proxy, instead of the system default one. * * @param p * the p * @return the git hub builder */ public GitHubBuilder withProxy(final Proxy p) { return withConnector(new ImpatientHttpConnector(url -> (HttpURLConnection) url.openConnection(p))); } /** * Builds a {@link GitHub} instance. * * @return the git hub * @throws IOException * the io exception */ public GitHub build() throws IOException { return new GitHub(endpoint, connector, rateLimitHandler, abuseLimitHandler, rateLimitChecker, authorizationProvider); } /** * Clone. * * @return the git hub builder */ @Override public GitHubBuilder clone() { try { return (GitHubBuilder) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException("Clone should be supported", e); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy