How to inject properties in XML file

Hi,

In [build.gradle] I use ANT to call a class which use an xml file as config. This xml file contain vars like

${this.property.should.be.filled}

maven.groovy (partly because it’s very long)

src {
 dir = 'file:///mda/src'
}
conf {
 dir = 'file:///mda/conf'
}
...

build.gradle:

def workingDir = new File('.').canonicalFile
def configUri = "file:///mda/conf/andromda-business-gima.xml"
def mylibs = 'c:/_Tools/_Libs'
  def loadConfiguration() {
    def environment = hasProperty('env') ? env : 'dev'
    setProperty 'environment', environment
    def mavenFile = file('maven.groovy')
    def maven = new ConfigSlurper(environment).parse(mavenFile.toURL())
    setProperty 'maven', maven
}
  task mda(dependsOn: classes) << {
        def path = ant.path {
            fileset(dir: mylibs, includes: '*.jar')
        }
   println "configUri is [" + configUri + "]\n"
 println "maven.conf.dir is [" + maven.conf.dir + "]\n"
    ant.taskdef(name: "andromda", classname: "org.andromda.ant.task.AndroMDAGenTask", classpath: path)
  ant.andromda(configurationUri: configUri)
   }

andromda-business-gima.xml: (partially because very long)

<andromda>
 <properties>
  <property name="modelValidation">false</property>
  <property name="cartridgeFilter">java,hibernate,spring</property>
 </properties>
 <server>
  <host>127.0.0.1</host>
  <port>4446</port>
 </server>
 <repositories>
  <repository name="netBeansMDR">
   <models>
    <model>
     <uri>jar:file:@maven.src.dir@/uml/gima/com.thalesis.onegima.backend.xml.zip!/com.thalesis.onegima.backend.xml</uri>
     <uri>jar:file:@maven.src.dir@/uml/org.thales.one.atlas.backend.xml.zip!/org.thales.one.atlas.backend.xml</uri>
     <moduleSearchLocations>
      <location>@maven.repo.local@/andromda/xml.zips</location>
      <location>@maven.src.dir@/uml/common</location>
      <location>@maven.src.dir@/uml/common/signaletique</location>
      <location>@maven.src.dir@/uml</location>
      <location>@maven.src.dir@/uml/edd</location>
      <location>@maven.src.dir@/uml/gima</location>
     </moduleSearchLocations>
    </model>
   </models>
  </repository>
 </repositories>
        ...
        ...

I’m sure it should be simple but I don’t find any tutorial on how to inject properties in XML.

So my question is: How to replace properties in XML file ?

Thank’s for your response.

To detokenize a file, you can use a ‘Copy’ task or method together with a filter. In your case, the ‘ReplaceTokens’ filter is a natural fit. Have a look at the corresponding section in the user guide for the details.

Thank’s for your response Peter. Unfortunately, it hang for another problem now, I suspect a bug.

I changed many things in my project so I give you a new shot of all the files.

[my.config] file (java properties file)

maven.multiproject.type='pom'
maven.src.dir='file:///_Datas/coder/Prj_XXX/XXX-BUSINESS/mda/src'
maven.conf.dir='file:///_Datas/coder/Prj_XXX/XXX-BUSINESS/mda/conf'
  // Global Model
maven.andromda.globalmodel.uri='jar:file:@maven.src.dir@/uml/YYY-ASModel.xml.zip!/ATL-ASModel.xml'
  // CDV models
maven.andromda.activite.cdv.uri='jar:file:@maven.src.dir@/uml/org.thalesis.xxx.view.activite.cdv.xml.zip!/org.yyy.xxx.view.activite.cdv.xml'
maven.andromda.avances='jar:file:@maven.src.dir@/uml/org.thalesis.xxx.view.avances.xml.zip!/org.thalesis.yyyy.view.avances.xml'
...
...

[build.gradle]

...
        //load propertie file
 def props = new Properties();
 new File("my.config").withInputStream { props.load(it) }
 props.each({
   project.setProperty(it.key, it.value)
 } )
...
...
 project.copy {
  from 'conf'
  into 'build'
  include defaultMdaConfigFileName
  //expand(project.properties)
 ==> DOESN'T WORK ! Why ?
  //=> REPLACEMENT
  project.properties.each { key, value ->
   if(key.startsWith('maven.')) {
    println "Filtering token ["+key+"]"
    filter(ReplaceTokens, tokens: [key, value.replace('@maven.src.dir@',project.getProperty('maven.src.dir')).replace("'", "")])
     }
   }
 }
...

This will copy the file with a size of 0. Following the stacktrace

And the result of the build:

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':mda'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:71)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:48)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:34)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:41)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:42)
        at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:243)
        at org.gradle.execution.DefaultTaskGraphExecuter.executeTask(DefaultTaskGraphExecuter.java:192)
        at org.gradle.execution.DefaultTaskGraphExecuter.doExecute(DefaultTaskGraphExecuter.java:177)
        at org.gradle.execution.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:83)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:36)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)
        at org.gradle.execution.DefaultBuildExecuter.access$300(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:80)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:70)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:63)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:157)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:112)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:80)
        at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:42)
        at org.gradle.launcher.cli.RunBuildAction.execute(RunBuildAction.java:28)
        at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:32)
        at org.gradle.launcher.exec.ExceptionReportingAction.execute(ExceptionReportingAction.java:21)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:233)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLoggingAction.execute(CommandLineActionFactory.java:217)
        at org.gradle.launcher.Main.doAction(Main.java:48)
        at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:53)
        at org.gradle.launcher.exec.EntryPoint$1.execute(EntryPoint.java:51)
        at org.gradle.launcher.exec.Execution.execute(Execution.java:28)
        at org.gradle.launcher.exec.EntryPoint.run(EntryPoint.java:39)
        at org.gradle.launcher.Main.main(Main.java:39)
        at org.gradle.launcher.ProcessBootstrap.runNoExit(ProcessBootstrap.java:51)
        at org.gradle.launcher.ProcessBootstrap.run(ProcessBootstrap.java:33)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:24)
Caused by: org.gradle.api.GradleException: Could not copy file 'C:\_Datas\coder\Prj_XXX\XXX-BUSINESS\mda\conf\andromda-business-yyy2.xml' to 'C:
\_Datas\coder\Prj_XXX\XXX-BUSINESS\mda\build\andromda-business-yyy2.xml'.
        at org.gradle.api.internal.file.AbstractFileTreeElement.copyTo(AbstractFileTreeElement.java:65)
        at org.gradle.api.internal.file.copy.MappingCopySpecVisitor$FileVisitDetailsImpl.copyTo(MappingCopySpecVisitor.java:117)
        at org.gradle.api.internal.file.copy.FileCopySpecVisitor.copyFile(FileCopySpecVisitor.java:56)
        at org.gradle.api.internal.file.copy.FileCopySpecVisitor.visitFileOrDir(FileCopySpecVisitor.java:52)
        at org.gradle.api.internal.file.copy.FileCopySpecVisitor.visitFile(FileCopySpecVisitor.java:39)
        at org.gradle.api.internal.file.copy.NormalizingCopySpecVisitor.visitFile(NormalizingCopySpecVisitor.java:70)
        at org.gradle.api.internal.file.copy.MappingCopySpecVisitor.visitFile(MappingCopySpecVisitor.java:50)
        at org.gradle.api.internal.file.collections.DirectoryFileTree.walkDir(DirectoryFileTree.java:151)
        at org.gradle.api.internal.file.collections.DirectoryFileTree.visit(DirectoryFileTree.java:119)
        at org.gradle.api.internal.file.collections.FileTreeAdapter.visit(FileTreeAdapter.java:96)
        at org.gradle.api.internal.file.CompositeFileTree.visit(CompositeFileTree.java:54)
        at org.gradle.api.internal.file.copy.CopyActionImpl.execute(CopyActionImpl.java:63)
        at org.gradle.api.internal.file.DefaultFileOperations.copy(DefaultFileOperations.java:120)
        at org.gradle.api.internal.project.AbstractProject.copy(AbstractProject.java:807)
        at org.gradle.api.internal.file.FileOperations$copy.call(Unknown Source)
        at build_2e9dkpvq8q97lr19rkjkpvb09s$_run_closure3.doCall(C:\_Datas\coder\Prj_ONE\ONE-BUSINESS\mda\build.gradle:148)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:448)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:436)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:63)
        ... 37 more
Caused by: org.gradle.api.InvalidUserDataException: Error - Invalid filter specification for org.apache.tools.ant.filters.ReplaceTokens
        at org.gradle.api.internal.file.copy.FilterChain$1.transform(FilterChain.java:69)
        at org.gradle.api.internal.file.copy.FilterChain$1.transform(FilterChain.java:58)
        at org.gradle.api.internal.ChainingTransformer.transform(ChainingTransformer.java:37)
        at org.gradle.api.internal.file.copy.FilterChain.transform(FilterChain.java:39)
        at org.gradle.api.internal.file.copy.FilterChain.transform(FilterChain.java:46)
        at org.gradle.api.internal.file.copy.MappingCopySpecVisitor$FileVisitDetailsImpl.open(MappingCopySpecVisitor.java:101)
        at org.gradle.api.internal.file.AbstractFileTreeElement.copyTo(AbstractFileTreeElement.java:43)
        at org.gradle.api.internal.file.copy.MappingCopySpecVisitor$FileVisitDetailsImpl.copyTo(MappingCopySpecVisitor.java:109)
        at org.gradle.api.internal.file.AbstractFileTreeElement.copyFile(AbstractFileTreeElement.java:72)
        at org.gradle.api.internal.file.AbstractFileTreeElement.copyTo(AbstractFileTreeElement.java:60)
        ... 55 more
Caused by: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[maven.andromda.activite.cdv.uri, jar:file:file:///_
Datas/coder/Prj_XXX/XXX-BUSINESS/mda/src/uml/org.thalesis.xxx.view.activite.cdv.xml.zip!/org.thalesis.yyy.view.activite.cdv.xml]' with
class 'java.util.ArrayList' to class 'java.util.Hashtable' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: j
ava.util.Hashtable(java.lang.String, java.lang.String)
        at org.gradle.util.ReflectionUtil.setProperty(ReflectionUtil.groovy:31)
        at org.gradle.util.ConfigureUtil.configureByMap(ConfigureUtil.java:36)
        at org.gradle.api.internal.file.copy.FilterChain$1.transform(FilterChain.java:65)
        ... 64 more

Any idea ?

Regards.

I tried to replace the filter like this:

filter(ReplaceTokens, tokens: [key+":'"+value.replace('@maven.src.dir@',project.getProperty('maven.src.dir')).replace("'", "")+"'"])

but without success !

Caused by: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[maven.andromda.activite.cdv.uri: 'jar:file:///
_Datas/coder/Prj_XXX/XXX-BUSINESS/mda/src/uml/org.thalesis.yyy.view.activite.cdv.xml.zip!/org.thalesis.yyy.view.activite.cdv.xml']' wit
h class 'java.util.ArrayList' to class 'java.util.Hashtable' due to: groovy.lang.GroovyRuntimeException: Could not find matching constructor for:
 java.util.Hashtable(java.lang.String)
        at org.gradle.util.ReflectionUtil.setProperty(ReflectionUtil.groovy:31)
        at org.gradle.util.ConfigureUtil.configureByMap(ConfigureUtil.java:36)
        at org.gradle.api.internal.file.copy.FilterChain$1.transform(FilterChain.java:65)
        ... 64 more

It seems trying to make a Hashtable in place of ArrayList ! What’s wrong ?

There are multiple problems with your code, one of which is that you pass a list rather than a map after tokens:. Try this:

task detokenizeMdaConfig(type: Copy) {
  from "conf"
  into "build"
  include defaultMdaConfigFileName
  def props = new Properties();
  new File("my.config").withInputStream { props.load(it) }
  filter(ReplaceTokens, tokens: props)
}

Bingo ! I’m a little bit disappointed because there is so many examples very differents on internet that it’s difficult to choose the good one.

Thank’s a lot, Fonzy (alias SteF)