The gradle wrapper distribution URL does not support user info (username/password) in the URL

Small patch to support when URL is using format:

http://user:pass@server:port/distributions/gradle-x-bin.zip
diff --git a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
index 39e6b4c..eb7b6a9 100644
--- a/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
+++ b/subprojects/wrapper/src/main/java/org/gradle/wrapper/Download.java
@@ -51,6 +51,11 @@ public class Download implements IDownload {
             URL url = address.toURL();
             out = new BufferedOutputStream(new FileOutputStream(destination));
             conn = url.openConnection();
+
          String userInfo = url.getUserInfo();
+
          if (userInfo != null) {
+
              String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userInfo.getBytes());
+
              conn.setRequestProperty("Authorization", basicAuth);
+
          }
             final String userAgentValue = calculateUserAgent();
             conn.setRequestProperty("User-Agent", userAgentValue);
             in = conn.getInputStream();

How widely available is ‘javax.xml.bind.DatatypeConverter’?

It’s included with JAXB, which is included by default in Java 6 and above. It has some limitations, but is sufficient for many needs.

It’s unfortunately the first public API within the JDK/JRE that exposes a Base64 encoding mechanism, as earlier JDKs have more than one embedded Base64 encoder class, but all are internal classes.

There have been many discussions over the years as to the “best” way to deal with Base64 encoding, one good thread is the stackoverflow one below:

http://stackoverflow.com/questions/469695/decode-base64-data-in-java

If Gradle decided to be Java 6+ only, then it could utilize this method. Otherwise it would need to utilize some JRE internal class for pre-Java 6 JDKs, or implement a simple Base64 encoder (fairly tiny code) to include within the wrapper – suppose it could include some other implementation in the wrapper jar like guava or apache commons, but size might be the concern.

-Spencer

My company are starting to role out gradle and require this functionality to use the gradle wrapper. As all dependencies must be sourced from our artifactory repository, which is password protected.

Here is a test for the above patch

diff --git a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy b/subprojects/wrapper/src/integTest/groovy/org/gradle/integ
index 7d22c49..bba9e61 100644
--- a/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy
+++ b/subprojects/wrapper/src/integTest/groovy/org/gradle/integtests/WrapperHttpIntegrationTest.groovy
@@ -145,4 +145,22 @@ class WrapperHttpIntegrationTest extends AbstractIntegrationSpec {
         and:
         proxyServer.requestCount == 1
     }
+
+
  public void "downloads wrapper with basic authentication"() {
+
      given:
+
      prepareWrapper("http://user_foo:password_foo@localhost:${server.port}")
+
      server.expectGet("/gradlew/dist", "user_foo", "password_foo", distribution.binDistribution)
+
+
      when:
+
      def result = wrapperExecuter.withTasks('hello').run()
+
+
      then:
+
      assertThat(result.output, containsString('hello'))
+
+
      when:
+
      result = wrapperExecuter.withTasks('hello').run()
+
+
      then:
+
      assertThat(result.output, containsString('hello'))
+
  }
 }

Thanks for the test. Any chance one of you can submit a pull request? That helps to streamline the process of getting changes accepted.

Note that any solution also needs to work with Java 1.5, since that’s the lowest version supported by Gradle.

Thanks.

What do Gradle use for Base64 encoding? That’s the only needs there is for the javax.xml.bind package? @Iain did you do a pull requests?

The pull request is on its way

Java 1.5 does not include a public Base64 encoding class. Would it be ok to include this public domain implementation in the wrapper code?

http://iharder.net/base64

Unlike the rest of Gradle, the wrapper can’t use any external libraries. Like the rest of Gradle, it has to work on Java 5 and higher.

I’d go with http://www.source-code.biz/base64coder/java/ (unless it’s not suitable for some reason) because it’s a lot smaller. Maybe you could also bring over the JUnit test.

I have just sent the pull request. https://github.com/gradle/gradle/pull/201

I would appreciate any feedback on this, as it is my first contribution. I have emailed the signed CLA.

I added the iharder code and test as sugested. The only changes were to pass checkstyle.

I added support for specifying the username and password in the users gradle.properties file. This is because the url is normally specified in the wrapper’s property file which is committed to source control (so users adding their username and password is not always safe).

Given that Gradle 2.0 now longer support JDK 1.5 has this issues been addressed.

I have recently run into an issue with a client where only internal authenticated repositories can be used. Serving up the gradle distribution from there fails, as user/pass is not supported in the wrapper.

(Well, techinically user/pass is supported in the wrapper, but only when using a proxy - going direcly to a server requiring authentication fails).

I would still love to add this feature to the wrapper, it still affects me too.

If there is any consensus to include this feature I am happy to resubmit the pull request without the Base64 implementation.

1 Like