I am creating a Gradle task in which I want to download and reference the jar file for an artifact that exists in a Maven repository. Specifically, I plan to call an external script through the Gradle exec task using the location of that jar as an argument to the script. Using the exec task is straightforward; what I am trying to figure out is how to acquire the location of artifact's jar file on the filesystem.
As a simple yet concrete example, assume I have the following files in my Gradle project directory:
build.gradle:
task myScript(type: Exec) {
executable './my_script.sh'
args jarFilePath // How do I get this value?
}
my_script.sh:
#!/usr/bin/env bash
echo "Jar file location: $1"
How can I get the file path to the artifact jar, downloading it from the remote repository if necessary? For instance, it should be downloaded if it's not in my local artifact cache, or it's an updated snapshot version.
Let's assume that the jar file we want is
guava-26.0-jre.jar
. The followingbuild.gradle
file will retrieve the artifact (if necessary) and provide the file location as an argument to the script:This creates a custom configuration named "myArtifact" with a single dependency on
guava-26.0-jre
. By marking it astransitive: false
none of the artifact's dependencies will be included in the configuration, nor will they be downloaded if they do not yet exist in the local artifact cache.The call to
configurations.myArtifact.singleFile
returns ajava.io.File
reference to the artifact's jar file. This getSingleFile() method also ensures that there is exactly one file in the collection, throwing anIllegalStateException
if there are zero or more than one. This guards against referencing the wrong artifact if the configuration gets incorrectly misconfigured in the future to having multiple artifacts (e.g. if somebody removes the "transitive" option from our script).The toAbsolutePath() method ensures that the path to the script is absolute, and therefore does not need to be resolved relative to any particular directory.
Note that this is copying the artifact to the task's temporary directory in a doFirst block, rather than referencing the file's path directly. This is so that the artifact doesn't need to be resolved when loading the script. Otherwise, the artifact would need to be resolved (and possibly downloaded) even when doing unrelated tasks — including such basic tasks as
clean
andtasks
— causing a build failure if the artifact could not be resolved.The
StandardCopyOption.REPLACE_EXISTING
option is used to overwrite any previous jar file from previous builds.