diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 9037572c7c..66b6ffe1df 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -128,10 +128,10 @@ public class GitHub { } /** - * Obtains the credential from "~/.github" + * Obtains the credential from "~/.github" or from the System Environment Properties. */ public static GitHub connect() throws IOException { - return GitHubBuilder.fromPropertyFile().build(); + return GitHubBuilder.fromCredentials().build(); } /** diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index baf26a6415..e08a8dd2a2 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -4,7 +4,9 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Map; import java.util.Properties; /** @@ -12,19 +14,89 @@ */ public class GitHubBuilder { private String endpoint = GitHub.GITHUB_URL; - private String user; - private String password; - private String oauthToken; + + // default scoped so unit tests can read them. + /* private */ String user; + /* private */ String password; + /* private */ String oauthToken; + private HttpConnector connector; public GitHubBuilder() { } + /** + * First check if the credentials are configured using the ~/.github properties file. + * + * If no user is specified it means there is no configuration present so check the environment instead. + * + * the system properties for the login, password or oauth environment variables. + * + * @return the configured Builder from credentials defined on the system or in the environment. + * + * @throws IOException + */ + public static GitHubBuilder fromCredentials() throws IOException { + + GitHubBuilder builder; + try { + builder = fromPropertyFile(); + + if (builder.user != null) + return builder; + else + return fromEnvironment(); + + } catch (FileNotFoundException e) { + return fromEnvironment(); + } + + } + + public static GitHubBuilder fromEnvironment(String loginVariableName, String passwordVariableName, String oauthVariableName) throws IOException { + + + Properties env = new Properties(); + + Object loginValue = System.getenv(loginVariableName); + + if (loginValue != null) + env.put("login", loginValue); + + Object passwordValue = System.getenv(passwordVariableName); + + if (passwordValue != null) + env.put("password", passwordValue); + + Object oauthValue = System.getenv(oauthVariableName); + + if (oauthValue != null) + env.put("oauth", oauthValue); + + return fromProperties(env); + + } + + public static GitHubBuilder fromEnvironment() throws IOException { + + Properties props = new Properties(); + + Map env = System.getenv(); + + for (Map.Entry element : env.entrySet()) { + + props.put(element.getKey(), element.getValue()); + } + + return fromProperties(props); + } + public static GitHubBuilder fromPropertyFile() throws IOException { File homeDir = new File(System.getProperty("user.home")); File propertyFile = new File(homeDir, ".github"); return fromPropertyFile(propertyFile.getPath()); } + public static GitHubBuilder fromPropertyFile(String propertyFileName) throws IOException { Properties props = new Properties(); FileInputStream in = null; @@ -34,6 +106,11 @@ public static GitHubBuilder fromPropertyFile(String propertyFileName) throws IOE } finally { IOUtils.closeQuietly(in); } + + return fromProperties(props); + } + + public static GitHubBuilder fromProperties(Properties props) { GitHubBuilder self = new GitHubBuilder(); self.withOAuthToken(props.getProperty("oauth"), props.getProperty("login")); self.withPassword(props.getProperty("login"), props.getProperty("password")); diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 6ff39feec9..25a7a09d2a 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -1,5 +1,12 @@ package org.kohsuke.github; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + import junit.framework.TestCase; /** @@ -21,4 +28,97 @@ public void testGitHubServerWithoutServer() throws Exception { GitHub hub = GitHub.connectUsingPassword("kohsuke", "bogus"); assertEquals("https://api.github.com/test", hub.getApiURL("/test").toString()); } + + public void testGitHubFromEnvironment() throws IOException { + + Mapprops = new HashMap(); + + props.put("login", "bogus"); + + setupEnvironment(props); + + GitHub hub = GitHub.connect(); + + assertEquals("bogus", hub.login); + + } + + public void testGitHubBuilderFromEnvironment() throws IOException { + + Mapprops = new HashMap(); + + props.put("login", "bogus"); + props.put("oauth", "bogus"); + props.put("password", "bogus"); + + setupEnvironment(props); + + GitHubBuilder builder = GitHubBuilder.fromEnvironment(); + + assertEquals("bogus", builder.user); + assertEquals("bogus", builder.oauthToken); + assertEquals("bogus", builder.password); + + } + + /* + * Copied from StackOverflow: http://stackoverflow.com/a/7201825/2336755 + * + * This allows chaning the process environment. + */ + private void setupEnvironment(Map newenv) { + try + { + Class processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment"); + Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment"); + theEnvironmentField.setAccessible(true); + Map env = (Map) theEnvironmentField.get(null); + env.putAll(newenv); + Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment"); + theCaseInsensitiveEnvironmentField.setAccessible(true); + Map cienv = (Map) theCaseInsensitiveEnvironmentField.get(null); + cienv.putAll(newenv); + } + catch (NoSuchFieldException e) + { + try { + Class[] classes = Collections.class.getDeclaredClasses(); + Map env = System.getenv(); + for(Class cl : classes) { + if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) { + Field field = cl.getDeclaredField("m"); + field.setAccessible(true); + Object obj = field.get(env); + Map map = (Map) obj; + map.clear(); + map.putAll(newenv); + } + } + } catch (Exception e2) { + e2.printStackTrace(); + } + } catch (Exception e1) { + e1.printStackTrace(); + } + + } + + public void testGitHubBuilderFromCustomEnvironment() throws IOException { + + Mapprops = new HashMap(); + + props.put("customLogin", "bogusLogin"); + props.put("customOauth", "bogusOauth"); + props.put("customPassword", "bogusPassword"); + + setupEnvironment(props); + + GitHubBuilder builder = GitHubBuilder.fromEnvironment("customLogin", "customPassword", "customOauth"); + + assertEquals("bogusLogin", builder.user); + assertEquals("bogusOauth", builder.oauthToken); + assertEquals("bogusPassword", builder.password); + + } + }