I am trying to implement something that will replace ${pattern}
in xml files in my build.gradle file:
processResources {
eachFile { FileCopyDetails fileCopyDetails ->
if (fileCopyDetails.name.contains("blueprint.xml")) {
project.logger.quiet "Processing: " + fileCopyDetails.path
logger.quiet "" + project.ext.properties.entrySet()
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [prop1, value, prop2, value])
}
}
}
tokens:
appears to take a Map. Again, how does this relate to the function signature?
Convert all properties with String values into a Map for input into tokens:
def tokenMap = new LinkedHashMap()
def stringProps = project.ext.properties.entrySet().findAll { entry -> entry.getValue() instanceof String }
stringProps.each { entry -> tokenMap.put(entry.key, entry.value)}
A look at the Gradle Javadoc reveals a filter function whose signature does not seem to match the examples. Particularly, the Map<String,?>
and Class<? extends FilterReader>
do not match the order in the examples as far as I understand them. Could somebody map the example to the function signature so that I understand what is going on?
CopySpec filter(Map<String,?> properties, Class<? extends FilterReader> filterType)
Adds a content filter to be used during the copy. Multiple calls to filter, add additional filters to the filter chain. Each filter should implement java.io.FilterReader. Include org.apache.tools.ant.filters.* for access to all the standard Ant filters.
Filter properties may be specified using groovy map syntax.
Examples:
filter(HeadFilter, lines:25, skip:2) filter(ReplaceTokens, tokens:[copyright:'2009', version:'2.3.1'])
Specified by:
filter
in interfaceContentFilterable
Parameters:
properties
- map of filter propertiesfilterType
- Class of filter to addReturns: this
Related:
How is a token replaced in a file for a Gradle build product?
Note:
What does not work is the SimpleTemplateEngine
processResources {
filesMatching("**/features.xml") {
// expand uses Groovy's SimpleTemplateEngine
project.logger.quiet "Processing: " + file
expand project.getProperties()
}
This is actually a feature of the underlying Groovy syntax. Groovy allows you to specify method parameters by name (i.e.
<name>: <value>
) whenever the first parameter to the method is declared as aMap
. Crucially, named parameters can appear at any point in the argumemt list, even after so-called positional parameters (i.e. those declared after theMap
in the method signature), and they will be put as entries in the initialMap
parameter. See the section Mixing named and positional parameters in the Groovy Language Documentation for more details.So, the Gradle
filter
method has signatureThe first
properties
parameter is of typeMap
, so this method can be called with named parameters. In addition, there is one more positional parameter,filterType
. So, to call this method, you must specify one parameter without a name, of typeClass<? extends FilterReader>
, which will be used forfilterType
, and zero or more named parameters, which will all be put in theproperties
Map.Taking one of the examples from the documentation:
will mean that
filter
is called withAny of the following calls would be equivalent:
The last call here passes both parameters positionally (you don't have to use named parameters when the first parameter is declared as a
Map
).Aside Note
I'm intrigued as to why using
expand
doesn't work - it should!