diff options
author | LexManos <LexManos@gmail.com> | 2019-05-03 15:43:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-03 15:43:07 -0700 |
commit | d3c01e7be2247cce9f6fe3456db73dd0a7ef1ccf (patch) | |
tree | 945e46af6d7359a987d31a30c162bc167e741407 | |
parent | 37d713bdb7459cdd44707b350fd12fd59517b415 (diff) | |
parent | 747c582804bdcd0409417fdd92f7a3042d80b6b5 (diff) | |
download | Artifactural-d3c01e7be2247cce9f6fe3456db73dd0a7ef1ccf.tar.gz Artifactural-d3c01e7be2247cce9f6fe3456db73dd0a7ef1ccf.tar.bz2 Artifactural-d3c01e7be2247cce9f6fe3456db73dd0a7ef1ccf.zip |
Merge pull request #1 from Aaron1011/gradle-compat-final
Add compatibility with Gradle 4.10 and above
-rw-r--r-- | build.gradle | 158 | ||||
-rw-r--r-- | gradle.properties | 1 | ||||
-rw-r--r-- | gradle/wrapper/gradle-wrapper.jar | bin | 52271 -> 54413 bytes | |||
-rw-r--r-- | gradle/wrapper/gradle-wrapper.properties | 4 | ||||
-rwxr-xr-x | gradlew | 78 | ||||
-rw-r--r-- | gradlew.bat | 174 | ||||
-rw-r--r-- | src/gradlecomp/java/com/amadornes/artifactural/gradle/Gradle410RepositoryAdapter.java | 42 | ||||
-rw-r--r-- | src/gradlecomp/java/com/amadornes/artifactural/gradle/GradleRepositoryAdapter.java | 54 |
8 files changed, 381 insertions, 130 deletions
diff --git a/build.gradle b/build.gradle index 635950d..d6cbd04 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,30 @@ +buildscript { + repositories { + mavenCentral() + } + dependencies { + // Needed for bytecode manipulation + classpath 'org.ow2.asm:asm-all:5.2' + } +} + plugins { id 'net.minecrell.licenser' version '0.3' id 'org.ajoberstar.grgit' version '2.3.0' //id 'com.github.johnrengelman.shadow' version '2.0.4' } +import java.nio.file.Paths +import org.objectweb.asm.ClassReader +import org.objectweb.asm.ClassWriter +import org.objectweb.asm.Opcodes +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.MethodInsnNode +import org.objectweb.asm.tree.VarInsnNode +import org.objectweb.asm.tree.InsnNode + +import java.util.jar.JarFile + apply plugin: 'java' apply plugin: 'maven-publish' @@ -15,7 +36,7 @@ def gitVersion() { def hash = desc.remove(desc.size() - 1) def offset = desc.remove(desc.size() - 1) def tag = desc.join('-') - def branch = grgit.branch.current().name + def branch = grgit.branch.current().name return "${tag}.${offset}" //${t -> if (branch != 'master') t << '-' + branch}" } @@ -52,10 +73,143 @@ dependencies { compile sourceSets.gradlecomp.output } + + +def gradleRepositoryAdapterPath = Paths.get("com", "amadornes", "artifactural", "gradle", "GradleRepositoryAdapter.class") +def classesDirs = sourceSets.gradlecomp.output.classesDirs.getFiles().first().toPath() + + +def _constructorName = "<init>" +def _constructorDesc = "(Lcom/amadornes/artifactural/api/repository/Repository;Lorg/gradle/api/internal/artifacts/repositories/DefaultMavenLocalArtifactRepository;)V" +def _modifiedSuperDesc = "()V" + +// This task patches 'GradleRepositoryAdapter' to make it compatibile with both Gradle 4.9 and 4.10 +// In Gradle 4.9, the constructor of AbstractArtifactRepository changes has zero arguments +// (instead of the one-argument constructor in 4.10, which we compile against) +// It's not possible to write a normal Java class that calls a constructor which doesn't exist at compile time. +// Therefore, we need to patch the bytecode of the class to properly call the non-arg super() constrcutor +class PatchGradleRepositoryAdapter extends DefaultTask { + + @Input String constructorName + @Input String constructorDesc + @Input String modifiedSuperDesc + @Input File gradleRepositoryAdapter + @Input File classesDir + @OutputDirectory java.nio.file.Path outputDir + + + @TaskAction + void patchClass() { + def originalGradleRepositoryAdapter = Paths.get(classesDir.toString(), gradleRepositoryAdapter.toString()) + + ClassNode node = new ClassNode() + ClassReader reader = new ClassReader(new FileInputStream(originalGradleRepositoryAdapter.toFile())) + reader.accept(node, 0) + + + def constructor = node.methods.find { + it.name == constructorName && it.desc == constructorDesc + } + + def getDescriptor = node.methods.find { + it.name == "getDescriptor" + } + + if (constructor == null) { + throw new RuntimeException("Failed to find target constructor!") + } + + if (getDescriptor == null) { + throw new RuntimeException("Failed to find getDescriptor()") + } + + // Strip out this method - it only exists + // so that GradleRepositoryAdapter will compile + node.methods.remove(getDescriptor) + + def superInvoc = constructor.instructions.find { + it instanceof MethodInsnNode && it.owner == "org/gradle/api/internal/artifacts/repositories/AbstractArtifactRepository" + } as MethodInsnNode + + if (superInvoc == null) { + throw new RuntimeException("Failed to find target super() invocation!") + } + + superInvoc.desc = modifiedSuperDesc + + def aconstNull = superInvoc.previous + if (!(aconstNull instanceof InsnNode) || aconstNull.type != 0) { + throw new RuntimeException("Unexpected instruction: " + aconstNull) + } + + constructor.instructions.remove(aconstNull) + + // Push first parameter of constructor (the ObjectFactory) onto the stack. + // This has the effect of calling super(objectFactory) + //constructor.instructions.insertBefore(superInvoc, new VarInsnNode(Opcodes.ALOAD, 1)) + + ClassWriter writer = new ClassWriter(0) + node.accept(writer) + + def outputFile = outputDir.resolve(gradleRepositoryAdapter.toPath()).toFile() + + outputFile.parentFile.mkdirs() + FileOutputStream fs = new FileOutputStream(outputFile) + fs.write(writer.toByteArray()) + } +} + + + +task patchConstructor(type: PatchGradleRepositoryAdapter) { + constructorName = _constructorName + constructorDesc = _constructorDesc + modifiedSuperDesc = _modifiedSuperDesc + classesDir = classesDirs.toFile() + outputDir = Paths.get(buildDir.toString(), "modifiedclasses") + gradleRepositoryAdapter = gradleRepositoryAdapterPath.toFile() +} + jar { from sourceSets.api.output from sourceSets.shared.output - from sourceSets.gradlecomp.output + from(sourceSets.gradlecomp.output) { + exclude gradleRepositoryAdapterPath.toString() + } + + from patchConstructor.outputs +} + +jar.doLast { + def jarPath = it.outputs.files.getFiles().first() + def jarFile = new JarFile(jarPath) + def entry = jarFile.getEntry(gradleRepositoryAdapterPath.toString()) + def stream = jarFile.getInputStream(entry) + + ClassReader reader = new ClassReader(stream) + ClassNode node = new ClassNode() + reader.accept(node, 0) + + def constructor = node.methods.find { + it.name == _constructorName && it.desc == _constructorDesc + } + + def superInvoc = constructor.instructions.find { + it instanceof MethodInsnNode && it.owner == "org/gradle/api/internal/artifacts/repositories/AbstractArtifactRepository" + } as MethodInsnNode + + if (superInvoc.desc == _modifiedSuperDesc) { + println("Successfully modified super() call!") + } else { + throw new RuntimeException("Failed to modify super() invocation - got desc of " + superInvoc.desc) + } + + def getDescriptor = node.methods.find { it.name == "getDescriptor"} + if (getDescriptor != null) { + throw new RuntimeException("Failed to remove getDescriptor with signature: " + getDescriptor.signature) + } else { + println("Successfully stripped getDescriptor method!") + } } task sourcesJar(type: Jar, dependsOn: classes) { diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differindex 30d399d..0d4a951 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5aa013a..2e7105d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Jun 09 16:26:43 CEST 2018 +#Thu Apr 25 19:18:54 EDT 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..e95643d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,90 +1,84 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/gradlecomp/java/com/amadornes/artifactural/gradle/Gradle410RepositoryAdapter.java b/src/gradlecomp/java/com/amadornes/artifactural/gradle/Gradle410RepositoryAdapter.java new file mode 100644 index 0000000..ceaf989 --- /dev/null +++ b/src/gradlecomp/java/com/amadornes/artifactural/gradle/Gradle410RepositoryAdapter.java @@ -0,0 +1,42 @@ +/* + * Artifactural + * Copyright (c) 2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package com.amadornes.artifactural.gradle; + +import com.amadornes.artifactural.api.repository.Repository; +import org.gradle.api.internal.artifacts.repositories.DefaultMavenLocalArtifactRepository; +import org.gradle.api.internal.artifacts.repositories.descriptor.FlatDirRepositoryDescriptor; +import org.gradle.api.internal.artifacts.repositories.descriptor.RepositoryDescriptor; +import org.gradle.api.model.ObjectFactory; + +import java.util.ArrayList; + +public class Gradle410RepositoryAdapter extends GradleRepositoryAdapter { + + Gradle410RepositoryAdapter(ObjectFactory objectFactory, Repository repository, DefaultMavenLocalArtifactRepository local) { + super(objectFactory, repository, local); + } + + + @Override + public RepositoryDescriptor getDescriptor() { + return new FlatDirRepositoryDescriptor("ArtifacturalRepository", new ArrayList<>()); + } + +} diff --git a/src/gradlecomp/java/com/amadornes/artifactural/gradle/GradleRepositoryAdapter.java b/src/gradlecomp/java/com/amadornes/artifactural/gradle/GradleRepositoryAdapter.java index 64d6652..669ad4c 100644 --- a/src/gradlecomp/java/com/amadornes/artifactural/gradle/GradleRepositoryAdapter.java +++ b/src/gradlecomp/java/com/amadornes/artifactural/gradle/GradleRepositoryAdapter.java @@ -37,11 +37,14 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.Resol import org.gradle.api.internal.artifacts.repositories.AbstractArtifactRepository; import org.gradle.api.internal.artifacts.repositories.DefaultMavenLocalArtifactRepository; import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository; +import org.gradle.api.internal.artifacts.repositories.descriptor.FlatDirRepositoryDescriptor; +import org.gradle.api.internal.artifacts.repositories.descriptor.RepositoryDescriptor; import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceArtifactResolver; import org.gradle.api.internal.artifacts.repositories.resolver.ExternalResourceResolver; import org.gradle.api.internal.artifacts.repositories.resolver.MavenResolver; import org.gradle.api.internal.artifacts.repositories.resolver.MetadataFetchingCost; import org.gradle.api.internal.component.ArtifactType; +import org.gradle.api.model.ObjectFactory; import org.gradle.internal.action.InstantiatingAction; import org.gradle.internal.component.external.model.ModuleComponentResolveMetadata; import org.gradle.internal.component.external.model.ModuleDependencyMetadata; @@ -65,10 +68,12 @@ import org.gradle.internal.resource.local.LocalFileStandInExternalResource; import org.gradle.internal.resource.local.LocallyAvailableExternalResource; import org.gradle.internal.resource.metadata.ExternalResourceMetaData; import org.gradle.internal.resource.transfer.DefaultCacheAwareExternalResourceAccessor; +import org.gradle.util.GradleVersion; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.ArrayList; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -85,7 +90,18 @@ public class GradleRepositoryAdapter extends AbstractArtifactRepository implemen maven.setUrl(local); maven.setName(name); - GradleRepositoryAdapter repo = new GradleRepositoryAdapter(repository, maven); + GradleRepositoryAdapter repo; + + // On Gradle 4.10 above, we need to use the constructor with the 'ObjectFactory' parameter + // (which can be safely passed as null - see BaseMavenInstaller). + // We use Gradle410RepositoryAdapter, which actually overrides 'getDescriptor' + if (GradleVersion.current().compareTo(GradleVersion.version("4.10")) >= 0) { + repo = new Gradle410RepositoryAdapter(null, repository, maven); + } else { + // On versions of gradle older than 4.10, we use the no-arg super constructor + repo = new GradleRepositoryAdapter(repository, maven); + } + repo.setName(name); handler.add(repo); return repo; @@ -96,7 +112,25 @@ public class GradleRepositoryAdapter extends AbstractArtifactRepository implemen private final String root; private final LocatedArtifactCache cache; + + // This constructor is modified via bytecode manipulation in 'build.gradle' + // DO NOT change this without modifying 'build.gradle' + // This contructor is used on Gradle 4.9 and below private GradleRepositoryAdapter(Repository repository, DefaultMavenLocalArtifactRepository local) { + // This is replaced with a call to 'super()', with no arguments + super(null); + this.repository = repository; + this.local = local; + this.root = cleanRoot(local.getUrl()); + this.cache = new LocatedArtifactCache(new File(root)); + } + + + // This constructor is used on Gradle 4.10 and above + GradleRepositoryAdapter(ObjectFactory objectFactory, Repository repository, DefaultMavenLocalArtifactRepository local) { + super(objectFactory); + // This duplication from the above two-argument constructor is unfortunate, + // but unavoidable this.repository = repository; this.local = local; this.root = cleanRoot(local.getUrl()); @@ -182,6 +216,24 @@ public class GradleRepositoryAdapter extends AbstractArtifactRepository implemen }; } + // This method will be deleted entirely in build.gradle + // In order for this class to compile, this method needs to exist + // at compile-time. However, the class 'RepositoryDescriptor' doesn't + // exist in Gradle 4.9. If we try to classload a class + // that contains RepositoryDescriptor as a method return type, + // the JVM will try to classload RepositoryDescriptor, leading + // to a NoClassDefFoundError + + // To fix this, we strip out this method at build time. + // At runtime, we instantiate Gradle410RepositoryAdapter + // when we're running on Gradle 4.10 on above. + // This ensures that 'getDescriptor' exists on Gradle 4.10, + // and doesn't existon Gradle 4.9 + public RepositoryDescriptor getDescriptor() { + throw new Error("This method should be been stripped at build time!"); + } + + private static String cleanRoot(URI uri) { String ret = uri.normalize().getPath().replace('\\', '/'); if (!ret.endsWith("/")) ret += '/'; |