'Gradle task replace string in .java file

I want to replace few lines in my Config.java file before the code gets compiled. All I was able to find is to parse file through filter during copying it. As soon as I have to copy it I had to save it somewhere - thats why I went for solution: copy to temp location while replacing lines > delete original file > copy duplicated file back to original place > delete temp file. Is there better solution?



Solution 1:[1]

To complement lance-java's answer, I found this idiom more simple if there's only one value you are looking to change:

task generateSources(type: Copy) {
    from 'src/replaceme/java'
    into "$buildDir/generated-src"
    filter { line -> line.replaceAll('xxx', 'aaa') }
}

Caveat: Keep in mind that the Copy task will only run if the source files change. If you want your replacement to happen based on other conditions, you need to use Gradle's incremental build features to specify that.

Solution 2:[2]

  1. I definitely wouldn't overwrite the original file
  2. I like to keep things directory based rather than filename based so if it were me, I'd put Config.java in it's own folder (eg src/replaceme/java)
  3. I'd create a generated-src directory under $buildDir so it's deleted via the clean task.

You can use the Copy task and ReplaceTokens filter. Eg:

apply plugin: 'java'
task generateSources(type: Copy) {
    from 'src/replaceme/java'
    into "$buildDir/generated-src"
    filter(ReplaceTokens, tokens: [
        'xxx': 'aaa', 
        'yyy': 'bbb'
    ])
}
// the following lines are important to wire the task in with the compileJava task
compileJava.source "$buildDir/generated-src"
compileJava.dependsOn generateSources

Solution 3:[3]

If you do wish to overwrite the original file, using a temp file strategy, the following will create the filtered files, copy them over the original, and then delete the temp files.

task copyAtoB(dependsOn: [existingTask]) {
    doLast {
        copy {
            from("folder/a") {
                include "*.java"
            }
            // Have to use a new path for modified files
            into("folder/b")
            filter {
                String line ->
                    line.replaceAll("changeme", "to this")
            }
        }
    }
}

task overwriteFilesInAfromB(dependsOn: [copyAtoB]) {
    doLast {
        copy {
            from("folder/b") {
                include "*.java"
            }
            into("folder/a")
        }
    }
}

// Finally, delete the files in folder B
task deleteB(type: Delete, dependsOn: overwriteFilesInAfromB) {
    delete("folder/b")
}

nextTask.dependsOn(deleteB)

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
Solution 2
Solution 3 bdetweiler