Return value when internally calling target with phing/phingcall - return-value

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>

Related

Junit 4test result parsing not able to find <failure> tag

here is my Junit test result.xml
I am able to get hold of testsuite and testcase nodes. Now I need to check if test case is failed.
I am using an approach where I check if testcase node has any child and then check if that child is failure node. But when I try to get hold of child node and its type, it returns only the TEXT_NODE and displays failure message text. How do I check if child node is failure?
<?xml version='1.0' encoding='UTF-8' ?>
<testsuite name="com.Test" tests="47" failures="1" errors="0" skipped="0" time="0.425" timestamp="2017-05-25T10:04:14" hostname="localhost">
<properties>
<property name="device" value="Nexus_6_API_22(AVD) - 5.1.1" />
<property name="flavor" value="DEV" />
<property name="project" value="test" />
</properties>
<testcase name="test_1" classname="com.Test" time="0.053" />
<testcase name="test_2" classname="com.Test" time="0.081" />
<testcase name="test_3" classname="com.Test" time="0.0" />
<testcase name="test_4" classname="com.Test" time="0.001">
<failure>junit.framework.ComparisonFailure: expected:<512[]> but was:<512[fed_]>
at junit.framework.Assert.assertEquals(Assert.java:85)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1853)
</failure>
</testcase>
</testsuite>
Well, I figured this out as below, posting for the benefit of others -
//Get a list of test cases with below code -
testCaseList = docElement.getElementsByTagName(TEST_CASE_TAG);
//Iterate through the list and set each item to testElement
// Get Test Case status
TestStatus testCaseStatus = TestStatus.FAILED;
if(testElement.hasChildNodes()) {
//Check if test failed ?
elems = getDirectChildsByTagName(testElement, TEST_FAILURE_TAG);
if(elems != null && elems.size()>0) {
logger.info("failed Tests :"+elems.size());
testCaseStatus = TtuTestStatus.FAILED;
}
//Check if test skipped ?
else {
elems = getDirectChildsByTagName(testElement, TEST_SKIPPED_TAG);
if(elems != null && elems.size()>0) {
logger.info("Skipped Tests :"+elems.size());
testCaseStatus = TtuTestStatus.SKIPPED;
}
}
}
else {
testCaseStatus = TtuTestStatus.PASSED;
}

Adding suffix to a list with foreach

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>

Integrate enunciate and ant for REST APIs document

I am encountering an error during integrating enunciate and ant for CXF REST service APIs project. Error exists in method getFeeItemsByCapID(). I try to find answer in source code, but without result. Who has any idea about the error? Thanks for your help. If you have any tips.
Ant Script
<path id="enunciate.classpath">
<fileset dir="${enunciate.home}/lib">
<include name="*.jar"/>
</fileset>
<!--include (optional) spring module-->
<fileset dir="${enunciate.home}/lib/modules/cxf">
<include name="*.jar"/>
</fileset>
<fileset dir="${java.home}">
<include name="lib/tools.jar"/>
</fileset>
</path>
<taskdef name="enunciate" classname="org.codehaus.enunciate.main.EnunciateTask">
<classpath refid="enunciate.classpath"/>
</taskdef>
<enunciate basedir="java/" configFile="enunciate.xml">
<include name="**/*.java"/>
<classpath refid="enunciate.classpath"/>
<export artifactId="war.file" destination="d:/myapp.war"/>
<javacArgument argument="-g"/>
</enunciate>
Enunciate.xml
<?xml version="1.0"?>
<enunciate label="test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
<namespaces>
<namespace id="api" uri="http://api.example.com/" />
<namespace id="link" uri="http://api.example.com/link" />
<namespace id="persona" uri="http://api.example.com/persona" />
</namespaces>
<modules>
<!-- Docs -->
<docs splashPackage="org.codehaus.enunciate.api" title="test" copyright="test.com"/>
<java-client disabled="false"/>
<amf disabled="true"/>
<c disabled="true"/>
<obj-c disabled="true"/>
<csharp disabled="true"/>
<spring-app disabled="false"/>
<cxf disabled="false"/>
<gwt disabled="true"/>
<jaxws-ri disabled="true"/>
<jersey disabled="true"/>
</modules>
Java Code
#GET
#RecordDetailSecurity(RecordDetailSectionType.FEE)
#Path("/{recordIds}/fees/")
#Produces(MediaType.APPLICATION_JSON)
#JsonView(Views.PublicView.class)
public ResponseModel getFeeItemsByCapID(#PathParam("recordIds") String recordIds,
#QueryParam("fields") #DefaultValue("") String fields) throws Exception
{
Exception:
java.lang.IllegalStateException: D:\AA7.2.0\main-dev\biz\modules\rest-apis\java\com\accela\restapis\jaxrs\agency\service\FeeWebService.java:76: the element 'value' must have a value specified.
at net.sf.jelly.apt.decorations.declaration.DecoratedAnnotationMirror.<init>(DecoratedAnnotationMirror.java:66)
at net.sf.jelly.apt.decorations.DeclarationDecorator.decorate(DeclarationDecorator.java:362)
at net.sf.jelly.apt.decorations.DeclarationDecorator.decorateAnnotationMirrors(DeclarationDecorator.java:113)
at net.sf.jelly.apt.decorations.declaration.DecoratedDeclaration.getAnnotationMirrors(DecoratedDeclaration.java:213)
at net.sf.jelly.apt.decorations.declaration.DecoratedDeclaration.getAnnotations(DecoratedDeclaration.java:195)
at net.sf.jelly.apt.decorations.declaration.DecoratedDeclaration.getAnnotation(DecoratedDeclaration.java:225)
at org.codehaus.enunciate.contract.jaxrs.ResourceMethod.<init>(ResourceMethod.java:130)
at org.codehaus.enunciate.contract.jaxrs.Resource.getResourceMethods(Resource.java:143)
at org.codehaus.enunciate.contract.jaxrs.Resource.<init>(Resource.java:69)
at org.codehaus.enunciate.contract.jaxrs.RootResource.<init>(RootResource.java:34)
at org.codehaus.enunciate.apt.EnunciateAnnotationProcessor.getRootModel(EnunciateAnnotationProcessor.java:214)
at org.codehaus.enunciate.apt.EnunciateAnnotationProcessor.process(EnunciateAnnotationProcessor.java:103)
at com.sun.mirror.apt.AnnotationProcessors$CompositeAnnotationProcessor.process(AnnotationProcessors.java:60)
at com.sun.tools.apt.comp.Apt.main(Apt.java:454)
at com.sun.tools.apt.main.JavaCompiler.compile(JavaCompiler.java:258)
at com.sun.tools.apt.main.Main.compile(Main.java:1102)
at com.sun.tools.apt.main.Main.compile(Main.java:964)
at com.sun.tools.apt.Main.processing(Main.java:95)
at com.sun.tools.apt.Main.process(Main.java:85)
at com.sun.tools.apt.Main.process(Main.java:67)
at org.codehaus.enunciate.main.Enunciate.invokeApt(Enunciate.java:777)
at org.codehaus.enunciate.main.Enunciate.doGenerate(Enunciate.java:366)
at org.codehaus.enunciate.main.Enunciate$Stepper.step(Enunciate.java:1735)
at org.codehaus.enunciate.main.Enunciate$Stepper.stepTo(Enunciate.java:1767)
at org.codehaus.enunciate.main.Enunciate.execute(Enunciate.java:174)
at org.codehaus.enunciate.main.EnunciateTask.execute(EnunciateTask.java:156)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.Main.runBuild(Main.java:758)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Source Code:
public DecoratedAnnotationMirror(AnnotationMirror delegate) {
if (delegate == null) {
throw new IllegalArgumentException("A delegate must be provided.");
}
this.delegate = delegate;
AnnotationType annotationType = delegate.getAnnotationType();
Collection<AnnotationTypeElementDeclaration> allElements = annotationType.getDeclaration() != null? annotationType.getDeclaration().getMethods() : Collections.<AnnotationTypeElementDeclaration>emptyList();
Map<AnnotationTypeElementDeclaration, AnnotationValue> elementValues = getElementValues();
put("annotationType", annotationType);
put("position", delegate.getPosition());
put("elementValues", elementValues);
allElementValues = new HashMap<String, Object>();
for (AnnotationTypeElementDeclaration element : allElements) {
if (elementValues.containsKey(element)) {
Object value = elementValues.get(element).getValue();
allElementValues.put(element.getSimpleName(), value);
put(element.getSimpleName(), value);
}
else {
AnnotationValue defaultValue = element.getDefaultValue();
if (defaultValue == null) {
throw new IllegalStateException(delegate.getPosition() + ": the element '" + element.getSimpleName() + "' must have a value specified.");
}
I have found root cause in my Customized Annotation. It seems because the annotation without default value. When I removed the customized annotation of method or append default value in annotation definition. the exception will be gone. But the annotation accept an enumeration, in business logic the annotation without default value. We always need to set enum value for using. But, why annotation always need default value? Anybody know the reason?
#Target( {ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface RecordDetailSecurity
{
RecordDetailSectionType value(); //append default value such as "default RecordDetailSectionType.ADDITIONAL_INFORMATION;"
}
#RecordDetailSecurity(RecordDetailSectionType.FEE)
public ResponseModel getFeeItemsByCapID(#PathParam("recordIds") String recordIds,
#QueryParam("fields") #DefaultValue("") String fields) throws Exception
About annotation default value error, I have created a sample project to try again. It works well. Now, I need to change my original opinion. It's my fault. :)
Firstly, my project compiling is successful without enunciate ant target before. However the enumeration "RecordDetailSectionType " belongs to another jar actually.
I didn't include the jar in to enunciate class path, so enunciate cannot to recognize the customized annotation type value. Sorry for the misunderstanding.

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.

Nant reading file in reverse order

I have a text file. I need to read the content of the file from the reverse order (from EOF). Please let me know how I can achieve it using Nant script.
Thanks,
Priya.R
You could write it in C# inside your NAnt script like this:
<target name="read">
<script language="C#" prefix="myprefix" >
<code>
<![CDATA[
[Function("reverse-lines")]
public static string ReverseLines( string s )
{
string[] lines = s.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
string result = "";
foreach (string line in lines)
{
result = line + "\r\n" + result;
}
return result;
}
]]>
</code>
</script>
<loadfile file="myfile.txt" property="contents" />
<echo message="File contents in correct order:" />
<echo message="${contents}" />
<echo message="File contents in reverse order:" />
<echo message="${myprefix::reverse-lines(contents)}" />
</target>
You could use the Windows program sort /R to create a sorted copy of the file.