gradle - create jar iteratively under a certain directory - gradle

I am trying to create multiple jars. I have a certain directory which contains multiple directory. Each directory has its own files(xml and sql). So I am trying to create a jar with a subdirectory name and all the files in it. Those jars will be used for junit test, so I want to create it during configuration phase in advance.
The target directory "../dist" exists outside this project.
ext.createTemplateJar = { sourceDirectory, jarFileName ->
jar {
archiveName = jarFileName
from sourceDirectory
includeEmptyDirs = false
manifest
{
attributes 'Implementation-Title' : VENDOR_NAME
}
}
println "creating a jar for ${jarFileName}"
}
tasks.withType(Jar) {
destinationDir = file("../dist")
}
task generateTemplates {
new File("${projectDir}/templates").eachFile() { file ->
if (file.isFile()) {
return
}
println "template dir is ${file.path}"
createTemplateJar(file.path, "${file.name}.jar")
}
}
When I execute this gradle generateTemplates, it runs fine, but I don't see any jar files created in the destination directory.
It seems something wrong, but I can't tell.

You should create multiple Jar tasks, one for each subdirectory inside ${projectDir}/templates, and have your generateTemplates task do nothing but depend on all of those tasks. For example (I renamed generateTemplates to allJars):
task allJars {
}
file("${projectDir}/templates").eachFile { f ->
def taskName = "jar${f.name.capitalize()}"
tasks.create(name: taskName, type: Jar) {
archiveName = "${f.name}.jar"
destinationDir = file('../dist')
// Configure each JAR however you want
}
allJars.dependsOn taskName
}
Example build:
$ ls templates/
bar baz foo test
$ ./gradlew clean allJars
:clean
:jarBar
:jarBaz
:jarFoo
:jarTest
:allJars
BUILD SUCCESSFUL
Total time: 0.615 secs
$ ls ../dist/
bar.jar baz.jar foo.jar test.jar

Related

Extracting single jar inside zip using gradle task

I’m trying to extract a jar from a zip file which is available inside the zip as below structure.
test.zip /web-inf /lib /result1.jar
Here is the task:-
task unzip(type: Copy){
group "testgroup"
def zipFile = file("$buildDir/test.zip")
def tree = zipTree(zipFile)
from(tree.matching { include "**/result1.jar"})
into "$builddir/dir"
includeEmptyDirs = false
}
But I am getting jar file with folder structure like /web-inf/lib/result1.jar. I want jar file alone, not the folders (/web-inf/lib/).
Please correct what is wrong in the gradle task.
Gradle Copy DSL provides a method eachFile (Closure closure) that you can use to perform action on each file which will be copied/extracted, see Copy DSL
In your case, you can use this method to rename (remove parent dirs from path) your file:
task unzip(type: Copy) {
group "testgroup"
from( zipTree(file("test.zip")).matching { include "**/result1.jar" } )
into "$buildDir/dir"
def parentDir = "web-inf/lib"
eachFile { fcp ->
fcp.path = fcp.path.replaceFirst("^$parentDir", '')
}
includeEmptyDirs = false
}

Gradle: remove some files from an existing war | for each war-file do: unpack, remove/filter, assemble war

I'm relatively new to gradle, so this might be a typical newbee-question.
In our gradle build, we have a set of war files (dependencies) that all include a file that we need to remove from those war files, before building our ear file.
How can I achieve the following:
- for all war files in a folder,
- extract war content to a location (using a Copy task & zipTree)
- re-pack to a new war applying a filter (using War & excludes)
I assume I'll create a new task and add some 'dependsOn' declarations.
task excludeUnwantedFiles(){
file(directoryWithOriginalWars).eachFile { file ->
???? unpack war, filter, assemble new war file ????
}
}
ear.dependsOn(excludeUnwantedFiles)
excludeUnwantedFiles.dependsOn(downloadAllOriginalWarsIntoDirectory)
How do I create that task, that executes for each war-file? What is the best way to do this?
Is there a way I can to this in one task? E.g. with the Copy task and using zipTree(fooBarWithFile.war) as 'from' and 'war(fooBarWithoutFile.war)' and applying a filter in between?
Or is this the way to go, just with a loop? Delete/Remove file from war with Gradle
Any help is highly appreciated!
Cheers,
d.
---------UPDATE-------------------
Thanx Lance Java for your solution.
As I mentioned in my comment, I faced the problem that the war files were downloaded/extracted during execution time and hence not accessable to define the new tasks at configuration time.
My workaround for this is to use tarTree (with a filter) to access the list of war-files that are not yet extracted. See my code example below:
def warFileSourceTarGz = '...tar.gz'
def nfsLibDir="$buildDir/dependencies/"
def nfsLibDownloadDir="$buildDir/downloadedDependencies/"
// task that downloads & extracts the tar.gz
task fetchNfsDependencies(type: Copy) {
from tarTree(warFileSourceTarGz)
into nfsLibDownloadDir
}
// loop through all war files inside the tar.gz and
// create a task to remove unwanted libraries for each war
task excludeUnwantedJarsFromWars(dependsOn: fetchNfsDependencies){
// access the "remote" tar.gz file to get the list of war-files to loop over
def warFileSource = tarTree(warFileSourceTarGz).matching{
include '*.war'
}
// for every war-file, create an exclude-path
warFileSource.visit { nextWarFile ->
if(nextWarFile.name.endsWith('.war')) {
String taskName = "excludeUnwantedJarsFrom_${nextWarFile.name.replace('.war', '')}"
String nextWarFilePath = nfsLibDownloadDir+"/"+nextWarFile.name
Zip tweakWarTask = tasks.create(name: taskName, type: Zip, dependsOn: fetchNfsDependencies) {
from zipTree(nextWarFilePath)
destinationDir = file(nfsLibDir)
archiveName = nextWarFile.name
// exclude these jars, as they cause classloading problems in our ear deployment.
exclude 'WEB-INF/lib/jcan-optrace*'
}
// hook into build-process
ear.dependsOn(tweakWarTask)
}
}
}
ear.dependsOn(excludeUnwantedJarsFromWars)
I'd create a Zip task per war file and wire all the tasks into the DAG by having assemble depend on them all
FileTree warFiles = fileTree(dir: 'path/to/wars', includes: ['**/*.war'])
warFiles.files.each { File warFile ->
String taskName = "tweakWar${warFile.name.replace('.war', '')}"
Zip tweakWarTask = tasks.create(name: taskName, type: Zip) {
from zipTree(warFile) {
exclude 'path/to/some/file.xml'
}
destinationDir = "$buildDir/tweakedWars"
archiveName = warFile.name
}
// wire the task into the dag
assemble.dependsOn tweakWarTask
}

Gradle copy task not copying files from temp folder first time around

I've a build file that runs tasks like this.
Task 1 (unpackWar): Unzips war file to Temp folder
Task 2 (copyWarFilesToWebContent): Copies the files to WebContent folder with some exclusions
Task 3 (copyRequiredJarFilesToWebContent): Unzips a couple of jar files from Temp/WEB-INF/lib to TempJarDir
Task 4 (explodeProductJars): Copies files we want from TempJarDir to WebContent folder
There is a single prepare task that runs each of these tasks using dependsOn and I've added mustRunAfter commands to each of the tasks so they execute in order. Also set upToDateWhen = false for each task.
What seems to happen is that Task 1 runs fine and unzips the war. Task 2 then uses the files from Temp and adds the required ones to WebContent correctly.
Task 3 and Task 4 are always coming back as Up To Date because seemingly there are no files to work with in the directory specified.
If I re-run prepare when the Temp folder exists, Task 3 and 4 run correctly.
I'm not sure if this is due to how fileTree works or if I'm doing something wrong. I've picked up gradle about a week ago and am still getting to grips with it.
Tasks look like this:
task prepare(dependsOn: ['unpackWar', 'copyWarFilesToWebContent', 'copyRequiredJarFilesToWebContent'])
prepare.outputs.upToDateWhen {false}
task unpackWar(type: Copy) {
description = 'unzips the war'
outputs.upToDateWhen { false }
def warFile = file(warFileLocation)
from zipTree(warFile)
into "Temp"
}
task copyWarFilesToWebContent(type: Copy) {
mustRunAfter unpackWar
description = 'Moves files from Temp to WebContent Folder'
outputs.upToDateWhen { false }
from ('Temp') {
exclude "**/*.class"
}
into 'WebContent'
}
task explodeProductJars(type: Copy) {
outputs.upToDateWhen { false }
FileTree tree = fileTree(dir: 'Temp/WEB-INF/lib', includes: ['application*-SNAPSHOT-resources.jar', 'services*-SNAPSHOT-resources.jar'])
tree.each {File file ->
from zipTree(file)
into "TempJarDir"
}
}
task copyRequiredJarFilesToWebContent(type: Copy, dependsOn: explodeProductJars) {
mustRunAfter copyWarFilesToWebContent
outputs.upToDateWhen { false }
from ("TempJarDir/META-INF/resources") {
include '**/*.xml'
}
into "WebContent/WEB-INF"
}
I've a feeling its something to do with fileTree but not sure whats happening exactly.
The Copy task is tricky. A Copy task will only be executed when it finds something to copy in the configuration phase. If it does not find anything during that phase it will be skipped.
You could use the copy method instead of the Copy task.
prepare( dependsOn: 'copyRequiredJarFilesToWebContent' ) {}
task unpackWar( type: Copy ) {
def warFile = file( warFileLocation )
from zipTree( warFile )
into 'Temp'
}
task copyWarFilesToWebContent( dependsOn: unpackWar ) << {
copy {
from ( 'Temp' ) {
exclude '**/*.class'
}
into 'WebContent'
}
}
task explodeProductJars( dependsOn: copyWarFilesToWebContent ) << {
copy {
FileTree tree = fileTree( dir: 'Temp/WEB-INF/lib', includes: [ 'application*-SNAPSHOT-resources.jar', 'services*-SNAPSHOT-resources.jar' ] )
tree.each { File file ->
from zipTree( file )
into 'TempJarDir'
}
}
}
task copyRequiredJarFilesToWebContent( dependsOn: explodeProductJars ) << {
copy {
from ( 'TempJarDir/META-INF/resources' ) {
include '**/*.xml'
}
into 'WebContent/WEB-INF'
}
}

Execute one gradle task

I've this two tasks:
war {
webInf { from 'src/main/resources/WEB-INF' }
manifest {
attributes 'Implementation-Version': versioning.info.display
}
}
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
task createDevelopmentWar(type: War, dependsOn: classes) {
archiveName "webapi-dev-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
copy {
from 'scopes/'
include 'configuration.development.properties'
into 'src/main/resources/'
}
}
Both tasks are trying to copy a property file fromscopes folder to src/main/resources/ folder.
I only run one task, however two files are copied in src/main/resources/ (configuration.demo.properties and configuration.development,properties.
Any ideas?
You use two copy specifications at the configuration phase (note, copy specification in that case doesn't configure your task, but add some extra action to it's configuration). That means, your files are getting copied during configuration. That's all because of this:
copy {
...
}
You have to run it during execution, to do that, try to move it into the doLast or doFirst closure, like so (for both tasks):
task createDemoWar(type: War, dependsOn: classes) {
archiveName "webapi-demo-${versioning.info.display}.war"
destinationDir = file("$buildDir/dist")
doFirst {
copy {
from 'scopes'
include 'configuration.demo.properties'
into 'src/main/resources/'
}
}
}
In that case, files will be copied only if task will be executed, right before the execution.

Gradle Distribution Task Output Files Not at Root of ZIP

I created a simple Gradle build that exports the contents of ./src/main/groovy to a zip file. The zip file contains a folder with the exact same name as the zip file. I cannot figure out how to get the files into the root of the zip file using the distribution plugin.
i.e. gradlew clean distZip produces:
helloDistribution-1.0.zip -> helloDistribution-1.0 -> files
what I would like:
helloDistribution-1.0.zip -> files
My build.gradle file:
apply plugin: 'groovy'
apply plugin: 'distribution'
version = '1.0'
distributions {
main {
contents {
from {
'src/main/groovy'
}
}
}
}
I have attempted to fix the problem by adding into { 'dir' } but to no avail.
Using into '/' seems to do the trick:
contents {
from {
'src/main/groovy'
}
into '/'
}
Unfortunately, penfold's answer did not work for me. Here is the solution I came up with:
task Package(type: Zip) {
from {
def rootScriptFiles = [] // collection of script files at the root of the src folder
new File('src/main/groovy/').eachFile { if (it.name.endsWith('.groovy')) rootScriptFiles.add(it) }
['build/libs/', // build binaries
'src/res/', // resources
rootScriptFiles, // groovy root source files
]
}
baseName = pluginName
}
To copy files into the root of helloDistribution-1.0.zip -> helloDistribution-1.0 -> use
contents {
from {
'some/file'
}
into ''
}

Resources