Adding suffix to a list with foreach - phing

I am including a .properties file, which has a list of properties:
configuration.files = file1, file2
configuration.files.file1.source = config/filename1
configuration.files.file2.source = config/filename2
Now I need the paths for each file changed to something like this:
vendor/project/config/filename1
vendor/project/config/filename2
To achieve that, I tried to foreach this list and prepend that suffix and overriding the existing property:
<foreach list="${configuration.files}" target="_prepend-vendor-path" param="file" >
<property name="configuration.files.${file}.source" value="/vendor/project/${configuration.files.${file}.source}" override="true"/>
</foreach>
<target name="_prepend-vendor-path" >
<echo msg="${configuration.files.${file}.source}" />
</target>
This doesn't work and I can't figure out why. Is it even possible to use target names like ${suffix}.name ? If not, how could I achive my goal here?

I just did some workaround for this, writing out the properties and their values to a file and readin them after the loop has finished with override = true:
<target name="_prepend-vendor-path" >
<exec dir="${project.basedir}" command="echo configuration.files.${file}.source = /vendor/project/${configuration.files.${file}.source} >> ${project.temp.config}" passthru="true" checkreturn="true" />
</target>
and after the foreach simply:
<property file="${project.temp.config}" override="true"/>
For some reason the properties won't be overridden in the foreach and I just can't figgure out why, but this little trick made it for me.

You can suffix your property values from your file with the property task using a filterchain and a regular expression replacement:
<?xml version="1.0"?>
<project name="Phing Build Tests" default="append-custom-path" basedir=".">
<target name="append-custom-path">
<property file="prop.properties">
<filterchain>
<replaceregexp>
<regexp pattern="^(.*)" replace="vendor/project/$1"/>
</replaceregexp>
</filterchain>
</property>
<echo>${configuration.files.file1.source}</echo>
<echo>${configuration.files.file2.source}</echo>
</target>
</project>

Related

db2 execute triggers using ant script

I have an sql file containing triggers. I want to execute this file using Ant script:
<target name="exec-sql-proc_db2" depends="init">
<property name="project.sql.dir" value="${project.metadata.dir}/sql" />
<property name="triggerFile" value="${project.sql.dir}/triggers_db2.sql" />
<echo message="${triggerFile}" />
<sql rdbms="DB2" driver="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://localhost:50000/project:currentSchema=mySchema;"
userid="root" password="root"
classpath="C:\projects\myProject\lib\db2jcc.jar"
src="${triggerFile}"
onerror="${sql.onerror}"
keepformat="true" delimiter="/" />
</target>
I get build successful, but the triggers are not executed !
Is there any other solution?
my trigger is :
CREATE or REPLACE TRIGGER PRODUCT_HISTORY_AFTER_UPDATE
AFTER UPDATE ON PRODUCT
REFERENCING NEW AS N
FOR EACH ROW
BEGIN
INSERT INTO productHistory ( id_h, id_product , name) values (id_h_seq.nextval, N.id_product , N.name );
END
/
<sql rdbms="DB2" driver="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://localhost:50000/project:currentSchema=mySchema;"
userid="root" password="root"
classpath="C:\projects\myProject\lib\db2jcc.jar"
src="${triggerFile}"
onerror="${sql.onerror}"
delimiter="/" >
SET SCHEMA mySchema
</sql>
I tried this part of code, that solves my problem

does phing support arrays with keys and values?

In phing i can set this:
<property name="build.myArray" value="something1, something2, something3" />
And then retrieve each value like this:
<foreach list="${build.myArray}" param="replace.me" target="build:create-vhost" />
<target name="build:create-vhost">
<filterchain>
<replacetokens begintoken="#" endtoken="#">
<token key="REPLACE_ME" value="${replace.me}" />
</replacetokens>
</filterchain>
</target>
My question is can i do the same this but using array with keys and values?
Something like that:
<property name="build.myArray" value="myKey = something1, myKey2 => something2, myKey3 => something3" />
and use that key names later
Is is possible to do it?
No, you cannot use properties as array in phing.

Import all build files in a directory - phing

I need to include all xml files inside a directory (I dont know the name, and count of files) in my current build.xml using ImportTask.
This is my build.xml file:
<?xml version="1.0" encoding="utf-8"?>
<project name="New Project" basedir="." default="myimport">
<target name="myimport" description="dummy to import other build files">
<if>
<isset property="file" />
<then>
<echo msg="Importing ${file}" />
<import file="${file}" />
</then>
</if>
</target>
<if>
<not>
<isset property="dummy.property" />
</not>
<then>
<echo msg="Now include all files in ./dev/build directory" />
<property name="dummy.property" value="true" />
<foreach param="msg" absparam="file" target="myimport">
<fileset dir="./dev/build/">
<include name="*.xml"/>
</fileset>
</foreach>
</then>
</if>
</project>
and an example file in target directory:
<?xml version="1.0" encoding="utf-8"?>
<project name="test" basedir="." default="dummy">
<target name="dummy" description="Dummy task">
<echo msg="Dummy task, just for test" />
</target>
<echo msg="Imported!" />
</project>
when I run phing -l the result is:
Buildfile: /home/f0rud/workspace/s/build.xml
[echo] Now include all files in ./dev/build directory
[foreach] Calling Buildfile '/home/f0rud/workspace/s/build.xml' with target 'myimport'
New Project > myimport:
[echo] Importing ./dev/build/test.xml
[echo] Imported!
Default target:
----------------------------------------------------------------------------
myimport dummy to import other build files
Main targets:
----------------------------------------------------------------------------
myimport dummy to import other build files
But there is no dummy (or test.dummy) target, why?
Note : There is a funny bug, if I remove the if part, I get Maximum function nesting level of '100' reached, aborting! error but thats not my problem (the if solve that problem.)
The problem is import work on global context.
When I call it inside a target, its not available in global context.
So I've written a simple Phing task to load all files of a fileset like so:
class ImportDirTask extends Task {
/** Array of filesets */
private $filesets = array();
/**
* Nested creator, adds a set of files (nested fileset attribute).
*/
function createFileSet() {
$num = array_push($this->filesets, new FileSet());
return $this->filesets[$num-1];
}
/**
* Parse a Phing build file and copy the properties, tasks, data types and
* targets it defines into the current project.
*
* #return void
*/
public function main () {
// filesets
foreach ($this->filesets as $fs) {
$ds = $fs->getDirectoryScanner($this->project);
$srcFiles = $ds->getIncludedFiles();
$srcDirs = $ds->getIncludedDirectories();
foreach ($srcFiles as $f)
{
$task = new ImportTask();
$task->setProject($this->project);
$task->init();
$task->setFile($this->file = $fs->getDir($this->project) . FileSystem::getFileSystem()->getSeparator() . $f);
$task->main();
}
}
} //end main
} //end ImportDirTask
It just work.

how to integrate junit in gwt project with the ant build file

I have a gwt project, and i want to do the unit test in my project, so i add a target of junit in the ant build file. But the build always fails,
BUILD FAILED C:\SG\workspace\app\build.xml:78: The for must include junit.jar if not in Ant's own classpath
here is the scripts
<target name="test" depends="clean.test,gwtc" description="run all Junit tests">
<mkdir dir ="test/test"/>
**<junit fork = "false" printsummary = "yes"/>** <!-- the line 78-->
<classpath refid = "project.class.path"/>
<batchtest todir = "test/test">
<fileset dir = "test" includes="**/${test}Test.java"/>
</batchtest>
<formatter type = "xml"/>
<junitreport toDir = "test/test">
<fileset dir = "test/test"/>
<report format="frames" todir="test"/>
</junitreport>
<exec os="window" executable="cmd.exe">
<arg line="-a /Applications/Safari.app test/index.html"/>
</exec>
</target>
You closed the <junit /> tag too early.
This is correct. classpath, batchtest and formatter have to be inside the junit Tag:
<junit fork = "false" printsummary = "yes">
<classpath refid = "project.class.path"/>
<batchtest todir = "test/test">
<fileset dir = "test" includes="**/${test}Test.java"/>
</batchtest>
<formatter type = "xml"/>
</junit>
And you have to make sure that junit.jar is either in ANT_HOME/lib, referenced in project.class.path or added as another classpath like <classpath refid = "junit.class.path"/>.

Return value when internally calling target with phing/phingcall

I am calling a target by means of phingcall command.
I want to pass back a status variable from the called target or at least change the existing value from the calling target.
Goal: I want to branch in my main target controlling logic if the sub target fails which I indicate with a property.
The code below does not work. Any idea how to make it work or an altertive approach for my goal?
Thanks,
Juergen
<target name="main">
<echo>target a</echo>
<echo>${bOk}</echo>
<exec command="echo 1" outputProperty="bOk" />
<echo>bOk is 1: ${bOk}</echo>
<phingcall inheritRefs="true" target="sub">
</phingcall>
<echo>bOk should now be 0: ${bOk}</echo>
</target>
<target name="sub">
<echo>target b</echo>
<echo>bOk is 1: ${bOk}</echo>
<exec command="echo 0" outputProperty="bOk" />
<echo>bOk now is 0: ${bOk}</echo>
</target>
The problem here is that
<echo>bOk should now be 0: ${bOk}</echo>
echos
bOk should now be 0: 1
Even with the great help of #phing IRC I couldn't solve the problem.
I decided to write a custom task to account for data passing between targets:
<?php
require_once "phing/Task.php";
class rvGlobalTask extends Task {
private static $bOk = 1;
private $sMode = null;
private $bValue = null;
private $outputProperty = null;
public function setSMode( $sMode ) {
$this->sMode = $sMode;
}
public function setBValue( $bValue ) {
$this->bValue = $bValue;
}
public function setOutputProperty( $outputProperty ) {
$this->outputProperty = $outputProperty;
}
public function main() {
if ( $this->sMode == "set" ) {
rvGlobalTask::$bOk = $this->bValue;
} else {
$this->project->setProperty(
$this->outputProperty,
rvGlobalTask::$bOk
);
}
}
}
?>
This works fine for my problem. Perhaps someone else finds this useful as well.
Here's how you use an ExecTask to capture output.
<?xml version="1.0" encoding="UTF-8"?>
<project name="example" default="check-composer">
<!-- set a property to contain the output -->
<property name="whichComposer" value="" />
<!-- check if composer (getcomposer.org) is installed globally -->
<target name="check-composer">
<!-- put the output of "which" in our property -->
<exec command="which composer" outputProperty="whichComposer" />
<!-- act on what we found out -->
<if>
<contains string="${whichComposer}" substring="composer" />
<then>
<echo>Composer installed at ${whichComposer}</echo>
</then>
<else>
<echo message="better install composer. ${whichComposer}"/>
</else>
</if>
</target>
</project>