Home > Back-end >  How can I use a properties file in the "expand" portion of the Gradle Copy task?
How can I use a properties file in the "expand" portion of the Gradle Copy task?

Time:02-02

Lets say I have properties file config.properties which has

prop1=abc
prop2=xyz

and a template-config.xml that looks something like

<bean id="id1" >
  <property name="prop1" value="${prop1}" />
  <property name="prop2" value="${prop2}" />
</bean>

I have 2 Questions:

  1. Is there a way I can use the property file in the expand() portion of the gradle copy task to inject the properties into the config from gradle.build.kts?

  2. Is there a way I can use expand to fill in only one of the properties without throwing an error?

So far I have

tasks.register<Copy>("create-config-from-template") {
    from("$buildDir/resources/main/template-config.xml")
    into("$buildDir/dist")
    expand(Pair("prop1", "abc"))
}

However, this throws an error

Missing property (prop2) for Groovy template expansion. Defined keys [prop1].

I know that I can also specify the value for prop2 inside "expand()", but for my purposes it would help if I could only inject some of the properties and not others. Is there a simple way to tell gradle not to worry about the other "${}" properties in the file?

If not, is there a way I can use the actual property file as the set of properties to expand? I can't seem to find the Kotlin DSL syntax for this anywhere.

Thank you very much in advance.

CodePudding user response:

For 1, you can use configure the existing processResources task to apply additional configuration to a specific file. In this case template-config.xml, for example:

tasks.processResources {
    filesMatching("**/template-config.xml") {
        val examplePropertiesTextResource = resources.text.fromFile(layout.projectDirectory.file("example.properties"))
        val exampleProperties = Properties().apply {
            FileInputStream(examplePropertiesTextResource.asFile()).use { load(it) }
        }
        val examplePropertiesMap = mutableMapOf<String, Any>().apply {
            exampleProperties.forEach { k, v -> put(k.toString(), v) }
        }
        expand(examplePropertiesMap)
    }
}

filesMatching will match on the file you want. Then the proceeding lines load the properties file, in this case a file name example.properties in the project's root directory. It is then transformed into a Map<String, Any> and passed to the expand method.

However, for 2, with the above approach it will fail if any properties are missing. This is because the underlying expansion engine (SimpleTemplateEngine) does not allow such configuration

As an alternative, you can use ExpandTokens from Apache ANT to achieve the replacement when some properties are missing:

tasks.processResources {
    filesMatching("**/template-config.xml") {
        val examplePropertiesTextResource = resources.text.fromFile(layout.projectDirectory.file("example.properties"))
        val exampleProperties = Properties().apply {
            FileInputStream(examplePropertiesTextResource.asFile()).use { load(it) }
        }
        val examplePropertiesMap = mapOf<String, Any>("tokens" to exampleProperties.toMap())
        println(examplePropertiesMap)
        filter(examplePropertiesMap, ReplaceTokens::class.java)
    }
}

Note that for ReplaceTokens, you must change the placeholders from ${example} to @example@:

<bean id="id1" >
    <property name="prop1" value="@prop1@" />
    <property name="prop2" value="@prop2@" />
</bean>

This is because Gradle only accepts a Class and ReplaceTokens is final, so you can't extend the class to use ${} as the placeholders.

  • Related