'How Do I Update An Existing War/Jar/Zip File Using Gradle?
I need to make a copy of an existing war file and update an xml file within it. My thoughts on how to do this are:
- Extract file from existing war
- Replace String in file
- Copy war
- Add modified file back to copied war
I can do the first 3 steps with Gradle but I can only work out how to do the last step with Ant.
task updateWar() << {
def originalWar = file("deploy/mywar.war")
def outputDir = file("deploy")
def wars = [ "war1", "war2" ]
wars.each() { warFile ->
delete "deploy/WEB-INF/ejb.xml"
copy {
//Step 1
from(zipTree(originalWar)) {
include 'WEB-INF/ejb.xml'
}
into outputDir
//Step 2
filter{
String line -> line.replaceAll("<value>OriginalText</value>",
"<value>UpdatedText</value>")
}
}
//Step 3
copy {
from outputDir
into outputDir
include 'mywar.war'
rename 'mywar.war',"${warFile}.war"
}
//Step 4
ant.jar(update: "true", destfile: deploy/${warFile}.war") {
fileset(dir: deploy", includes: 'WEB-INF/**')
}
}
}
Ideally there would be a filter option that allowed me to modify the specified file when I was copying but I haven't worked that out yet.
How do you do this effectively in Gradle without falling back to Ant? Is even a groovy gradle way to do it in one step?
Edit: I have got closer. A Zip task using a ziptree from the original war was the first key step. The filesMatching combined with the filter was the secret sauce! However, I can't use this in a loop like I can the copy method so I'm still stuck :(
task updateWar(type: Zip) {
def originalWar = file("deploy/mywar.war")
def outputDir = file("deploy")
archiveName = "war2.war"
destinationDir = outputDir
from (zipTree(originalWar),{
filesMatching("WEB-INF/ejb.xml") {
filter{
String line -> line.replaceAll("<value>OriginalText</value>",
"<value>UpdatedText</value>")
}
}
})
}
Solution 1:[1]
Assuming you just want to replace the original file within the war with one in the res folder, here is how to do it:
task updateWar(type: Zip) {
def originalWar = file("deploy/mywar.war")
archiveBaseName = 'mywar'
archiveExtension = 'war'
from(zipTree(originalWar)) {
// Remove the original ejb.xml if it exists
exclude("**/WEB-INF/ejb.xml")
}
// Include our own ejb.xml
from('res/ejb.xml') {
into('WEB-INF/')
}
}
Solution 2:[2]
With Gradle 7.x you can replace archive (zip) files via DuplicatesStrategy. It does not provide 'override' strategy, buy you can achieve the same result with 'exclude' strategy and reversed copy order. Like this:
task updateWar(type: Zip) {
...
duplicatesStrategy 'exclude'
// First copy the overriding files.
from('res/ejb.xml') {
into('WEB-INF/')
}
// Then copy the common content.
// (duplicate files it will be skipped)
from(zipTree(originalWar)) {
...
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | smac89 |
| Solution 2 | Dimitar II |
