]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Introduce org.argeo.slc.lib.detached
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 22 Nov 2008 12:07:45 +0000 (12:07 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 22 Nov 2008 12:07:45 +0000 (12:07 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@1850 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

68 files changed:
runtime/org.argeo.slc.lib.detached/.classpath [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/.project [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/build.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/pom.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/assembly/base.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/base/bin/slc [new file with mode: 0755]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml [new file with mode: 0644]
runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml [new file with mode: 0644]

diff --git a/runtime/org.argeo.slc.lib.detached/.classpath b/runtime/org.argeo.slc.lib.detached/.classpath
new file mode 100644 (file)
index 0000000..9653ef0
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" output="target/classes" path="src/main/java"/>\r
+       <classpathentry kind="src" output="target/classes" path="src/main/resources"/>\r
+       <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>\r
+       <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>\r
+       <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>\r
+       <classpathentry kind="output" path="target/classes"/>\r
+</classpath>\r
diff --git a/runtime/org.argeo.slc.lib.detached/.project b/runtime/org.argeo.slc.lib.detached/.project
new file mode 100644 (file)
index 0000000..f874c09
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.slc.agent</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.maven.ide.eclipse.maven2Builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.maven.ide.eclipse.maven2Nature</nature>
+       </natures>
+</projectDescription>
diff --git a/runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs b/runtime/org.argeo.slc.lib.detached/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..964778b
--- /dev/null
@@ -0,0 +1,12 @@
+#Fri Aug 29 11:31:46 CEST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/runtime/org.argeo.slc.lib.detached/build.xml b/runtime/org.argeo.slc.lib.detached/build.xml
new file mode 100644 (file)
index 0000000..4213f1d
--- /dev/null
@@ -0,0 +1,35 @@
+<project xmlns:artifact="urn:maven-artifact-ant" default="deploy">\r
+\r
+       <path id="maven-ant-tasks.classpath"\r
+             path="D:\dev\tools\maven-2.0.7\lib\maven-ant-tasks-2.0.7.jar" />\r
+       <typedef resource="org/apache/maven/artifact/ant/antlib.xml"\r
+                uri="urn:maven-artifact-ant"\r
+                classpathref="maven-ant-tasks.classpath" />\r
+\r
+       <property name="local" location="D:/dev/mavenLocal/" />\r
+       <property name="local.argeo" location="${local}/org/argeo/slc/" />\r
+       <property name="repo.argeo"\r
+                 value="file:///D:/dev/test/mavenArgeoLocalRep/" />\r
+\r
+       <target name="deploy">\r
+               <deploy artifact="argeo-slc-core" version="0.6.0" />\r
+       </target>\r
+\r
+       <!-- Macrodefs -->\r
+       <macrodef name="deploy">\r
+               <attribute name="artifact" />\r
+               <attribute name="version" />\r
+               <sequential>\r
+                       <artifact:install-provider artifactId="wagon-file"\r
+                                                  version="1.0-beta-2" />\r
+                       <artifact:deploy file="${local.argeo}/@{artifact}/@{version}/@{artifact}-@{version}.jar">\r
+                               <artifact:pom file="pom.xml" />\r
+                               <remoterepository url="${repo.argeo}" />\r
+                               <attach classifier="sources"\r
+                                       file="${local.argeo}/@{artifact}/@{version}/@{artifact}-@{version}-sources.jar" />\r
+                               <attach classifier="javadoc"\r
+                                       file="${local.argeo}/@{artifact}/@{version}/@{artifact}-@{version}-javadoc.jar" />\r
+                       </artifact:deploy>\r
+               </sequential>\r
+       </macrodef>\r
+</project>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/pom.xml b/runtime/org.argeo.slc.lib.detached/pom.xml
new file mode 100644 (file)
index 0000000..3965981
--- /dev/null
@@ -0,0 +1,135 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.slc</groupId>
+               <artifactId>argeo-slc</artifactId>
+               <version>0.11.2-SNAPSHOT</version>
+               <relativePath>../org.argeo.slc</relativePath>
+       </parent>
+       <artifactId>org.argeo.slc.agent</artifactId>
+       <packaging>jar</packaging>
+       <name>Argeo SLC Agent</name>
+       <scm>
+               <connection>
+                       scm:svn:https://www.argeo.org/svn/slc/trunk/org.argeo.slc.agent
+               </connection>
+               <url>
+                       https://www.argeo.org/svn/slc/trunk/org.argeo.slc.agent
+               </url>
+       </scm>
+       <build>
+               <plugins>
+                       <!-- Look to parent pom for inheritances -->
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-source-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-surefire-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-assembly-plugin</artifactId>
+                               <configuration>
+                                       <descriptors>
+                                               <descriptor>src/assembly/base.xml</descriptor>
+                                       </descriptors>
+                               </configuration>
+                               <executions>
+                                       <execution>
+                                               <id>assembly-base</id>
+                                               <phase>package</phase>
+                                               <goals>
+                                                       <goal>single</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <configuration>
+                                       <instructions>
+                                               <Export-Package>
+                                                       org.argeo.slc.*
+                                               </Export-Package>
+                                               <Import-Package>*,org.argeo.slc.core.test.spring,org.apache.commons.cli;resolution:=optional</Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+       <dependencies>
+               <dependency>
+                       <groupId>org.argeo.slc</groupId>
+                       <artifactId>org.argeo.slc.core</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.argeo.slc</groupId>
+                       <artifactId>org.argeo.slc.detached</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.springframework.ws</groupId>
+                       <artifactId>org.springframework.ws</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>javax.xml.soap</groupId>
+                       <artifactId>com.springsource.javax.xml.soap</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>com.sun.xml</groupId>
+                       <artifactId>
+                               com.springsource.com.sun.xml.messaging.saaj
+                       </artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.argeo.dep.osgi</groupId>
+                       <artifactId>org.argeo.dep.osgi.ant</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.commons</groupId>
+                       <artifactId>com.springsource.org.apache.commons.net</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.oro</groupId>
+                       <artifactId>com.springsource.org.apache.oro</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.bsf</groupId>
+                       <artifactId>com.springsource.org.apache.bsf</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.beanshell</groupId>
+                       <artifactId>com.springsource.bsh</artifactId>
+               </dependency>
+
+               <!--
+                       <dependency> <groupId>org.apache.maven</groupId>
+                       <artifactId>maven-embedder</artifactId> </dependency> <dependency>
+                       <groupId>org.apache.maven</groupId>
+                       <artifactId>maven-settings</artifactId> </dependency>
+               -->
+               <dependency>
+                       <groupId>org.argeo.dep.osgi</groupId>
+                       <artifactId>org.argeo.dep.osgi.commons.cli</artifactId>
+               </dependency>
+
+       </dependencies>
+</project>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/assembly/base.xml b/runtime/org.argeo.slc.lib.detached/src/assembly/base.xml
new file mode 100644 (file)
index 0000000..aef97a5
--- /dev/null
@@ -0,0 +1,16 @@
+<assembly xmlns="http://maven.apache.org/POM/4.0.0"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/assembly-1.1.0-SNAPSHOT.xsd">
+       <id>base</id>
+       <includeBaseDirectory>false</includeBaseDirectory>
+       <formats>
+               <format>tar.gz</format>
+       </formats>
+       <fileSets>
+               <fileSet>
+                       <directory>src/base</directory>
+                       <outputDirectory></outputDirectory>
+                       <fileMode>0755</fileMode>
+               </fileSet>
+       </fileSets>
+</assembly>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/base/bin/slc b/runtime/org.argeo.slc.lib.detached/src/base/bin/slc
new file mode 100755 (executable)
index 0000000..ca8ef49
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Find home
+if [ -z "$ARGEO_SLC_HOME" -o ! -d "$ARGEO_SLC_HOME" ] ; then
+  ## resolve links - $0 may be a link to home
+  PRG="$0"
+  progname=`basename "$0"`
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+    PRG="$link"
+    else
+    PRG=`dirname "$PRG"`"/$link"
+    fi
+  done
+
+  ARGEO_SLC_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  ARGEO_SLC_HOME=`cd "$ARGEO_SLC_HOME" && pwd`
+fi
+
+echo ARGEO_SLC_HOME=$ARGEO_SLC_HOME
+
+for i in "${ARGEO_SLC_HOME}"/lib/*.jar
+       do
+       CLASSPATH="$CLASSPATH:$i"
+       done
+
+#echo CLASSPATH=$CLASSPATH
+
+java -cp $CLASSPATH org.argeo.slc.cli.SlcMain "$@"
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntConstants.java
new file mode 100644 (file)
index 0000000..f89742d
--- /dev/null
@@ -0,0 +1,47 @@
+package org.argeo.slc.ant;
+
+public interface AntConstants {
+       // ANT
+       /** The Ant reference to the Spring application context used. */
+       public static final String REF_ROOT_CONTEXT = "slcApplicationContext";
+       /** The Ant reference to the SLC structure registry used. */
+       public static final String REF_STRUCTURE_REGISTRY = "slcStructureRegistry";
+       /** The Ant reference to the <code>TreePath</code> of the current project */
+       public static final String REF_PROJECT_PATH = "slcProjectPath";
+       /**
+        * Resource path to the property file listing the SLC specific Ant tasks:
+        * /org/argeo/slc/ant/taskdefs.properties
+        */
+       public static final String SLC_TASKDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/taskdefs.properties";
+       /**
+        * Resource path to the property file listing the SLC specific Ant types:
+        * /org/argeo/slc/ant/typedefs.properties
+        */
+       public static final String SLC_TYPEDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/typedefs.properties";
+       public static final String REF_SLC_EXECUTION = "slcExecution";
+
+       // SLC EXECUTION
+       public static final String EXECTYPE_ANT = "org.apache.tools.ant";
+       public static final String EXECTYPE_SLC_ANT = "org.argeo.slc.ant";
+
+       public final static String EXECATTR_RUNTIME = "slc.runtime";
+       public final static String EXECATTR_ANT_FILE = "ant.file";
+       public final static String EXECATTR_ANT_TARGETS = "ant.targets";
+
+       // PROPERTIES
+       /** Property for the root dir (SLC root property file). */
+       public final static String ROOT_DIR_PROPERTY = "slc.rootDir";
+       /** Property for the conf dir (SLC root property file). */
+       public final static String CONF_DIR_PROPERTY = "slc.confDir";
+       /** Property for the work dir (SLC root property file). */
+       public final static String WORK_DIR_PROPERTY = "slc.workDir";
+       /** Name of the Spring bean used by default */
+       public final static String DEFAULT_TEST_RUN_PROPERTY = "slc.defaultTestRun";
+
+       /** Property for the runtime to use. */
+       public final static String RUNTIME_PROPERTY = "slc.runtime";
+
+       // LOG4J
+       public final static String MDC_ANT_PROJECT = "slc.ant.project";
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntExecutionContext.java
new file mode 100644 (file)
index 0000000..75bfd34
--- /dev/null
@@ -0,0 +1,33 @@
+package org.argeo.slc.ant;
+
+import org.apache.tools.ant.Project;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.runtime.SlcExecutionContext;
+import org.springframework.context.ApplicationContext;
+
+public class AntExecutionContext implements SlcExecutionContext {
+       private final Project project;
+
+       public AntExecutionContext(Project project) {
+               this.project = project;
+       }
+
+       public <T> T getBean(String name) {
+               ApplicationContext context = (ApplicationContext) project
+                               .getReference(AntConstants.REF_ROOT_CONTEXT);
+               return (T) context.getBean(name);
+       }
+
+       public <T> T getAntRef(String antId) {
+               return (T) project.getReference(antId);
+       }
+
+       public SlcExecution getSlcExecution() {
+               return (SlcExecution) project
+                               .getReference(AntConstants.REF_SLC_EXECUTION);
+       }
+
+       public Project getProject() {
+               return project;
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntRunner.java
new file mode 100644 (file)
index 0000000..1adb210
--- /dev/null
@@ -0,0 +1,91 @@
+package org.argeo.slc.ant;\r
+\r
+import java.io.File;\r
+import java.net.URL;\r
+import java.util.Arrays;\r
+import java.util.Map;\r
+import java.util.Properties;\r
+import java.util.Vector;\r
+\r
+import org.apache.tools.ant.Project;\r
+import org.apache.tools.ant.ProjectHelper;\r
+import org.apache.tools.ant.helper.ProjectHelper2;\r
+import org.argeo.slc.core.SlcException;\r
+\r
+/** Run regular Ant script (that is, not SLC instrumented) */\r
+public class AntRunner {\r
+       private URL buildFile;\r
+       private String[] targets;\r
+       private Properties properties;\r
+\r
+       public AntRunner() {\r
+\r
+       }\r
+\r
+       public AntRunner(URL buildFile, String target, Properties properties) {\r
+               this(buildFile, new String[] { target }, properties);\r
+       }\r
+\r
+       public AntRunner(URL buildFile, String[] targets, Properties properties) {\r
+               this.buildFile = buildFile;\r
+               this.targets = targets;\r
+               this.properties = properties;\r
+       }\r
+\r
+       public void run() {\r
+               Project p = new Project();\r
+\r
+               String path = buildFile.getFile();\r
+               p.setUserProperty("ant.file", path);\r
+               p.setBaseDir(extractBaseDir(path));\r
+\r
+               p.init();\r
+               ProjectHelper projectHelper = new ProjectHelper2();\r
+               p.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, projectHelper);\r
+               projectHelper.parse(p, buildFile);\r
+\r
+               if (properties != null) {\r
+                       for (Map.Entry<Object, Object> entry : properties.entrySet()) {\r
+                               p.setUserProperty(entry.getKey().toString(), entry.getValue()\r
+                                               .toString());\r
+                       }\r
+               }\r
+\r
+               p.fireBuildStarted();\r
+               Throwable exception = null;\r
+               try {\r
+                       if (targets == null) {\r
+                               p.executeTarget(p.getDefaultTarget());\r
+                       } else {\r
+                               p.executeTargets(new Vector<String>(Arrays.asList(targets)));\r
+                       }\r
+               } catch (Throwable e) {\r
+                       exception = e;\r
+                       throw new SlcException("Could not run Ant script " + buildFile, e);\r
+               } finally {\r
+                       p.fireBuildFinished(exception);\r
+               }\r
+\r
+       }\r
+\r
+       private File extractBaseDir(String path) {\r
+               String baseDir = null;\r
+               if (path.length() > 1) {\r
+                       int indx = path.lastIndexOf('/', path.length() - 1);\r
+                       if (indx == -1 || indx == 0) {\r
+                               baseDir = "/";\r
+                       } else {\r
+                               baseDir = path.substring(0, indx) + "/";\r
+                       }\r
+               } else {\r
+                       baseDir = "/";\r
+               }\r
+               File file = new File(baseDir);\r
+               if (file.exists()) {\r
+                       return file;\r
+               } else {\r
+                       return new File(System.getProperty("user.dir"));\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/AntSlcApplication.java
new file mode 100644 (file)
index 0000000..410098d
--- /dev/null
@@ -0,0 +1,424 @@
+package org.argeo.slc.ant;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.Appender;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.MDC;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.core.structure.SimpleSElement;
+import org.argeo.slc.core.structure.StructureRegistry;
+import org.argeo.slc.core.structure.tree.TreeSPath;
+import org.argeo.slc.core.structure.tree.TreeSRegistry;
+import org.argeo.slc.logging.Log4jUtils;
+import org.argeo.slc.runtime.SlcExecutionOutput;
+import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.SystemPropertyUtils;
+
+public class AntSlcApplication {
+       private final static String DEFAULT_APP_LOG4J_PROPERTIES = "org/argeo/slc/ant/defaultAppLog4j.properties";
+
+       private final static Log log = LogFactory.getLog(AntSlcApplication.class);
+
+       private Resource contextLocation;
+       private ConfigurableApplicationContext parentContext;
+
+       private Resource rootDir;
+       private Resource confDir;
+       private File workDir;
+
+       public void execute(SlcExecution slcExecution, Properties properties,
+                       Map<String, Object> references,
+                       SlcExecutionOutput<AntExecutionContext> executionOutput) {
+
+               // Properties and application logging initialization
+               initSystemProperties(properties);
+               Log4jUtils.initLog4j("classpath:" + DEFAULT_APP_LOG4J_PROPERTIES);
+
+               log.info("\n###\n### Start SLC execution " + slcExecution.getUuid()
+                               + "\n###\n");
+               if (log.isDebugEnabled()) {
+                       log.debug("rootDir=" + rootDir);
+                       log.debug("confDir=" + confDir);
+                       log.debug("workDir=" + workDir);
+               }
+
+               // Ant coordinates
+               String scriptRelativePath = findAntScript(slcExecution);
+               List<String> targets = findAntTargets(slcExecution);
+
+               // Spring initialization
+               ConfigurableApplicationContext ctx = createExecutionContext(slcExecution);
+
+               // Ant project initialization
+               Project project = new Project();
+               AntExecutionContext executionContext = new AntExecutionContext(project);
+               project.addReference(AntConstants.REF_ROOT_CONTEXT, ctx);
+               project.addReference(AntConstants.REF_SLC_EXECUTION, slcExecution);
+
+               try {
+                       initProject(project, properties, references);
+                       parseProject(project, scriptRelativePath);
+
+                       // Execute project
+                       initStructure(project, scriptRelativePath);
+                       runProject(project, targets);
+
+                       if (executionOutput != null)
+                               executionOutput.postExecution(executionContext);
+               } finally {
+                       ctx.close();
+               }
+       }
+
+       protected void initSystemProperties(Properties userProperties) {
+               // Set user properties as system properties so that Spring can access
+               // them
+               if (userProperties != null) {
+                       for (Object key : userProperties.keySet()) {
+                               System.setProperty(key.toString(), userProperties
+                                               .getProperty(key.toString()));
+                       }
+               }
+
+               if (System.getProperty(AntConstants.DEFAULT_TEST_RUN_PROPERTY) == null) {
+                       System.setProperty(AntConstants.DEFAULT_TEST_RUN_PROPERTY,
+                                       "defaultTestRun");
+               }
+
+               try {
+                       if (rootDir != null)
+                               setSystemPropertyForRes(AntConstants.ROOT_DIR_PROPERTY, rootDir);
+                       if (confDir != null)
+                               setSystemPropertyForRes(AntConstants.CONF_DIR_PROPERTY, confDir);
+                       if (workDir != null)
+                               System.setProperty(AntConstants.WORK_DIR_PROPERTY, workDir
+                                               .getCanonicalPath());
+
+                       // Additional properties in slc.properties file. Already set sytem
+                       // properties (such as the various directories) can be resolved in
+                       // placeholders.
+                       if (confDir != null) {
+                               Resource slcPropertiesRes = confDir
+                                               .createRelative("slc.properties");
+                               if (slcPropertiesRes.exists()) {
+                                       Properties slcProperties = new Properties();
+                                       InputStream in = slcPropertiesRes.getInputStream();
+                                       try {
+                                               slcProperties.load(in);
+                                       } finally {
+                                               IOUtils.closeQuietly(in);
+                                       }
+
+                                       for (Object obj : slcProperties.keySet()) {
+                                               String key = obj.toString();
+                                               if (!System.getProperties().containsKey(key)) {
+                                                       String value = SystemPropertyUtils
+                                                                       .resolvePlaceholders(slcProperties
+                                                                                       .getProperty(key));
+                                                       System.setProperty(key, value);
+                                               }
+                                       }
+                               }
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot init system properties.", e);
+               }
+       }
+
+       /**
+        * Set property as an absolute file path if the resource can be located on
+        * the file system, or as an url.
+        */
+       private void setSystemPropertyForRes(String key, Resource res)
+                       throws IOException {
+               String value = null;
+               try {
+                       value = res.getFile().getCanonicalPath();
+               } catch (IOException e) {
+                       value = res.getURL().toString();
+               }
+               System.setProperty(key, value);
+       }
+
+       protected ConfigurableApplicationContext createExecutionContext(
+                       SlcExecution slcExecution) {
+               try {
+
+                       // Find runtime definition
+                       Resource runtimeRes = null;
+                       String runtimeStr = slcExecution.getAttributes().get(
+                                       AntConstants.EXECATTR_RUNTIME);
+                       if (runtimeStr == null)
+                               runtimeStr = System.getProperty(AntConstants.RUNTIME_PROPERTY,
+                                               "default");
+
+                       ResourceLoader rl = new DefaultResourceLoader(getClass()
+                                       .getClassLoader());
+                       try {// tries absolute reference
+                               runtimeRes = rl.getResource(runtimeStr);
+                       } catch (Exception e) {
+                               // silent
+                       }
+                       if (runtimeRes == null || !runtimeRes.exists()) {
+                               if (confDir != null)
+                                       runtimeRes = confDir.createRelative("runtime/" + runtimeStr
+                                                       + ".xml");
+                       }
+
+                       // Find runtime independent application context definition
+                       if (confDir != null && contextLocation == null) {
+                               contextLocation = confDir
+                                               .createRelative("applicationContext.xml");
+                       }
+
+                       GenericApplicationContext ctx = new GenericApplicationContext(
+                                       parentContext);
+                       ctx.setDisplayName("SLC Execution #" + slcExecution.getUuid());
+
+                       XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
+                       if (runtimeRes != null && runtimeRes.exists())
+                               xmlReader.loadBeanDefinitions(runtimeRes);
+                       else
+                               log.warn("No runtime context defined");
+
+                       if (contextLocation != null && contextLocation.exists())
+                               xmlReader.loadBeanDefinitions(contextLocation);
+                       else
+                               log.warn("No runtime independent application context defined");
+
+                       // Add property place holder
+                       PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
+                       ppc.setIgnoreUnresolvablePlaceholders(true);
+                       ctx.addBeanFactoryPostProcessor(ppc);
+
+                       ctx.refresh();
+                       return ctx;
+               } catch (Exception e) {
+                       throw new SlcException(
+                                       "Cannot create SLC execution application context.", e);
+               }
+       }
+
+       protected String findAntScript(SlcExecution slcExecution) {
+               String scriptStr = slcExecution.getAttributes().get(
+                               AntConstants.EXECATTR_ANT_FILE);
+               if (scriptStr == null)
+                       throw new SlcException("No Ant script provided");
+
+               return scriptStr;
+       }
+
+       protected List<String> findAntTargets(SlcExecution slcExecution) {
+               String targetList = slcExecution.getAttributes().get(
+                               AntConstants.EXECATTR_ANT_TARGETS);
+               List<String> targets = new Vector<String>();
+               if (targetList != null) {
+                       StringTokenizer stTargets = new StringTokenizer(targetList, ",");
+                       while (stTargets.hasMoreTokens()) {
+                               targets.add(stTargets.nextToken());
+                       }
+               }
+               return targets;
+       }
+
+       protected void initProject(Project project, Properties properties,
+                       Map<String, Object> references) {
+               if (properties != null) {
+                       for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+                               project.setUserProperty(entry.getKey().toString(), entry
+                                               .getValue().toString());
+                       }
+               }
+
+               if (references != null) {
+                       for (Map.Entry<String, Object> entry : references.entrySet()) {
+                               project.addReference(entry.getKey(), entry.getValue());
+                       }
+               }
+
+               //project.addBuildListener(new CommonsLoggingListener());
+
+               ListableBeanFactory context = (ListableBeanFactory) project
+                               .getReference(AntConstants.REF_ROOT_CONTEXT);
+               // Register build listeners
+               Map<String, BuildListener> listeners = BeanFactoryUtils
+                               .beansOfTypeIncludingAncestors(context, BuildListener.class,
+                                               false, false);
+               for (BuildListener listener : listeners.values()) {
+                       project.addBuildListener(listener);
+               }
+
+               // Register log4j appenders from context
+               MDC.put(AntConstants.MDC_ANT_PROJECT, project);
+               Map<String, Appender> appenders = context.getBeansOfType(
+                               Appender.class, false, true);
+               for (Appender appender : appenders.values()) {
+                       LogManager.getRootLogger().addAppender(appender);
+               }
+
+               project.init();
+               addCustomTaskAndTypes(project);
+       }
+
+       /** Loads the SLC specific Ant tasks. */
+       protected void addCustomTaskAndTypes(Project project) {
+               Properties taskdefs = getDefs(project,
+                               AntConstants.SLC_TASKDEFS_RESOURCE_PATH);
+               for (Object o : taskdefs.keySet()) {
+                       String name = o.toString();
+                       try {
+                               project.addTaskDefinition(name, Class.forName(taskdefs
+                                               .getProperty(name)));
+                       } catch (ClassNotFoundException e) {
+                               log.error("Unknown class for task " + name, e);
+                       }
+               }
+               Properties typedefs = getDefs(project,
+                               AntConstants.SLC_TYPEDEFS_RESOURCE_PATH);
+               for (Object o : typedefs.keySet()) {
+                       String name = o.toString();
+                       try {
+                               project.addDataTypeDefinition(name, Class.forName(typedefs
+                                               .getProperty(name)));
+                       } catch (ClassNotFoundException e) {
+                               log.error("Unknown class for type " + name, e);
+                       }
+               }
+       }
+
+       private Properties getDefs(Project project, String path) {
+               Properties defs = new Properties();
+               try {
+                       InputStream in = project.getClass().getResourceAsStream(path);
+                       defs.load(in);
+                       in.close();
+               } catch (IOException e) {
+                       throw new SlcException("Cannot load task definitions", e);
+               }
+               return defs;
+       }
+
+       protected void initStructure(Project project, String scriptRelativePath) {
+               // Init structure registry
+               StructureRegistry<TreeSPath> registry = new TreeSRegistry();
+               project.addReference(AntConstants.REF_STRUCTURE_REGISTRY, registry);
+
+               // Lowest levels
+               StringTokenizer st = new StringTokenizer(scriptRelativePath, "/");
+               TreeSPath currPath = null;
+               while (st.hasMoreTokens()) {
+                       String name = st.nextToken();
+                       if (currPath == null) {
+                               currPath = TreeSPath.createRootPath(name);
+                       } else {
+                               if (st.hasMoreTokens())// don't register project file
+                                       currPath = currPath.createChild(name);
+                       }
+                       registry.register(currPath, new SimpleSElement(name));
+               }
+
+               // Project level
+               String projectName = project.getName() != null
+                               && !project.getName().equals("") ? project.getName()
+                               : "project";
+               TreeSPath projectPath = currPath.createChild(projectName);
+
+               String projectDesc = project.getDescription() != null
+                               && !project.getDescription().equals("") ? project
+                               .getDescription() : projectPath.getName();
+
+               registry.register(projectPath, new SimpleSElement(projectDesc));
+               project.addReference(AntConstants.REF_PROJECT_PATH, projectPath);
+
+               if (log.isDebugEnabled())
+                       log.debug("Project path: " + projectPath);
+       }
+
+       protected void parseProject(Project project, String scriptRelativePath) {
+               try {
+                       Resource script = rootDir.createRelative(scriptRelativePath);
+                       File baseDir = null;
+                       try {
+                               File scriptFile = script.getFile();
+                               baseDir = scriptFile.getParentFile();
+                       } catch (IOException e) {// resource is not a file
+                               baseDir = new File(System.getProperty("user.dir"));
+                       }
+                       project.setBaseDir(baseDir);
+                       // Reset basedir property, in order to avoid base dir override when
+                       // running in Maven
+                       project.setProperty("basedir", baseDir.getAbsolutePath());
+
+                       ProjectHelper2 projectHelper = new ProjectHelper2();
+                       project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE,
+                                       projectHelper);
+                       projectHelper.parse(project, script.getURL());
+               } catch (Exception e) {
+                       throw new SlcException("Could not parse project for script "
+                                       + scriptRelativePath, e);
+               }
+
+       }
+
+       protected void runProject(Project p, List<String> targets) {
+               p.fireBuildStarted();
+               Throwable exception = null;
+               try {
+                       if (targets.size() == 0) {// no target defined
+                               p.executeTarget(p.getDefaultTarget());
+                       } else {
+                               p.executeTargets(new Vector<String>(targets));
+                       }
+               } catch (Throwable e) {
+                       exception = e;
+                       throw new SlcException("SLC Ant execution failed", exception);
+               } finally {
+                       p.fireBuildFinished(exception);
+               }
+       }
+
+       public void setContextLocation(Resource contextLocation) {
+               this.contextLocation = contextLocation;
+       }
+
+       public void setRootDir(Resource rootDir) {
+               this.rootDir = rootDir;
+       }
+
+       public void setConfDir(Resource confDir) {
+               this.confDir = confDir;
+       }
+
+       public void setWorkDir(File workDir) {
+               this.workDir = workDir;
+       }
+
+       public void setParentContext(ConfigurableApplicationContext runtimeContext) {
+               this.parentContext = runtimeContext;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/RemoveRootDirMapper.java
new file mode 100644 (file)
index 0000000..43b247c
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.slc.ant;
+
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tools.ant.util.FileNameMapper;
+
+public class RemoveRootDirMapper implements FileNameMapper {
+       private Log log = LogFactory.getLog(RemoveRootDirMapper.class);
+       private String to = "enabled";
+
+       public String[] mapFileName(String sourceFileName) {
+               StringTokenizer st = new StringTokenizer(sourceFileName, "/");
+               boolean first = true;
+               boolean skipRoot = !to.equals("disabled");
+               StringBuffer buf = new StringBuffer("");
+               while (st.hasMoreTokens()) {
+                       if (first && skipRoot) { // skip
+                               st.nextToken();
+                               first = false;
+                       } else {
+                               buf.append(st.nextToken()).append('/');
+                       }
+               }
+
+               if (log.isTraceEnabled()) {
+                       log.trace("Source: " + sourceFileName + " - out: " + buf);
+               }
+               return new String[] { buf.toString() };
+       }
+
+       public void setFrom(String from) {
+       }
+
+       public void setTo(String to) {
+               this.to = to;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/SlcExecutionBuildListener.java
new file mode 100644 (file)
index 0000000..7447583
--- /dev/null
@@ -0,0 +1,202 @@
+package org.argeo.slc.ant;\r
+\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.apache.log4j.AppenderSkeleton;\r
+import org.apache.log4j.Level;\r
+import org.apache.log4j.MDC;\r
+import org.apache.log4j.spi.LoggingEvent;\r
+import org.apache.tools.ant.BuildEvent;\r
+import org.apache.tools.ant.BuildListener;\r
+import org.apache.tools.ant.Project;\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.process.SlcExecution;\r
+import org.argeo.slc.core.process.SlcExecutionNotifier;\r
+import org.argeo.slc.core.process.SlcExecutionStep;\r
+\r
+public class SlcExecutionBuildListener extends AppenderSkeleton implements\r
+               BuildListener {\r
+       private List<SlcExecutionNotifier> notifiers = new Vector<SlcExecutionNotifier>();\r
+\r
+       private boolean currentStepNotified = true;\r
+\r
+       // CUSTOMIZATIONS\r
+       /**\r
+        * Whether to log Ant initialization stuff before the first target has been\r
+        * called.\r
+        */\r
+       private boolean logBeforeFirstTarget = false;\r
+       /** Whether the first target has been called. */\r
+       private boolean firstTargetStarted = false;\r
+\r
+       private boolean logTaskStartFinish = true;\r
+\r
+       public SlcExecutionBuildListener() {\r
+               // Default log level\r
+               setThreshold(Level.INFO);\r
+       }\r
+\r
+       public void buildStarted(BuildEvent event) {\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               for (SlcExecutionNotifier notifier : notifiers) {\r
+                       notifier.newExecution(slcExecution);\r
+               }\r
+       }\r
+\r
+       public void buildFinished(BuildEvent event) {\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               String oldStatus = slcExecution.getStatus();\r
+               slcExecution.setStatus(SlcExecution.STATUS_FINISHED);\r
+\r
+               for (SlcExecutionNotifier notifier : notifiers) {\r
+                       notifier.updateStatus(slcExecution, oldStatus, slcExecution\r
+                                       .getStatus());\r
+               }\r
+       }\r
+\r
+       public void messageLogged(BuildEvent event) {\r
+               if (!shouldLog())\r
+                       return;\r
+\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               if (slcExecution != null) {\r
+                       if (currentStepNotified) {\r
+                               slcExecution.getSteps().add(\r
+                                               new SlcExecutionStep(event.getMessage()));\r
+                               notifyStep(slcExecution, slcExecution.currentStep());\r
+                               currentStepNotified = true;\r
+                       } else {\r
+                               slcExecution.currentStep().addLog(event.getMessage());\r
+                       }\r
+               } else {\r
+                       // TODO: log before initialization?\r
+               }\r
+       }\r
+\r
+       public void targetStarted(BuildEvent event) {\r
+               if (!firstTargetStarted)\r
+                       firstTargetStarted = true;\r
+\r
+               addLogStep(event, "Target " + event.getTarget().getName() + " started");\r
+       }\r
+\r
+       public void targetFinished(BuildEvent event) {\r
+               addLogStep(event, "Target " + event.getTarget().getName() + " finished");\r
+       }\r
+\r
+       public void taskStarted(BuildEvent event) {\r
+               if (!shouldLog())\r
+                       return;\r
+\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               if (!currentStepNotified) {\r
+                       notifyStep(slcExecution, slcExecution.currentStep());\r
+                       currentStepNotified = true;\r
+               }\r
+\r
+               String msg = null;\r
+               if (logTaskStartFinish)\r
+                       msg = "Task " + event.getTask().getTaskName() + " started";\r
+\r
+               slcExecution.getSteps().add(new SlcExecutionStep(msg));\r
+\r
+               currentStepNotified = false;\r
+       }\r
+\r
+       public void taskFinished(BuildEvent event) {\r
+               if (!shouldLog())\r
+                       return;\r
+\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               if (!currentStepNotified) {\r
+\r
+                       if (logTaskStartFinish)\r
+                               slcExecution.currentStep().addLog(\r
+                                               "Task " + event.getTask().getTaskName() + " finished");\r
+\r
+                       notifyStep(slcExecution, slcExecution.currentStep());\r
+                       currentStepNotified = true;\r
+               }\r
+       }\r
+\r
+       public void setNotifiers(List<SlcExecutionNotifier> notifiers) {\r
+               this.notifiers = notifiers;\r
+       }\r
+\r
+       protected SlcExecution getSlcExecution(BuildEvent event) {\r
+               return getSlcExecution(event.getProject());\r
+       }\r
+\r
+       protected SlcExecution getSlcExecution(Project project) {\r
+               SlcExecution slcExecution = (SlcExecution) project\r
+                               .getReference(AntConstants.REF_SLC_EXECUTION);\r
+\r
+               if (slcExecution == null)\r
+                       throw new SlcException("No SLC Execution registered.");\r
+               return slcExecution;\r
+       }\r
+\r
+       protected void addLogStep(BuildEvent event, String msg) {\r
+               SlcExecution slcExecution = getSlcExecution(event);\r
+               slcExecution.getSteps().add(new SlcExecutionStep(msg));\r
+\r
+               notifyStep(slcExecution, slcExecution.currentStep());\r
+               currentStepNotified = true;\r
+       }\r
+\r
+       protected void notifyStep(SlcExecution slcExecution, SlcExecutionStep step) {\r
+               Vector<SlcExecutionStep> additionalSteps = new Vector<SlcExecutionStep>();\r
+               additionalSteps.add(step);\r
+               notifySteps(slcExecution, additionalSteps);\r
+       }\r
+\r
+       protected void notifySteps(SlcExecution slcExecution,\r
+                       List<SlcExecutionStep> additionalSteps) {\r
+               for (SlcExecutionNotifier notifier : notifiers) {\r
+                       notifier.addSteps(slcExecution, additionalSteps);\r
+               }\r
+       }\r
+\r
+       /* Log4j methods */\r
+\r
+       @Override\r
+       protected void append(LoggingEvent event) {\r
+               Project project = (Project) MDC.get(AntConstants.MDC_ANT_PROJECT);\r
+               if (project == null)\r
+                       throw new SlcException("No Ant project registered in Log4j MDC.");\r
+\r
+               SlcExecution slcExecution = getSlcExecution(project);\r
+               if (currentStepNotified) {\r
+                       slcExecution.getSteps().add(\r
+                                       new SlcExecutionStep(event.getMessage().toString()));\r
+                       currentStepNotified = false;\r
+               } else {\r
+                       slcExecution.currentStep().addLog(event.getMessage().toString());\r
+               }\r
+       }\r
+\r
+       protected boolean shouldLog() {\r
+               return logBeforeFirstTarget || firstTargetStarted;\r
+       }\r
+\r
+       public void close() {\r
+       }\r
+\r
+       public boolean requiresLayout() {\r
+               return false;\r
+       }\r
+\r
+       public void setLogBeforeFirstTarget(boolean logBeforeFirstTarget) {\r
+               this.logBeforeFirstTarget = logBeforeFirstTarget;\r
+       }\r
+\r
+       public void setLogTaskStartFinish(boolean logTaskStartFinish) {\r
+               this.logTaskStartFinish = logTaskStartFinish;\r
+       }\r
+\r
+       public void setLogLevel(String logLevel) {\r
+               setThreshold(Level.toLevel(logLevel));\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcDeployTask.java
new file mode 100644 (file)
index 0000000..2055e3b
--- /dev/null
@@ -0,0 +1,72 @@
+package org.argeo.slc.ant.deploy;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tools.ant.BuildException;\r
+import org.argeo.slc.ant.spring.SpringArg;\r
+import org.argeo.slc.ant.structure.SAwareTask;\r
+import org.argeo.slc.core.build.Distribution;\r
+import org.argeo.slc.core.deploy.Deployment;\r
+import org.argeo.slc.core.deploy.DeploymentData;\r
+import org.argeo.slc.core.deploy.TargetData;\r
+\r
+/** Ant task wrapping a deployment. */\r
+public class SlcDeployTask extends SAwareTask {\r
+       private Log log = LogFactory.getLog(SlcDeployTask.class);\r
+\r
+       private String deploymentBean = null;\r
+\r
+       private SpringArg<DeploymentData> deploymentDataArg;\r
+       private SpringArg<TargetData> targetDataArg;\r
+       private SpringArg<Distribution> distributionArg;\r
+\r
+       @Override\r
+       public void executeActions(String mode) throws BuildException {\r
+               Deployment deployment = (Deployment) getContext().getBean(\r
+                               deploymentBean);\r
+\r
+               // set overridden references\r
+               if (distributionArg != null) {\r
+                       deployment.setDistribution(distributionArg.getInstance());\r
+                       log.trace("Overrides distribution");\r
+               }\r
+\r
+               if (deploymentDataArg != null) {\r
+                       deployment.setDeploymentData(deploymentDataArg.getInstance());\r
+                       log.trace("Overrides deployment data");\r
+               }\r
+\r
+               if (targetDataArg != null) {\r
+                       deployment.setTargetData(targetDataArg.getInstance());\r
+                       log.trace("Overrides target data");\r
+               }\r
+\r
+               deployment.execute();\r
+       }\r
+\r
+       /**\r
+        * The bean name of the test run to use. If not set the default is used.\r
+        * \r
+        * @see SlcAntConfig\r
+        */\r
+       public void setDeployment(String deploymentBean) {\r
+               this.deploymentBean = deploymentBean;\r
+       }\r
+\r
+       /** Creates deployment data sub tag. */\r
+       public SpringArg<DeploymentData> createDeploymentData() {\r
+               deploymentDataArg = new SpringArg<DeploymentData>();\r
+               return deploymentDataArg;\r
+       }\r
+\r
+       /** Creates target data sub tag. */\r
+       public SpringArg<TargetData> createTargetData() {\r
+               targetDataArg = new SpringArg<TargetData>();\r
+               return targetDataArg;\r
+       }\r
+\r
+       public SpringArg<Distribution> createDistribution() {\r
+               distributionArg = new SpringArg<Distribution>();\r
+               return distributionArg;\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/SlcManagerTask.java
new file mode 100644 (file)
index 0000000..c4cc74b
--- /dev/null
@@ -0,0 +1,35 @@
+package org.argeo.slc.ant.deploy;
+
+import java.lang.reflect.Method;
+
+import org.argeo.slc.ant.structure.SAwareTask;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.deploy.DeployedSystem;
+import org.argeo.slc.core.deploy.DeployedSystemManager;
+
+public class SlcManagerTask extends SAwareTask {
+       private String action;
+       private String manager;
+
+       @Override
+       protected void executeActions(String mode) {
+               DeployedSystemManager<DeployedSystem> systemManager = getBean(manager);
+
+               try {
+                       Method method = systemManager.getClass().getMethod(action, null);
+                       method.invoke(systemManager, null);
+               } catch (Exception e) {
+                       throw new SlcException("Cannot execute action " + action
+                                       + " for manager " + manager, e);
+               }
+       }
+
+       public void setAction(String action) {
+               this.action = action;
+       }
+
+       public void setManager(String manager) {
+               this.manager = manager;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/deploy/package.html
new file mode 100644 (file)
index 0000000..76582d1
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<head></head>\r
+<body>\r
+Integration of SLC Deploy in Ant.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/detached/SlcDetachedTask.java
new file mode 100644 (file)
index 0000000..d973d38
--- /dev/null
@@ -0,0 +1,76 @@
+package org.argeo.slc.ant.detached;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.spring.MapArg;
+import org.argeo.slc.ant.structure.SAwareTask;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.detached.DetachedAnswer;
+import org.argeo.slc.detached.DetachedClient;
+import org.argeo.slc.detached.DetachedRequest;
+import org.argeo.slc.spring.SpringUtils;
+
+public class SlcDetachedTask extends SAwareTask {
+       private final static Log log = LogFactory.getLog(SlcDetachedTask.class);
+
+       private String client;
+       private String action;
+
+       private MapArg properties;
+
+       @Override
+       protected void executeActions(String mode) {
+               // Find detached client
+               DetachedClient detachedClient = null;
+               if (client != null)
+                       detachedClient = getBean(client);
+               else
+                       detachedClient = SpringUtils.loadSingleFromContext(getContext(),
+                                       DetachedClient.class);
+
+               if (detachedClient == null)
+                       throw new SlcException("Could not find any detached client.");
+
+               // Prepare and send request
+               DetachedRequest request = new DetachedRequest(UUID.randomUUID()
+                               .toString());
+               request.setRef(action);
+
+               if (properties != null) {
+                       Properties props = new Properties();
+                       props.putAll(properties.getMap());
+                       request.setProperties(props);
+               }
+
+               try {
+                       detachedClient.sendRequest(request);
+                       DetachedAnswer answer = detachedClient.receiveAnswer();
+                       if (answer.getStatus() == DetachedAnswer.ERROR)
+                               throw new SlcException("Error when executing request "
+                                               + answer.getUuid() + ": " + answer.getLog());
+                       else
+                               log.info("Admin answer: " + answer.getLog());
+               } catch (Exception e) {
+                       throw new SlcException("Could not send request.", e);
+               }
+       }
+
+       public void setClient(String driverBean) {
+               this.client = driverBean;
+       }
+
+       public void setAction(String action) {
+               this.action = action;
+       }
+
+       public MapArg createProperties() {
+               if (properties == null)
+                       properties = new MapArg();
+               else
+                       throw new SlcException("Properties already declared.");
+               return properties;
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/package.html
new file mode 100644 (file)
index 0000000..9f36fb1
--- /dev/null
@@ -0,0 +1,38 @@
+<html>\r
+<head></head>\r
+<body>\r
+Bases classes for SLC Ant extensions.\r
+<h2>Introduction</h2>\r
+SLC Ant allows to integrate Ant and Spring in order to run an\r
+application based on top of SLC. Sequence of actions are defined in Ant\r
+files with specific Ant tasks referencing Spring beans implementing the\r
+SLC interfaces. The properties of these beans can be overridden at\r
+runtime in the Ant scripts.\r
+<br />\r
+SLC Ant also provides a tree-based implementation of the SLC structure\r
+which allows to uniquely identify and reference the various actions.\r
+\r
+<h2>Installation</h2>\r
+The structure will be first defined by the directory tree where the Ant\r
+files are stored. In order to define the root of this tree, you need to\r
+place in the root directory an\r
+<b>SLC Ant root file</b>\r
+(default name: slcRoot.properties).\r
+<br />\r
+In this root file you can define a configuration directory and a work\r
+directory (default values are provided if they are not explicitly set).\r
+<br />\r
+Additional properties can then be defined in files stored under the\r
+configuration directory.\r
+<br />\r
+For details about the configuration and the various properties, please\r
+refer to {@link org.argeo.slc.ant.SlcAntConfig}.\r
+\r
+<h2>Running SLC Ant</h2>\r
+SLC Ant can be run either via pure Ant scripts or programmatically using\r
+{@link org.argeo.slc.ant.AntRegistryUtil}. In both cases, make sure that\r
+SLC and its dependencies are in the classpath (Spring (always), logging\r
+system such as log4j, Hibernate, etc.).\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/AbstractSpringTask.java
new file mode 100644 (file)
index 0000000..f0eae3f
--- /dev/null
@@ -0,0 +1,24 @@
+package org.argeo.slc.ant.spring;\r
+\r
+import org.springframework.context.ApplicationContext;\r
+\r
+import org.apache.tools.ant.Task;\r
+\r
+import org.argeo.slc.ant.AntConstants;\r
+import org.argeo.slc.core.process.SlcExecution;\r
+\r
+/** Abstract Ant task providing access to a Spring context. */\r
+public abstract class AbstractSpringTask extends Task {\r
+\r
+       /** Gets the related Spring context. */\r
+       protected ApplicationContext getContext() {\r
+               return (ApplicationContext) getProject().getReference(\r
+                               AntConstants.REF_ROOT_CONTEXT);\r
+       }\r
+\r
+       /** Gets the related slc execution or null if not is registered. */\r
+       protected SlcExecution getSlcExecution() {\r
+               return (SlcExecution) getProject().getReference(\r
+                               AntConstants.REF_SLC_EXECUTION);\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/ListArg.java
new file mode 100644 (file)
index 0000000..7c270ee
--- /dev/null
@@ -0,0 +1,37 @@
+package org.argeo.slc.ant.spring;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.argeo.slc.core.SlcException;
+
+/** List of overrides */
+public class ListArg {
+       private List<OverrideArg> list = new Vector<OverrideArg>();
+
+       /** Creates override sub tag. */
+       public OverrideArg createOverride() {
+               OverrideArg overrideArg = new OverrideArg();
+               list.add(overrideArg);
+               return overrideArg;
+       }
+
+       /** Gets as list of objects. */
+       public List<Object> getAsObjectList(List<Object> originalList) {
+               if (originalList != null && originalList.size() != list.size()) {
+                       throw new SlcException("Cannot merge lists of different sizes.");
+               }
+
+               List<Object> objectList = new Vector<Object>(list.size());
+
+               for (int i = 0; i < list.size(); i++) {
+                       OverrideArg arg = list.get(i);
+
+                       if (originalList != null)
+                               arg.setOriginal(originalList.get(i));
+
+                       objectList.add(arg.getObject());
+               }
+               return objectList;
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/MapArg.java
new file mode 100644 (file)
index 0000000..6f53994
--- /dev/null
@@ -0,0 +1,97 @@
+package org.argeo.slc.ant.spring;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+import java.util.Vector;\r
+\r
+import org.apache.tools.ant.BuildException;\r
+\r
+import org.argeo.slc.core.SlcException;\r
+\r
+public class MapArg {\r
+       private List<EntryArg> entries = new Vector<EntryArg>();\r
+       private Map<String, Object> map = new TreeMap<String, Object>();\r
+\r
+       public EntryArg createEntry() {\r
+               EntryArg arg = new EntryArg();\r
+               entries.add(arg);\r
+               return arg;\r
+       }\r
+\r
+       public Map<String, Object> getAsObjectMap(Map<String, Object> originalMap) {\r
+               Map<String, Object> objectMap = new TreeMap<String, Object>();\r
+               for (EntryArg arg : entries) {\r
+                       String key = arg.getKey();\r
+\r
+                       if (objectMap.containsKey(key)) {\r
+                               throw new SlcException("Key '" + key + "' already set.");\r
+                       }\r
+\r
+                       if (originalMap != null && originalMap.containsKey(key)\r
+                                       && arg.getOverrideArg() != null)\r
+                               arg.getOverrideArg().setOriginal(originalMap.get(key));\r
+\r
+                       objectMap.put(key, arg.getObject());\r
+\r
+               }\r
+               return objectMap;\r
+       }\r
+\r
+       /**\r
+        * Returns a cached reference if it was already called. This reference could\r
+        * have been modified externally and thus not anymore be in line with the\r
+        * configuration.\r
+        */\r
+       public Map<String, Object> getMap() {\r
+               if (map.size() == 0)\r
+                       map = getAsObjectMap(null);\r
+               return map;\r
+       }\r
+\r
+       public static class EntryArg {\r
+               private String key;\r
+               private Object valueStr;\r
+               private OverrideArg overrideArg;\r
+\r
+               public String getKey() {\r
+                       return key;\r
+               }\r
+\r
+               public void setKey(String key) {\r
+                       this.key = key;\r
+               }\r
+\r
+               public Object getObject() {\r
+                       if (overrideArg != null) {\r
+                               return overrideArg.getObject();\r
+                       } else if (valueStr != null) {\r
+                               return valueStr;\r
+                       } else {\r
+                               throw new BuildException("Value not set.");\r
+                       }\r
+               }\r
+\r
+               public void setValue(String value) {\r
+                       check();\r
+                       this.valueStr = value;\r
+               }\r
+\r
+               public OverrideArg createOverride() {\r
+                       check();\r
+                       overrideArg = new OverrideArg();\r
+                       return overrideArg;\r
+               }\r
+\r
+               private void check() {\r
+                       if (valueStr != null || overrideArg != null) {\r
+                               throw new BuildException("Value already set");\r
+                       }\r
+               }\r
+\r
+               public OverrideArg getOverrideArg() {\r
+                       return overrideArg;\r
+               }\r
+\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/OverrideArg.java
new file mode 100644 (file)
index 0000000..645b592
--- /dev/null
@@ -0,0 +1,103 @@
+package org.argeo.slc.ant.spring;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tools.ant.BuildException;\r
+\r
+/** Ant type allowing to override bean properties. */\r
+public class OverrideArg extends SpringArg<Object> {\r
+       private final static Log log = LogFactory.getLog(OverrideArg.class);\r
+\r
+       private String name;\r
+       private Object value;\r
+       private ListArg overrideList;\r
+       private MapArg overrideMap;\r
+\r
+       private Boolean merge = false;\r
+\r
+       /** The name of the property to override. */\r
+       public String getName() {\r
+               return name;\r
+       }\r
+\r
+       /** Sets the name. */\r
+       public void setName(String name) {\r
+               this.name = name;\r
+       }\r
+\r
+       /** Both value and bean cannot be set. */\r
+       public void setValue(String value) {\r
+               checkValueAlreadySet();\r
+               this.value = value;\r
+       }\r
+\r
+       @Override\r
+       public void setBean(String bean) {\r
+               checkValueAlreadySet();\r
+               super.setBean(bean);\r
+       }\r
+\r
+       /** Creates override list sub tag. */\r
+       public ListArg createList() {\r
+               checkValueAlreadySet();\r
+               overrideList = new ListArg();\r
+               return overrideList;\r
+       }\r
+\r
+       public MapArg createMap() {\r
+               checkValueAlreadySet();\r
+               overrideMap = new MapArg();\r
+               return overrideMap;\r
+       }\r
+\r
+       /**\r
+        * The related object: the value if a value had been set or an instance of\r
+        * the bean if not.\r
+        */\r
+       public Object getObject() {\r
+               if (value != null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as value");\r
+                       return value;\r
+               } else if (getBean() != null\r
+                               || getAntref() != null\r
+                               // works on original if no collection is defined\r
+                               || (getOriginal() != null && overrideList == null && overrideMap == null)) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as instance");\r
+                       return getInstance();\r
+               } else if (overrideList != null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as list");\r
+                       return overrideList.getAsObjectList((List<Object>) getOriginal());\r
+               } else if (overrideMap != null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns override object as map");\r
+                       return overrideMap\r
+                                       .getAsObjectMap((Map<String, Object>) getOriginal());\r
+               } else {\r
+                       throw new BuildException("Value or bean not set.");\r
+               }\r
+       }\r
+\r
+       protected void checkValueAlreadySet() {\r
+               super.checkValueAlreadySet();\r
+               if (value != null || overrideList != null || overrideMap != null) {\r
+                       if (!getMerge()) {\r
+                               throw new BuildException("Value already set.");\r
+                       }\r
+               }\r
+       }\r
+\r
+       public Boolean getMerge() {\r
+               return merge;\r
+       }\r
+\r
+       public void setMerge(Boolean merge) {\r
+               this.merge = merge;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringArg.java
new file mode 100644 (file)
index 0000000..3f3bb3c
--- /dev/null
@@ -0,0 +1,163 @@
+package org.argeo.slc.ant.spring;\r
+\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tools.ant.types.DataType;\r
+import org.argeo.slc.ant.AntConstants;\r
+import org.argeo.slc.core.SlcException;\r
+import org.springframework.beans.BeanWrapper;\r
+import org.springframework.beans.BeanWrapperImpl;\r
+import org.springframework.beans.factory.InitializingBean;\r
+import org.springframework.context.ApplicationContext;\r
+\r
+/** Abstract Ant type wrapping a Spring bean. */\r
+public class SpringArg<T> extends DataType {\r
+       private final static Log log = LogFactory.getLog(SpringArg.class);\r
+\r
+       private List<OverrideArg> overrides = new Vector<OverrideArg>();\r
+\r
+       private String bean;\r
+       private String antref;\r
+       /**\r
+        * Reference to the original object, used to merge overrides. <b>this object\r
+        * will be modified</b>.\r
+        */\r
+       private T original;\r
+\r
+       // cache bean instance to avoid reading it twice if it is a prototype\r
+       private T instance = null;\r
+\r
+       /** The <u>name</u> of the underlying bean, as set through the attribute. */\r
+       public String getBean() {\r
+               return bean;\r
+       }\r
+\r
+       /** Setter for the bean name. */\r
+       public void setBean(String bean) {\r
+               checkValueAlreadySet();\r
+               this.bean = bean;\r
+       }\r
+\r
+       public String getAntref() {\r
+               return antref;\r
+       }\r
+\r
+       /** Sets a reference to an ant data type. */\r
+       public void setAntref(String antref) {\r
+               checkValueAlreadySet();\r
+               this.antref = antref;\r
+       }\r
+\r
+       /**\r
+        * Retrieve the instance of the bean, and sets the overridden properties.\r
+        * <b>The value is cached.</b>\r
+        */\r
+       public T getInstance() {\r
+               if (instance == null) {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Creates instance");\r
+\r
+                       if (bean != null) {\r
+                               instance = (T) getContext().getBean(bean);\r
+                               if (instance == null)\r
+                                       throw new SlcException("No object found for Spring bean "\r
+                                                       + bean);\r
+                       } else if (antref != null) {\r
+                               instance = (T) getProject().getReference(antref);\r
+                               if (instance == null)\r
+                                       throw new SlcException("No object found for Ant reference "\r
+                                                       + antref);\r
+                       } else if (original != null) {\r
+                               instance = original;\r
+                       } else {\r
+                               throw new SlcException(\r
+                                               "Don't know how to retrieve bean instance");\r
+                       }\r
+\r
+                       setOverridenProperties(instance);\r
+\r
+                       // FIXME: why are we doing this? Could not find any object using it\r
+                       if (instance instanceof InitializingBean) {\r
+                               try {\r
+                                       ((InitializingBean) instance).afterPropertiesSet();\r
+                               } catch (Exception e) {\r
+                                       throw new SlcException("Could not initialize bean", e);\r
+                               }\r
+                       }\r
+               } else {\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Returns cached instance");\r
+               }\r
+               return instance;\r
+       }\r
+\r
+       protected void setOverridenProperties(Object obj) {\r
+               BeanWrapper wrapper = new BeanWrapperImpl(obj);\r
+               for (OverrideArg override : overrides) {\r
+                       if (override.getName() == null) {\r
+                               throw new SlcException(\r
+                                               "The name of the property to override has to be set.");\r
+                       }\r
+\r
+                       if (log.isTraceEnabled())\r
+                               log.trace(this + "\t: Overrides property " + override.getName()\r
+                                               + " with " + override);\r
+\r
+                       if (override.getMerge() == true) {\r
+                               // if override is marked as merged retrieve the value and set is\r
+                               // as original\r
+                               override.setOriginal(wrapper.getPropertyValue(override\r
+                                               .getName()));\r
+                       }\r
+                       wrapper.setPropertyValue(override.getName(), override.getObject());\r
+               }\r
+\r
+       }\r
+\r
+       /** Creates an override subtag. */\r
+       public OverrideArg createOverride() {\r
+               OverrideArg propertyArg = new OverrideArg();\r
+               overrides.add(propertyArg);\r
+               return propertyArg;\r
+       }\r
+\r
+       /** The related Spring application context. */\r
+       protected ApplicationContext getContext() {\r
+               return (ApplicationContext) getProject().getReference(\r
+                               AntConstants.REF_ROOT_CONTEXT);\r
+       }\r
+\r
+       protected void checkValueAlreadySet() {\r
+               if (antref != null || bean != null || original != null) {\r
+                       throw new SlcException("Instance value already defined.");\r
+               }\r
+       }\r
+\r
+       public void setOriginal(T original) {\r
+               checkValueAlreadySet();\r
+               this.original = original;\r
+       }\r
+\r
+       public T getOriginal() {\r
+               return original;\r
+       }\r
+\r
+       @Override\r
+       public String toString() {\r
+               StringBuffer buf = new StringBuffer(getClass().getSimpleName());\r
+               if (bean != null) {\r
+                       buf.append("#bean=").append(bean);\r
+               } else if (antref != null) {\r
+                       buf.append("#antref=").append(antref);\r
+               } else if (original != null) {\r
+                       buf.append("#orig=").append(original.hashCode());\r
+               } else {\r
+                       buf.append("#noid");\r
+               }\r
+               buf.append("#").append(hashCode());\r
+               return buf.toString();\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/SpringRegister.java
new file mode 100644 (file)
index 0000000..a7d88f2
--- /dev/null
@@ -0,0 +1,51 @@
+package org.argeo.slc.ant.spring;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tools.ant.BuildException;
+
+public class SpringRegister extends AbstractSpringTask {
+       private static final Log log = LogFactory.getLog(SpringRegister.class);
+
+       private List<BeanArg> beans = new Vector<BeanArg>();
+
+       @Override
+       public void execute() throws BuildException {
+               for (BeanArg bean : beans) {
+                       Object instance = bean.getInstance();
+                       if (bean.getAntid() != null) {
+                               getProject().addReference(bean.getAntid(), instance);
+                       } else {
+                               if (bean.getAntref() != null) {
+                                       log
+                                                       .warn("Cannot register beans with antref (Ant reference "
+                                                                       + bean.getAntref() + ")");
+                               } else {
+                                       getProject().addReference(bean.getBean(), instance);
+                               }
+                       }
+               }
+       }
+
+       public BeanArg createObject() {
+               BeanArg bean = new BeanArg();
+               beans.add(bean);
+               return bean;
+       }
+
+       protected static class BeanArg extends SpringArg<Object> {
+               private String antid;
+
+               public String getAntid() {
+                       return antid;
+               }
+
+               public void setAntid(String antid) {
+                       this.antid = antid;
+               }
+
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/spring/package.html
new file mode 100644 (file)
index 0000000..6d141d9
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<head></head>\r
+<body>\r
+Integration of Spring in Ant.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/SAwareTask.java
new file mode 100644 (file)
index 0000000..134b2c1
--- /dev/null
@@ -0,0 +1,160 @@
+package org.argeo.slc.ant.structure;\r
+\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.apache.tools.ant.BuildException;\r
+import org.apache.tools.ant.Target;\r
+import org.argeo.slc.ant.AntConstants;\r
+import org.argeo.slc.ant.spring.AbstractSpringTask;\r
+import org.argeo.slc.ant.spring.SpringArg;\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.structure.SimpleSElement;\r
+import org.argeo.slc.core.structure.StructureAware;\r
+import org.argeo.slc.core.structure.StructureElement;\r
+import org.argeo.slc.core.structure.StructureRegistry;\r
+import org.argeo.slc.core.structure.tree.TreeSPath;\r
+\r
+/** Ant task that can be registered within a structure. */\r
+public abstract class SAwareTask extends AbstractSpringTask {\r
+       private String path;\r
+       private TreeSPath treeSPath;\r
+       private final List<SpringArg> sAwareArgs = new Vector<SpringArg>();\r
+\r
+       private StructureElementArg structureElementArg;\r
+\r
+       @Override\r
+       public void init() throws BuildException {\r
+               StructureRegistry<TreeSPath> registry = getRegistry();\r
+               Target target = getOwningTarget();\r
+\r
+               TreeSPath targetPath = createTargetPath(target);\r
+               SimpleSElement targetElement = (SimpleSElement) registry\r
+                               .getElement(createTargetPath(target));\r
+\r
+               if (targetElement == null) {\r
+                       targetElement = new SimpleSElement(target.getDescription(),\r
+                                       "<no target desc>");\r
+                       registry.register(targetPath, targetElement);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Includes this arg in the checks for propagation of structure related\r
+        * information.\r
+        */\r
+       protected void addSAwareArg(SpringArg arg) {\r
+               sAwareArgs.add(arg);\r
+       }\r
+\r
+       @Override\r
+       /**\r
+        * Called by Ant at runtime. Decides whether to call the actions depending\r
+        * of the mode of the underlying structure registry.\r
+        * \r
+        * @see #executeActions\r
+        * @see StructureRegistry\r
+        */\r
+       public final void execute() throws BuildException {\r
+               if (path == null) {\r
+                       // register the task in the structure\r
+                       TreeSPath targetPath = createTargetPath(getOwningTarget());\r
+                       TreeSPath taskPath = targetPath.createChild(getTaskName()\r
+                                       + targetPath.listChildren(getRegistry()).size());\r
+\r
+                       treeSPath = taskPath;\r
+               } else {\r
+                       treeSPath = new TreeSPath(path);\r
+               }\r
+\r
+               if (getRegistry().getElement(treeSPath) == null) {\r
+                       // No structure element registered.\r
+                       if (structureElementArg != null) {\r
+                               getRegistry().register(treeSPath,\r
+                                               structureElementArg.getStructureElement());\r
+                       } else {\r
+                               if (getDescription() != null) {\r
+                                       getRegistry().register(treeSPath,\r
+                                                       new SimpleSElement(getDescription()));\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // notify registered args\r
+               for (SpringArg arg : sAwareArgs) {\r
+                       Object obj = arg.getInstance();\r
+\r
+                       if (obj instanceof StructureAware) {\r
+                               StructureAware<TreeSPath> sAwareT = (StructureAware<TreeSPath>) obj;\r
+                               sAwareT.notifyCurrentPath(getRegistry(), treeSPath);\r
+                       }\r
+               }\r
+\r
+               // execute depending on the registry mode\r
+               String mode = getRegistry().getMode();\r
+               if (mode.equals(StructureRegistry.ALL)) {\r
+                       executeActions(mode);\r
+               } else if (mode.equals(StructureRegistry.ACTIVE)) {\r
+                       List<TreeSPath> activePaths = getRegistry().getActivePaths();\r
+\r
+                       if (activePaths.contains(treeSPath)) {\r
+                               if (activePaths.contains(treeSPath)) {\r
+                                       executeActions(mode);\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       /** Actions to be executed by the implementor. */\r
+       protected abstract void executeActions(String mode);\r
+\r
+       public <T> T getBean(String beanName) {\r
+               return (T) getContext().getBean(beanName);\r
+       }\r
+\r
+       /** Create a reference to an external structure element. */\r
+       public StructureElementArg createStructureElement() {\r
+               if (structureElementArg != null)\r
+                       throw new SlcException("Arg already set.");\r
+               structureElementArg = new StructureElementArg();\r
+               return structureElementArg;\r
+       }\r
+\r
+       /** Gets the underlying structure registry. */\r
+       protected StructureRegistry<TreeSPath> getRegistry() {\r
+               return (StructureRegistry<TreeSPath>) getProject().getReference(\r
+                               AntConstants.REF_STRUCTURE_REGISTRY);\r
+       }\r
+\r
+       /** Creates the treeSPath for a given Ant target. */\r
+       protected static TreeSPath createTargetPath(Target target) {\r
+               TreeSPath projectPath = (TreeSPath) target.getProject().getReference(\r
+                               AntConstants.REF_PROJECT_PATH);\r
+               return projectPath.createChild(target.getName());\r
+       }\r
+\r
+       /** Gets the treeSPath under which this task is registered. */\r
+       public TreeSPath getTreeSPath() {\r
+               return treeSPath;\r
+       }\r
+\r
+       public String getLabel() {\r
+               String description = super.getDescription();\r
+               if (description == null) {\r
+                       return "<no task def>";\r
+               } else {\r
+                       return description;\r
+               }\r
+       }\r
+\r
+       public void setPath(String path) {\r
+               this.path = path;\r
+       }\r
+}\r
+\r
+class StructureElementArg extends SpringArg {\r
+       public StructureElement getStructureElement() {\r
+               return (StructureElement) getInstance();\r
+       }\r
+}
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/structure/package.html
new file mode 100644 (file)
index 0000000..99e45d3
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<head></head>\r
+<body>\r
+Integration of SLC Structure in Ant.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/ParentContextType.java
new file mode 100644 (file)
index 0000000..7915b1a
--- /dev/null
@@ -0,0 +1,102 @@
+package org.argeo.slc.ant.test;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Vector;\r
+\r
+import org.apache.tools.ant.types.DataType;\r
+\r
+import org.argeo.slc.ant.spring.MapArg;\r
+import org.argeo.slc.core.SlcException;\r
+import org.argeo.slc.core.test.context.ContextAware;\r
+import org.argeo.slc.core.test.context.ContextUtils;\r
+import org.argeo.slc.core.test.context.ParentContextAware;\r
+\r
+public class ParentContextType extends DataType implements ParentContextAware {\r
+       private MapArg values = null;\r
+       private MapArg expectedValues = null;\r
+\r
+       private String contextAnyFlag = DEFAULT_ANY_FLAG;\r
+       private String contextSkipFlag = DEFAULT_SKIP_FLAG;\r
+\r
+       private String basedon = null;\r
+\r
+       private List<ContextAware> children = new Vector<ContextAware>();\r
+\r
+       public MapArg createValues() {\r
+               values = new MapArg();\r
+               return values;\r
+       }\r
+\r
+       public MapArg createExpectedValues() {\r
+               expectedValues = new MapArg();\r
+               return expectedValues;\r
+       }\r
+\r
+       public void addChildContext(ContextAware contextAware) {\r
+               children.add(contextAware);\r
+       }\r
+\r
+       public Collection<ContextAware> getChildContexts() {\r
+               return children;\r
+       }\r
+\r
+       public String getContextAnyFlag() {\r
+               return contextAnyFlag;\r
+       }\r
+\r
+       public void setContextAnyFlag(String contextAnyFlag) {\r
+               this.contextAnyFlag = contextAnyFlag;\r
+       }\r
+\r
+       public String getContextSkipFlag() {\r
+               return contextSkipFlag;\r
+       }\r
+\r
+       public void setContextSkipFlag(String contextSkipFlag) {\r
+               this.contextSkipFlag = contextSkipFlag;\r
+       }\r
+\r
+       public Map<String, Object> getExpectedValues() {\r
+               if (expectedValues == null)\r
+                       expectedValues = new MapArg();\r
+               if (basedon != null) {\r
+                       Map<String, Object> map = getBaseContext().getExpectedValues();\r
+                       ContextUtils.putNotContained(expectedValues.getMap(), map);\r
+               }\r
+               return expectedValues.getMap();\r
+       }\r
+\r
+       public Map<String, Object> getValues() {\r
+               if (values == null)\r
+                       values = new MapArg();\r
+               if (basedon != null) {\r
+                       Map<String, Object> map = getBaseContext().getValues();\r
+                       ContextUtils.putNotContained(values.getMap(), map);\r
+               }\r
+               return values.getMap();\r
+       }\r
+\r
+       private ParentContextType getBaseContext() {\r
+               return (ParentContextType) getProject().getReference(basedon);\r
+       }\r
+\r
+       public void setValues(Map<String, Object> values) {\r
+               throw new SlcException("Cannot override values map.");\r
+       }\r
+\r
+       public void setUpdateValues(Map<String, Object> overrideValues) {\r
+               getValues().putAll(overrideValues);\r
+       }\r
+\r
+       public void setUpdateExpectedValues(\r
+                       Map<String, Object> overrideExpectedValues) {\r
+               getExpectedValues().putAll(overrideExpectedValues);\r
+       }\r
+\r
+       public void setBasedon(String basedon) {\r
+               this.basedon = basedon;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcCloseTestResultTask.java
new file mode 100644 (file)
index 0000000..7aab475
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.slc.ant.test;\r
+\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.ant.spring.SpringArg;\r
+import org.argeo.slc.ant.structure.SAwareTask;\r
+import org.argeo.slc.core.structure.StructureRegistry;\r
+import org.argeo.slc.core.test.TestResult;\r
+\r
+/** Ant tasks closing a given result. */\r
+public class SlcCloseTestResultTask extends SAwareTask {\r
+       private final static Log log = LogFactory\r
+                       .getLog(SlcCloseTestResultTask.class);\r
+\r
+       public List<SpringArg<TestResult>> results = new Vector<SpringArg<TestResult>>();\r
+\r
+       @Override\r
+       public void executeActions(String mode) {\r
+               if (!mode.equals(StructureRegistry.READ)) {\r
+                       for (SpringArg<TestResult> result : results) {\r
+                               try {\r
+                                       result.getInstance().close();\r
+                               } catch (RuntimeException e) {\r
+                                       log.error("Could not close result "\r
+                                                       + (result.getBean() != null ? result.getBean()\r
+                                                                       : result.getAntref()), e);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       public SpringArg<TestResult> createResult() {\r
+               SpringArg<TestResult> result = new SpringArg<TestResult>();\r
+               results.add(result);\r
+               return result;\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcReportTask.java
new file mode 100644 (file)
index 0000000..7587762
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.slc.ant.test;\r
+\r
+import org.argeo.slc.ant.structure.SAwareTask;\r
+import org.argeo.slc.core.structure.StructureAware;\r
+import org.argeo.slc.core.structure.StructureRegistry;\r
+import org.argeo.slc.core.test.TestReport;\r
+import org.argeo.slc.core.test.TestResult;\r
+\r
+/** Ant tasks generating a report. */\r
+public class SlcReportTask extends SAwareTask {\r
+       private String result;\r
+       private String report;\r
+\r
+       @Override\r
+       public void executeActions(String mode) {\r
+               if (!mode.equals(StructureRegistry.READ)) {\r
+                       TestResult testResult = null;\r
+                       if (result != null) {\r
+                               testResult = (TestResult) getContext().getBean(result);\r
+                       }\r
+                       TestReport testReport = (TestReport) getContext().getBean(report);\r
+                       if (testReport instanceof StructureAware) {\r
+                               ((StructureAware) testReport).notifyCurrentPath(getRegistry(),\r
+                                               null);\r
+                       }\r
+                       testReport.generateTestReport(testResult);\r
+               }\r
+       }\r
+\r
+       /** Sets the bean name of the result to close. */\r
+       public void setResult(String bean) {\r
+               this.result = bean;\r
+       }\r
+\r
+       /** Sets the bean name of the report to generate. */\r
+       public void setReport(String report) {\r
+               this.report = report;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/SlcTestTask.java
new file mode 100644 (file)
index 0000000..66444f1
--- /dev/null
@@ -0,0 +1,165 @@
+package org.argeo.slc.ant.test;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.apache.tools.ant.BuildException;\r
+import org.argeo.slc.ant.AntConstants;\r
+import org.argeo.slc.ant.spring.SpringArg;\r
+import org.argeo.slc.ant.structure.SAwareTask;\r
+import org.argeo.slc.core.deploy.DeployedSystem;\r
+import org.argeo.slc.core.process.SlcExecution;\r
+import org.argeo.slc.core.structure.StructureAware;\r
+import org.argeo.slc.core.structure.tree.TreeSPath;\r
+import org.argeo.slc.core.test.ExecutableTestRun;\r
+import org.argeo.slc.core.test.SimpleResultPart;\r
+import org.argeo.slc.core.test.SimpleTestResult;\r
+import org.argeo.slc.core.test.SimpleTestRun;\r
+import org.argeo.slc.core.test.TestData;\r
+import org.argeo.slc.core.test.TestDefinition;\r
+import org.argeo.slc.core.test.TestResult;\r
+import org.argeo.slc.core.test.TestResultPart;\r
+import org.argeo.slc.core.test.TestStatus;\r
+import org.argeo.slc.core.test.WritableTestRun;\r
+import org.argeo.slc.spring.SpringUtils;\r
+import org.springframework.beans.BeansException;\r
+\r
+/** Ant task wrapping a test run. */\r
+public class SlcTestTask extends SAwareTask {\r
+       private Log log = LogFactory.getLog(SlcTestTask.class);\r
+\r
+       private String testRunBean = null;\r
+\r
+       private SpringArg<TestDefinition> testDefinitionArg;\r
+       private SpringArg<TestData> testDataArg;\r
+       private SpringArg<DeployedSystem> deployedSystemArg;\r
+       private SpringArg<TestResult> testResultArg;\r
+\r
+       @Override\r
+       public void executeActions(String mode) throws BuildException {\r
+               // find test run\r
+               final String testRunBeanT;\r
+               if (testRunBean != null) {\r
+                       testRunBeanT = testRunBean;\r
+               } else {\r
+                       testRunBeanT = getProject().getProperty(\r
+                                       AntConstants.DEFAULT_TEST_RUN_PROPERTY);\r
+               }\r
+               WritableTestRun testRun = null;\r
+\r
+               if (testRunBeanT != null) {\r
+                       try {\r
+                               testRun = (WritableTestRun) getContext().getBean(testRunBeanT);\r
+                               if (log.isTraceEnabled())\r
+                                       log.trace("Load test run bean from bean name "\r
+                                                       + testRunBeanT);\r
+                       } catch (BeansException e) {\r
+                               // silent, will try defaults\r
+                       }\r
+               }\r
+\r
+               if (testRun == null) {\r
+                       testRun = loadSingleFromContext(WritableTestRun.class);\r
+                       if (testRun == null) {\r
+                               testRun = new SimpleTestRun();\r
+                               log.trace("Created default simple test run");\r
+                       } else {\r
+                               if (log.isTraceEnabled())\r
+                                       log.trace("Load test run from scanning Spring context");\r
+                       }\r
+               }\r
+\r
+               // set overridden references\r
+               if (testDataArg != null) {\r
+                       testRun.setTestData(testDataArg.getInstance());\r
+                       log.trace("Overrides test data");\r
+               }\r
+\r
+               if (testDefinitionArg != null) {\r
+                       testRun.setTestDefinition(testDefinitionArg.getInstance());\r
+                       log.trace("Overrides test definition");\r
+               }\r
+\r
+               if (deployedSystemArg != null) {\r
+                       testRun.setDeployedSystem(deployedSystemArg.getInstance());\r
+                       log.trace("Overrides deployed system");\r
+               }\r
+\r
+               if (testResultArg != null) {\r
+                       testRun.setTestResult(testResultArg.getInstance());\r
+                       log.trace("Overrides test result");\r
+               }\r
+\r
+               // notify path to test result\r
+               TestResult result = testRun.getTestResult();\r
+               if (result == null) {\r
+                       result = loadSingleFromContext(TestResult.class);\r
+                       if (result == null) {\r
+                               result = new SimpleTestResult();\r
+                               log.warn("Created default simple test result");\r
+                       } else {\r
+                               if (log.isTraceEnabled())\r
+                                       log.trace("Load test result from scanning Spring context");\r
+                       }\r
+                       testRun.setTestResult(result);\r
+               }\r
+\r
+               SlcExecution slcExecution = getSlcExecution();\r
+               testRun.notifySlcExecution(slcExecution);\r
+\r
+               if (result != null && result instanceof StructureAware) {\r
+                       ((StructureAware<TreeSPath>) result).notifyCurrentPath(\r
+                                       getRegistry(), getTreeSPath());\r
+               }\r
+\r
+               try {\r
+                       ((ExecutableTestRun) testRun).execute();\r
+               } catch (RuntimeException e) {\r
+                       if (result != null) {\r
+                               SimpleResultPart errorPart = new SimpleResultPart(\r
+                                               TestStatus.ERROR,\r
+                                               "Unexpected exception when running test", e);\r
+                               result.addResultPart(errorPart);\r
+                       }\r
+                       throw e;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * The bean name of the test run to use. If not set the default is used.\r
+        * \r
+        * @see SlcAntConfig\r
+        */\r
+       public void setTestRun(String testRunBean) {\r
+               this.testRunBean = testRunBean;\r
+       }\r
+\r
+       /** Creates sub tag. */\r
+       public SpringArg<TestDefinition> createTestDefinition() {\r
+               testDefinitionArg = new SpringArg<TestDefinition>();\r
+               // only test definitions can add to path\r
+               addSAwareArg(testDefinitionArg);\r
+               return testDefinitionArg;\r
+       }\r
+\r
+       /** Creates sub tag. */\r
+       public SpringArg<TestData> createTestData() {\r
+               testDataArg = new SpringArg<TestData>();\r
+               return testDataArg;\r
+       }\r
+\r
+       /** Creates sub tag. */\r
+       public SpringArg<DeployedSystem> createDeployedSystem() {\r
+               deployedSystemArg = new SpringArg<DeployedSystem>();\r
+               return deployedSystemArg;\r
+       }\r
+\r
+       /** Creates sub tag. */\r
+       public SpringArg<TestResult> createTestResult() {\r
+               testResultArg = new SpringArg<TestResult>();\r
+               return testResultArg;\r
+       }\r
+\r
+       protected <T> T loadSingleFromContext(Class<T> clss) {\r
+               return SpringUtils.loadSingleFromContext(getContext(), clss);\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/test/package.html
new file mode 100644 (file)
index 0000000..179159b
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<head></head>\r
+<body>\r
+Integration of SLC Test in Ant.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/AntSlcApplicationTestCase.java
new file mode 100644 (file)
index 0000000..7b28123
--- /dev/null
@@ -0,0 +1,34 @@
+package org.argeo.slc.ant.unit;
+
+import junit.framework.TestCase;
+
+import org.argeo.slc.ant.AntExecutionContext;
+import org.argeo.slc.cli.DefaultSlcRuntime;
+import org.argeo.slc.runtime.SlcExecutionOutput;
+
+public abstract class AntSlcApplicationTestCase extends TestCase implements
+               SlcExecutionOutput<AntExecutionContext> {
+
+       /** To be overriden */
+       public void postExecution(AntExecutionContext executionContext) {
+
+       }
+
+       protected String getRootDir() {
+               return System.getProperty("slc.rootDir", "src/main/slc/root");
+       }
+
+       protected String getAbsoluteScript(String relative) {
+               return getRootDir() + '/' + relative;
+       }
+
+       protected void execute(String relativeScript) {
+               execute(relativeScript, null);
+       }
+
+       protected void execute(String relativeScript, String targets) {
+               new DefaultSlcRuntime().executeScript(
+                               getAbsoluteScript(relativeScript), targets, this);
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ant/unit/MinimalAntClasspathTestCase.java
new file mode 100644 (file)
index 0000000..bf6c0b6
--- /dev/null
@@ -0,0 +1,37 @@
+package org.argeo.slc.ant.unit;
+
+import java.io.File;
+import java.util.UUID;
+
+import org.argeo.slc.ant.AntConstants;
+import org.argeo.slc.ant.AntExecutionContext;
+import org.argeo.slc.ant.AntSlcApplication;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.runtime.SlcExecutionOutput;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.springframework.core.io.FileSystemResource;
+
+public class MinimalAntClasspathTestCase extends AbstractSpringTestCase
+               implements SlcExecutionOutput<AntExecutionContext> {
+       protected void execute(String scriptPath) {
+               AntSlcApplication slcApp = new AntSlcApplication();
+               slcApp.setRootDir(new FileSystemResource(new File("src/test/resources")
+                               .getAbsolutePath()
+                               + File.separator));
+               slcApp.setWorkDir(new File(System.getProperty("java.io.tmpdir")));
+               slcApp.setParentContext(getContext());
+
+               SlcExecution slcExecution = new SlcExecution();
+               slcExecution.setUuid(UUID.randomUUID().toString());
+               slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_FILE,
+                               scriptPath);
+               slcExecution.setUser("user");
+
+               slcApp.execute(slcExecution, null, null, this);
+       }
+
+       /** to be overridden */
+       public void postExecution(AntExecutionContext executionContext) {
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/DefaultSlcRuntime.java
new file mode 100644 (file)
index 0000000..841a823
--- /dev/null
@@ -0,0 +1,229 @@
+package org.argeo.slc.cli;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.AntExecutionContext;
+import org.argeo.slc.ant.AntSlcApplication;
+import org.argeo.slc.ant.AntConstants;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.process.SlcExecution;
+import org.argeo.slc.runtime.SlcExecutionOutput;
+import org.argeo.slc.spring.SpringUtils;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+
+public class DefaultSlcRuntime {
+       private final static Log log = LogFactory.getLog(DefaultSlcRuntime.class);
+
+       public final static String SLC_ROOT_FILE_NAME = "slcRoot.properties";
+
+       /**
+        * Simplified execution with default runtime, default target, and no
+        * properties/reference arguments.
+        * 
+        * @param script
+        *            path to the script
+        * @param executionOutput
+        *            output
+        * 
+        * @see #executeScript(String, String, String, Properties, Map,
+        *      SlcExecutionOutput)
+        */
+       public void executeScript(String script,
+                       SlcExecutionOutput<AntExecutionContext> executionOutput) {
+               executeScript(null, script, null, null, null, executionOutput);
+       }
+
+       /**
+        * Simplified execution with default runtime, and no properties/reference
+        * arguments.
+        * 
+        * @param script
+        *            path to the script
+        * @param targets
+        *            comma separated list of targets
+        * @param executionOutput
+        *            output
+        * @see #executeScript(String, String, String, Properties, Map,
+        *      SlcExecutionOutput)
+        */
+       public void executeScript(String script, String targets,
+                       SlcExecutionOutput<AntExecutionContext> executionOutput) {
+               executeScript(null, script, targets, null, null, executionOutput);
+       }
+
+       public void executeScript(String runtime, String script, String targets,
+                       Properties properties, Map<String, Object> references,
+                       SlcExecutionOutput<AntExecutionContext> executionOutput) {
+
+               Resource scriptRes = findScript(script);
+               Resource slcRootFile = findSlcRootFile(scriptRes);
+               if (slcRootFile == null)
+                       throw new SlcException(
+                                       "Could not find any SLC root file, "
+                                                       + "please configure one at the root of your scripts hierarchy.");
+
+               SlcExecution slcExecution = createSlcExecution(runtime, slcRootFile,
+                               scriptRes, targets);
+
+               AntSlcApplication application = getApplication(slcRootFile);
+               application.execute(slcExecution, properties, references,
+                               executionOutput);
+       }
+
+       protected Resource findScript(String scriptStr) {
+               Resource scriptRes;
+               if (new File(scriptStr).exists()) {
+                       scriptRes = new FileSystemResource(scriptStr);
+               } else {
+                       scriptRes = new DefaultResourceLoader(SlcMain.class
+                                       .getClassLoader()).getResource(scriptStr);
+               }
+               return scriptRes;
+       }
+
+       protected SlcExecution createSlcExecution(String runtimeStr,
+                       Resource slcRootFile, Resource script, String targets) {
+               SlcExecution slcExecution = new SlcExecution();
+               slcExecution.setUuid(UUID.randomUUID().toString());
+               try {
+                       slcExecution.setHost(InetAddress.getLocalHost().getHostName());
+               } catch (UnknownHostException e) {
+                       slcExecution.setHost(SlcExecution.UNKOWN_HOST);
+               }
+
+               slcExecution.setType(AntConstants.EXECTYPE_SLC_ANT);
+
+               slcExecution.setUser(System.getProperty("user.name"));
+
+               if (runtimeStr != null)
+                       slcExecution.getAttributes().put(AntConstants.EXECATTR_RUNTIME,
+                                       runtimeStr);
+               String scriptRelativePath = SpringUtils.extractRelativePath(SpringUtils
+                               .getParent(slcRootFile), script);
+
+               slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_FILE,
+                               scriptRelativePath);
+               if (targets != null)
+                       slcExecution.getAttributes().put(AntConstants.EXECATTR_ANT_TARGETS,
+                                       targets);
+
+               slcExecution.setStatus(SlcExecution.STATUS_SCHEDULED);
+               return slcExecution;
+       }
+
+       protected AntSlcApplication getApplication(Resource slcRootFile) {
+               AntSlcApplication application = new AntSlcApplication();
+               InputStream inRootFile = null;
+               try {
+                       // Remove basedir property in order to avoid conflict with Maven
+                       // if (all.containsKey("basedir"))
+                       // all.remove("basedir");
+
+                       inRootFile = slcRootFile.getInputStream();
+                       Properties rootProps = loadFile(inRootFile);
+
+                       Resource confDir = null;
+                       File workDir = null;
+                       // Root dir
+                       final Resource rootDir = SpringUtils.getParent(slcRootFile);
+
+                       // Conf dir
+                       String confDirStr = rootProps
+                                       .getProperty(AntConstants.CONF_DIR_PROPERTY);
+                       if (confDirStr != null)
+                               confDir = new DefaultResourceLoader(application.getClass()
+                                               .getClassLoader()).getResource(confDirStr);
+
+                       if (confDir == null || !confDir.exists()) {
+                               // confDir = rootDir.createRelative("../conf");
+                               confDir = SpringUtils.getParent(rootDir)
+                                               .createRelative("conf/");
+                       }
+
+                       // Work dir
+                       String workDirStr = rootProps
+                                       .getProperty(AntConstants.WORK_DIR_PROPERTY);
+                       if (workDirStr != null) {
+                               workDir = new File(workDirStr);
+                       }
+
+                       if (workDir == null || !workDir.exists()) {
+                               try {
+                                       File rootDirAsFile = rootDir.getFile();
+                                       workDir = new File(rootDirAsFile.getParent()
+                                                       + File.separator + "work").getCanonicalFile();
+                               } catch (IOException e) {
+                                       workDir = new File(System.getProperty("java.io.tmpdir")
+                                                       + File.separator + "slcExecutions" + File.separator
+                                                       + slcRootFile.getURL().getPath());
+                                       log.debug("Root dir is not a file: " + e.getMessage()
+                                                       + ", creating work dir in temp: " + workDir);
+                               }
+                               workDir.mkdirs();
+                       }
+
+                       application.setConfDir(confDir);
+                       application.setRootDir(rootDir);
+                       application.setWorkDir(workDir);
+
+                       return application;
+               } catch (IOException e) {
+                       throw new SlcException(
+                                       "Could not prepare SLC application for root file "
+                                                       + slcRootFile, e);
+               } finally {
+                       IOUtils.closeQuietly(inRootFile);
+               }
+       }
+
+       /**
+        * Recursively scans directories downwards until it find a file name as
+        * defined by {@link #SLC_ROOT_FILE_NAME}.
+        */
+       protected Resource findSlcRootFile(Resource currDir) {
+               if (log.isTraceEnabled())
+                       log.trace("Look for SLC root file in " + currDir);
+
+               try {
+                       Resource slcRootFile = currDir.createRelative(SLC_ROOT_FILE_NAME);
+                       if (slcRootFile.exists()) {
+                               if (log.isDebugEnabled())
+                                       log.debug("Found SLC root file: " + slcRootFile);
+                               return slcRootFile;
+                       } else {
+                               String currPath = currDir.getURL().getPath();
+                               if (currPath.equals("/") || currPath.equals("")) {
+                                       return null;
+                               } else {
+                                       return findSlcRootFile(SpringUtils.getParent(currDir));
+                               }
+                       }
+               } catch (IOException e) {
+                       throw new SlcException("Problem when looking in SLC root file in "
+                                       + currDir, e);
+               }
+       }
+
+       /** Loads the content of a file as <code>Properties</code>. */
+       private Properties loadFile(InputStream in) {
+               Properties p = new Properties();
+               try {
+                       p.load(in);
+               } catch (IOException e) {
+                       throw new SlcException("Cannot read SLC root file", e);
+               }
+               return p;
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/cli/SlcMain.java
new file mode 100644 (file)
index 0000000..cf52581
--- /dev/null
@@ -0,0 +1,232 @@
+package org.argeo.slc.cli;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.AntConstants;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.logging.Log4jUtils;
+
+public class SlcMain {
+       public enum Mode {
+               single, agent
+       }
+
+       private static Log log = null;
+
+       private final static String BOOTSTRAP_LOG4J_CONFIG = "org/argeo/slc/cli/bootstrapLog4j.properties";
+
+       private final static Option modeOpt = OptionBuilder.withLongOpt("mode")
+                       .withArgName("mode").hasArg().withDescription(
+                                       "SLC execution mode, one of: " + listModeValues()).create(
+                                       'm');
+
+       private final static Option propertyOpt = OptionBuilder.withLongOpt(
+                       "property").withArgName("prop1=val1,prop2=val2").hasArgs()
+                       .withValueSeparator(',').withDescription(
+                                       "use value for given property").create('p');
+
+       private final static Option propertiesOpt = OptionBuilder.withLongOpt(
+                       "properties").withArgName("properties file").hasArgs()
+                       .withValueSeparator(',').withDescription(
+                                       "load properties from file (-p has priority)").create('P');
+
+       private final static Option scriptOpt = OptionBuilder.withLongOpt("script")
+                       .withArgName("script").hasArg().withDescription(
+                                       "SLC script to execute").create('s');
+
+       private final static Option targetsOpt = OptionBuilder.withLongOpt(
+                       "targets").withArgName("targets").hasArg().withDescription(
+                       "Targets to execute").create('t');
+
+       private final static Option runtimeOpt = OptionBuilder.withLongOpt(
+                       "runtime").withArgName("runtime").hasArg().withDescription(
+                       "Runtime to use, either a full path or relative to slc app conf dir: "
+                                       + "<conf dir>/runtime/<runtime>/.xml").create('r');
+
+       private final static Options options;
+
+       private final static String commandName = "slc";
+
+       static {
+               options = new Options();
+               options.addOption(modeOpt);
+               options.addOption(scriptOpt);
+               options.addOption(targetsOpt);
+               options.addOption(propertyOpt);
+               options.addOption(propertiesOpt);
+               options.addOption(runtimeOpt);
+       }
+
+       public static void main(String[] args) {
+               Mode mode = null;
+               Properties properties = new Properties();
+               String script = null;
+               String targets = null;
+               String runtimeStr = null;
+
+               try {
+
+                       CommandLineParser clParser = new GnuParser();
+                       CommandLine cl = clParser.parse(options, args);
+
+                       // Mode
+                       String modeStr = cl.getOptionValue(modeOpt.getOpt());
+                       if (modeStr == null) {
+                               mode = Mode.single;
+                       } else {
+                               try {
+                                       mode = Mode.valueOf(modeStr);
+                               } catch (IllegalArgumentException e) {
+                                       throw new SlcException("Unrecognized mode '" + modeStr
+                                                       + "'", e);
+                               }
+                       }
+
+                       // Script
+                       if (mode.equals(Mode.single)) {
+                               if (!cl.hasOption(scriptOpt.getOpt()))
+                                       throw new SlcException("Mode " + Mode.single
+                                                       + " requires option '" + scriptOpt.getLongOpt()
+                                                       + "'");
+                               script = cl.getOptionValue(scriptOpt.getOpt());
+
+                               // Targets
+                               if (cl.hasOption(targetsOpt.getOpt()))
+                                       targets = cl.getOptionValue(targetsOpt.getOpt());
+                       }
+
+                       // Properties
+                       if (cl.hasOption(propertiesOpt.getOpt())) {
+                               for (String propertyFile : cl.getOptionValues(propertiesOpt
+                                               .getOpt())) {
+                                       loadPropertyFile(properties, propertyFile);
+                               }
+                       }
+                       if (cl.hasOption(propertyOpt.getOpt())) {
+                               for (String property : cl.getOptionValues(propertyOpt.getOpt())) {
+                                       addProperty(properties, property);
+                               }
+                       }
+
+                       // Runtime
+                       if (cl.hasOption(runtimeOpt.getOpt())) {
+                               runtimeStr = cl.getOptionValue(runtimeOpt.getOpt());
+                       }
+               } catch (ParseException e) {
+                       System.err.println("Problem with command line arguments. "
+                                       + e.getMessage());
+                       badExit();
+               } catch (SlcException e) {
+                       System.err.println(e.getMessage());
+                       badExit();
+               } catch (Exception e) {
+                       System.err.println("Unexpected exception when bootstrapping.");
+                       e.printStackTrace();
+                       badExit();
+               }
+
+               // Initializes logging and log arguments
+               initLogging(properties);
+               if (log.isDebugEnabled()) {
+                       log.debug("Mode: " + mode);
+                       if (runtimeStr != null)
+                               log.debug("Runtime: " + runtimeStr);
+                       log.debug("User properties: " + properties);
+                       if (script != null)
+                               log.debug("Script: " + script);
+                       if (targets != null)
+                               log.debug("Targets: " + targets);
+               }
+
+               // Execution
+               if (mode.equals(Mode.single)) {
+                       try {
+                               DefaultSlcRuntime runtime = new DefaultSlcRuntime();
+                               runtime.executeScript(runtimeStr, script, targets, properties,
+                                               null, null);
+                               //System.exit(0);
+                       } catch (SlcException e) {
+                               log.error("SLC client terminated with an error: ", e);
+                               System.exit(1);
+                       }
+               }
+       }
+
+       public static void printUsage() {
+               new HelpFormatter().printHelp(commandName, options, true);
+       }
+
+       private static String listModeValues() {
+               StringBuffer buf = new StringBuffer("");
+               for (Mode mode : Mode.values()) {
+                       buf.append(mode).append(", ");
+               }
+               String str = buf.toString();
+               // unsafe, but there will be at least one value in the enum
+               return str.substring(0, str.length() - 2);
+       }
+
+       protected static void addProperty(Properties properties, String property) {
+               int eqIndex = property.indexOf('=');
+               if (eqIndex == 0)
+                       throw new SlcException("Badly formatted property " + property);
+
+               if (eqIndex > 0) {
+                       String key = property.substring(0, eqIndex);
+                       String value = property.substring(eqIndex + 1);
+                       properties.setProperty(key, value);
+
+               } else {
+                       properties.setProperty(property, "true");
+               }
+       }
+
+       protected static void loadPropertyFile(Properties properties,
+                       String propertyFile) {
+               FileInputStream in = null;
+               try {
+                       in = new FileInputStream(propertyFile);
+                       properties.load(in);
+               } catch (Exception e) {
+                       throw new SlcException("Could not load proeprty file "
+                                       + propertyFile);
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       private static void initLogging(Properties userProperties) {
+               System.setProperty("log4j.defaultInitOverride", "true");
+
+               // Add log4j user properties to System properties
+               for (Object obj : userProperties.keySet()) {
+                       String key = obj.toString();
+                       if (key.startsWith("log4j.")) {
+                               System.setProperty(key, userProperties.getProperty(key));
+                       }
+               }
+               Log4jUtils.initLog4j(System.getProperty("log4j.configuration",
+                               "classpath:" + BOOTSTRAP_LOG4J_CONFIG));
+               log = LogFactory.getLog(SlcMain.class);
+
+       }
+
+       private static void badExit() {
+               printUsage();
+               System.exit(1);
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestData.java
new file mode 100644 (file)
index 0000000..ee471cc
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.slc.lib.detached;
+
+import org.argeo.slc.core.test.context.DefaultContextTestData;
+
+public class DetachedTestData extends DefaultContextTestData {
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedTestDefinition.java
new file mode 100644 (file)
index 0000000..becb4f8
--- /dev/null
@@ -0,0 +1,144 @@
+package org.argeo.slc.lib.detached;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.structure.tree.TreeSRelatedHelper;
+import org.argeo.slc.core.test.SimpleResultPart;
+import org.argeo.slc.core.test.TestDefinition;
+import org.argeo.slc.core.test.TestResult;
+import org.argeo.slc.core.test.TestRun;
+import org.argeo.slc.core.test.TestStatus;
+import org.argeo.slc.core.test.context.ContextUtils;
+import org.argeo.slc.detached.DetachedAnswer;
+import org.argeo.slc.detached.DetachedClient;
+import org.argeo.slc.detached.DetachedRequest;
+import org.argeo.slc.detached.DetachedStep;
+import org.argeo.slc.detached.ui.UiStep;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.BeanInitializationException;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+
+public class DetachedTestDefinition extends TreeSRelatedHelper implements
+               TestDefinition, BeanNameAware, BeanFactoryAware, InitializingBean {
+       private final static Log log = LogFactory
+                       .getLog(DetachedTestDefinition.class);
+
+       private DetachedStep step;
+       private DetachedClient client;
+
+       // Spring properties
+       private String testDefBeanName = null;
+       private BeanDefinitionRegistry beanDefinitionRegistry = null;
+       private String stepRef = null;
+
+       public void execute(TestRun testRun) {
+               // Look for step bean name
+               String stepBeanNameT = null;
+               if (this.stepRef == null && step != null) {
+                       if (step instanceof UiStep) {
+                               stepBeanNameT = ((UiStep) step).getBeanName();
+                       } else {
+                               // Introspects bean factory in order to find step bean name
+                               BeanDefinition thisBeanDef = beanDefinitionRegistry
+                                               .getBeanDefinition(testDefBeanName);
+                               PropertyValue propValue = thisBeanDef.getPropertyValues()
+                                               .getPropertyValue("step");
+                               Object stepBeanRef = propValue.getValue();
+                               BeanReference ref = (BeanReference) stepBeanRef;
+                               stepBeanNameT = ref.getBeanName();
+                       }
+               } else if (this.stepRef != null) {
+                       stepBeanNameT = this.stepRef;
+               }
+
+               // Execute
+               DetachedRequest request = new DetachedRequest();
+               request.setPath(getBasePath().toString());
+               request.setUuid(UUID.randomUUID().toString());
+               request.setRef(stepBeanNameT);
+
+               DetachedTestData testData = testRun.getTestData();
+               if (testData != null) {
+                       Map<String, Object> values = testData.getValues();
+                       Properties inputParameters = new Properties();
+                       inputParameters.putAll(values);// TODO: check conversions to string
+                       request.setProperties(inputParameters);
+               }
+
+               try {
+                       client.sendRequest(request);
+               } catch (Exception e) {
+                       throw new SlcException("Could not send request for step "
+                                       + stepBeanNameT, e);
+               }
+
+               try {
+                       DetachedAnswer answer = client.receiveAnswer();
+                       if (answer.getStatus() == DetachedAnswer.ERROR)
+                               throw new SlcException("Error when executing step "
+                                               + answer.getUuid() + ": " + answer.getLog());
+                       else
+                               log.info("Received answer for '" + request.getRef() + "' ("
+                                               + answer.getStatusAsString() + "):" + answer.getLog());
+
+                       if (testData != null) {
+                               Properties outputParameters = answer.getProperties();
+                               for (Object key : outputParameters.keySet())
+                                       testData.getValues().put(key.toString(),
+                                                       outputParameters.get(key));
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Could not receive answer #"
+                                       + request.getUuid() + " for step " + stepBeanNameT, e);
+               }
+
+               if (testData != null) {
+                       ContextUtils.compareReachedExpected(testData, testRun
+                                       .getTestResult(), this);
+               } else {
+                       ((TestResult)testRun.getTestResult()).addResultPart(
+                                       new SimpleResultPart(TestStatus.PASSED, "Step "
+                                                       + stepBeanNameT + " executed successfully"));
+               }
+       }
+
+       public void setBeanName(String name) {
+               this.testDefBeanName = name;
+       }
+
+       public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+               if (beanFactory instanceof BeanDefinitionRegistry)
+                       beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory;
+               else
+                       throw new BeanInitializationException(
+                                       "Require BeanDefinitionRegistry");
+       }
+
+       public void afterPropertiesSet() throws Exception {
+       }
+
+       public void setStep(DetachedStep step) {
+               this.step = step;
+       }
+
+       public void setClient(DetachedClient client) {
+               this.client = client;
+       }
+
+       public void setStepRef(String stepBeanName) {
+               this.stepRef = stepBeanName;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/lib/detached/DetachedXmlConverterSpring.java
new file mode 100644 (file)
index 0000000..799b473
--- /dev/null
@@ -0,0 +1,68 @@
+package org.argeo.slc.lib.detached;
+
+import java.io.IOException;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.detached.DetachedAnswer;
+import org.argeo.slc.detached.DetachedCommunication;
+import org.argeo.slc.detached.DetachedException;
+import org.argeo.slc.detached.DetachedRequest;
+import org.argeo.slc.detached.DetachedXmlConverter;
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.Unmarshaller;
+import org.springframework.oxm.XmlMappingException;
+import org.springframework.xml.validation.XmlValidator;
+import org.xml.sax.InputSource;
+
+public class DetachedXmlConverterSpring implements DetachedXmlConverter {
+       private Marshaller marshaller;
+       private Unmarshaller unmarshaller;
+
+       public void marshallCommunication(DetachedCommunication detCom,
+                       Result result) {
+               if (detCom instanceof DetachedRequest) {
+                       marshallRequest((DetachedRequest) detCom, result);
+               } else if (detCom instanceof DetachedAnswer) {
+                       marshallAnswer((DetachedAnswer) detCom, result);
+               } else {
+                       throw new DetachedException("Unkown communication type "
+                                       + detCom.getClass());
+               }
+       }
+
+       public DetachedCommunication unmarshallCommunication(Source source) {
+               try {
+                       return (DetachedCommunication) unmarshaller.unmarshal(source);
+               } catch (Exception e) {
+                       throw new SlcException("Could not unmarshall", e);
+               }
+       }
+
+       public void marshallRequest(DetachedRequest request, Result result) {
+               try {
+                       marshaller.marshal(request, result);
+               } catch (Exception e) {
+                       throw new SlcException("Could not marshall", e);
+               }
+       }
+
+       public void marshallAnswer(DetachedAnswer answer, Result result) {
+               try {
+                       marshaller.marshal(answer, result);
+               } catch (Exception e) {
+                       throw new SlcException("Could not marshall", e);
+               }
+       }
+
+       public void setMarshaller(Marshaller marshaller) {
+               this.marshaller = marshaller;
+       }
+
+       public void setUnmarshaller(Unmarshaller unmarshaller) {
+               this.unmarshaller = unmarshaller;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenDeployEnvironment.java
new file mode 100644 (file)
index 0000000..744aa2c
--- /dev/null
@@ -0,0 +1,73 @@
+package org.argeo.slc.maven;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.AntRunner;
+import org.argeo.slc.core.SlcException;
+import org.argeo.slc.core.deploy.DeployEnvironment;
+
+public class MavenDeployEnvironment {/*implements DeployEnvironment {
+       private static final Log log = LogFactory
+                       .getLog(MavenDeployEnvironment.class);
+       private MavenManager mavenManager;
+
+       public void unpackTo(Object packg, File targetLocation,
+                       Map<String, String> filter) {
+               File packageLocation;
+               String type = null;
+               String removeRootDir = "enabled";
+               if (packg instanceof MavenFile) {
+                       packageLocation = mavenManager
+                                       .getPackageLocation((MavenFile) packg);
+                       type = ((MavenFile) packg).getType();
+               } else if (packg instanceof File) {
+                       packageLocation = (File) packg;
+                       // TODO: type based on extension
+               } else {
+                       throw new SlcException("Unrecognized package type "
+                                       + packg.getClass());
+               }
+               if (log.isDebugEnabled()) {
+                       log.debug("Unpack " + packageLocation + " of type " + type + " to "
+                                       + targetLocation);
+               }
+
+               try {
+                       File tempDir = new File("/tmp/" + UUID.randomUUID().toString());
+                       tempDir.mkdirs();
+                       targetLocation.mkdirs();
+                       Properties props = new Properties();
+                       props.setProperty("dest", targetLocation.getAbsolutePath());
+                       props.setProperty("src", packageLocation.getAbsolutePath());
+                       props.setProperty("tempDir", tempDir.getAbsolutePath());
+                       props.setProperty("removeRootDir", removeRootDir);
+
+                       URL antUrl = getClass().getClassLoader().getResource(
+                                       "org/argeo/slc/support/deploy/ant/build.xml");
+
+                       if (type == null || type.equals("zip")) {
+                               new AntRunner(antUrl, "deployZip", props).run();
+                       } else if (type.equals("tar.gz")) {
+                               new AntRunner(antUrl, "deployTarGz", props).run();
+                       } else {
+                               throw new SlcException("Unknow package type " + type);
+                       }
+               } catch (SlcException e) {
+                       throw e;
+               } catch (Exception e) {
+                       throw new SlcException("Cannot unpack package " + packg + " to "
+                                       + targetLocation, e);
+               }
+       }
+
+       public void setMavenManager(MavenManager mavenManager) {
+               this.mavenManager = mavenManager;
+       }
+*/
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenFile.java
new file mode 100644 (file)
index 0000000..31c6385
--- /dev/null
@@ -0,0 +1,63 @@
+package org.argeo.slc.maven;\r
+\r
+import org.argeo.slc.core.build.Distribution;\r
+import org.argeo.slc.core.deploy.DeploymentData;\r
+\r
+public class MavenFile implements Distribution, DeploymentData {\r
+       private String groupId;\r
+       private String artifactId;\r
+       private String version;\r
+       private String type;\r
+       private String classifier;\r
+\r
+       private String distributionId;\r
+\r
+       public String getDistributionId() {\r
+               return distributionId;\r
+       }\r
+\r
+       public void setDistributionId(String distributionId) {\r
+               this.distributionId = distributionId;\r
+       }\r
+\r
+       public String getGroupId() {\r
+               return groupId;\r
+       }\r
+\r
+       public void setGroupId(String groupId) {\r
+               this.groupId = groupId;\r
+       }\r
+\r
+       public String getArtifactId() {\r
+               return artifactId;\r
+       }\r
+\r
+       public void setArtifactId(String artifactId) {\r
+               this.artifactId = artifactId;\r
+       }\r
+\r
+       public String getVersion() {\r
+               return version;\r
+       }\r
+\r
+       public void setVersion(String version) {\r
+               this.version = version;\r
+       }\r
+\r
+       public String getType() {\r
+               return type;\r
+       }\r
+\r
+       public void setType(String type) {\r
+               this.type = type;\r
+       }\r
+\r
+       public String getClassifier() {\r
+               return classifier;\r
+       }\r
+\r
+       public void setClassifier(String classifier) {\r
+               this.classifier = classifier;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/MavenManager.java
new file mode 100644 (file)
index 0000000..9908c3b
--- /dev/null
@@ -0,0 +1,104 @@
+package org.argeo.slc.maven;\r
+\r
+import java.io.File;\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+//import org.apache.maven.artifact.Artifact;\r
+//import org.apache.maven.artifact.repository.ArtifactRepository;\r
+//import org.apache.maven.embedder.MavenEmbedder;\r
+//import org.apache.maven.embedder.MavenEmbedderException;\r
+\r
+import org.argeo.slc.core.SlcException;\r
+\r
+public class MavenManager {/* FIXME\r
+       private final Log log = LogFactory.getLog(getClass());\r
+\r
+       private String localRepositoryPath;\r
+\r
+       private ArtifactRepository localRepository;\r
+       private List<ArtifactRepository> remoteRepositoriesInternal;\r
+       private List<RemoteRepository> remoteRepositories = new Vector<RemoteRepository>();\r
+\r
+       private MavenEmbedder mavenEmbedder;\r
+\r
+       public void init() {\r
+               try {\r
+                       mavenEmbedder = new MavenEmbedder();\r
+                       mavenEmbedder.setOffline(true);\r
+                       mavenEmbedder.setClassLoader(Thread.currentThread()\r
+                                       .getContextClassLoader());\r
+                       mavenEmbedder.start();\r
+\r
+                       mavenEmbedder.setLocalRepositoryDirectory(new File(\r
+                                       localRepositoryPath));\r
+\r
+                       localRepository = mavenEmbedder.getLocalRepository();\r
+\r
+                       remoteRepositoriesInternal = new Vector<ArtifactRepository>();\r
+                       for (RemoteRepository remoteRepository : remoteRepositories) {\r
+\r
+                               ArtifactRepository repository = mavenEmbedder.createRepository(\r
+                                               remoteRepository.getUrl(), remoteRepository.getId());\r
+                               remoteRepositoriesInternal.add(repository);\r
+                       }\r
+\r
+               } catch (Exception e) {\r
+                       throw new SlcException("Cannot initialize Maven manager", e);\r
+               }\r
+       }\r
+\r
+       private Artifact resolve(MavenFile mavenDistribution) {\r
+               try {\r
+                       Artifact artifact;\r
+                       if (mavenDistribution.getClassifier() == null) {\r
+                               artifact = mavenEmbedder.createArtifact(mavenDistribution\r
+                                               .getGroupId(), mavenDistribution.getArtifactId(),\r
+                                               mavenDistribution.getVersion(),\r
+                                               Artifact.SCOPE_PROVIDED, mavenDistribution.getType());\r
+                       } else {\r
+                               artifact = mavenEmbedder.createArtifactWithClassifier(\r
+                                               mavenDistribution.getGroupId(), mavenDistribution\r
+                                                               .getArtifactId(), mavenDistribution\r
+                                                               .getVersion(), mavenDistribution.getType(),\r
+                                               mavenDistribution.getClassifier());\r
+                       }\r
+\r
+                       mavenEmbedder.resolve(artifact, remoteRepositoriesInternal,\r
+                                       localRepository);\r
+\r
+                       return artifact;\r
+               } catch (Exception e) {\r
+                       throw new SlcException("Cannot resolve artifact.", e);\r
+               }\r
+       }\r
+\r
+       public File getPackageLocation(MavenFile mavenDistribution) {\r
+               return resolve(mavenDistribution).getFile();\r
+       }\r
+\r
+       public void destroy() {\r
+               try {\r
+                       if (mavenEmbedder != null) {\r
+                               mavenEmbedder.stop();\r
+                       }\r
+               } catch (MavenEmbedderException e) {\r
+                       log.error("Cannot destroy Maven manager", e);\r
+               }\r
+       }\r
+\r
+       public void setLocalRepositoryPath(String localRepositoryPath) {\r
+               this.localRepositoryPath = localRepositoryPath;\r
+       }\r
+\r
+       public List<RemoteRepository> getRemoteRepositories() {\r
+               return remoteRepositories;\r
+       }\r
+\r
+       public void setRemoteRepositories(List<RemoteRepository> remoteRepositories) {\r
+               this.remoteRepositories = remoteRepositories;\r
+       }\r
+*/\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/maven/RemoteRepository.java
new file mode 100644 (file)
index 0000000..cbf027c
--- /dev/null
@@ -0,0 +1,23 @@
+package org.argeo.slc.maven;
+
+public class RemoteRepository {
+       private String id;
+       private String url;
+
+       public String getId() {
+               return id;
+       }
+
+       public void setId(String id) {
+               this.id = id;
+       }
+
+       public String getUrl() {
+               return url;
+       }
+
+       public void setUrl(String url) {
+               this.url = url;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/ValidatingClientInterceptor.java
new file mode 100644 (file)
index 0000000..05861d9
--- /dev/null
@@ -0,0 +1,88 @@
+package org.argeo.slc.ws.client;\r
+\r
+import java.io.IOException;\r
+\r
+import javax.xml.transform.Source;\r
+\r
+import org.springframework.ws.client.WebServiceClientException;\r
+import org.springframework.ws.client.WebServiceIOException;\r
+import org.springframework.ws.client.support.interceptor.ClientInterceptor;\r
+import org.springframework.ws.context.MessageContext;\r
+import org.springframework.xml.validation.XmlValidator;\r
+import org.xml.sax.SAXParseException;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+public class ValidatingClientInterceptor implements ClientInterceptor {\r
+       private final static Log log = LogFactory\r
+                       .getLog(ValidatingClientInterceptor.class);\r
+\r
+       private Boolean validateRequest = true;\r
+       private Boolean validateResponse = false;\r
+       private XmlValidator validator = null;\r
+\r
+       public boolean handleFault(MessageContext messageContext)\r
+                       throws WebServiceClientException {\r
+               return true;\r
+       }\r
+\r
+       public boolean handleRequest(MessageContext messageContext)\r
+                       throws WebServiceClientException {\r
+               if (validateRequest) {\r
+                       if (messageContext.getRequest() == null)\r
+                               return true;\r
+\r
+                       Source source = messageContext.getRequest().getPayloadSource();\r
+                       try {\r
+                               return validate(source);\r
+                       } catch (IOException e) {\r
+                               throw new WebServiceIOException("Cannot validate request", e);\r
+                       }\r
+               } else {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       public boolean handleResponse(MessageContext messageContext)\r
+                       throws WebServiceClientException {\r
+               if (validateResponse) {\r
+                       if (messageContext.getResponse() == null)\r
+                               return true;\r
+\r
+                       Source source = messageContext.getResponse().getPayloadSource();\r
+                       try {\r
+                               return validate(source);\r
+                       } catch (IOException e) {\r
+                               throw new WebServiceIOException("Cannot validate response", e);\r
+                       }\r
+               } else {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       protected boolean validate(Source source) throws IOException {\r
+               SAXParseException[] exceptions = validator.validate(source);\r
+               if (exceptions.length != 0) {\r
+                       for (SAXParseException ex : exceptions) {\r
+                               log.error(ex.getMessage());\r
+                       }\r
+                       return false;\r
+               } else {\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       public void setValidateRequest(Boolean validateRequest) {\r
+               this.validateRequest = validateRequest;\r
+       }\r
+\r
+       public void setValidateResponse(Boolean validateResponse) {\r
+               this.validateResponse = validateResponse;\r
+       }\r
+\r
+       public void setValidator(XmlValidator validator) {\r
+               this.validator = validator;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/client/WebServiceUtils.java
new file mode 100644 (file)
index 0000000..43ad313
--- /dev/null
@@ -0,0 +1,84 @@
+package org.argeo.slc.ws.client;\r
+\r
+import java.util.Iterator;\r
+\r
+import javax.xml.transform.Source;\r
+import javax.xml.transform.dom.DOMSource;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.springframework.ws.client.core.WebServiceTemplate;\r
+import org.springframework.ws.soap.SoapFaultDetail;\r
+import org.springframework.ws.soap.SoapFaultDetailElement;\r
+import org.springframework.ws.soap.client.SoapFaultClientException;\r
+import org.springframework.xml.transform.StringResult;\r
+import org.w3c.dom.Node;\r
+\r
+public abstract class WebServiceUtils {\r
+       private final static Log log = LogFactory.getLog(WebServiceUtils.class);\r
+\r
+       public static Object marshalSendAndReceiveSafe(WebServiceTemplate template,\r
+                       Object req) {\r
+               try {\r
+                       Object resp = marshalSendAndReceive(template, req);\r
+                       return resp;\r
+               } catch (Exception e) {\r
+                       log.error("Cannot send web servicerequest: " + e.getMessage());\r
+                       if (log.isDebugEnabled()) {\r
+                               log.debug("Webservice exception details: ", e);\r
+                       }\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       public static Object marshalSendAndReceive(WebServiceTemplate template,\r
+                       Object req) {\r
+               if (log.isTraceEnabled()) {\r
+                       try {\r
+                               StringResult result = new StringResult();\r
+                               template.getMarshaller().marshal(req, result);\r
+                               log.trace("About to send " + result);\r
+                       } catch (Exception e) {\r
+                               log.error("Cannot marshall " + req + " for logging", e);\r
+                       }\r
+               }\r
+               Object resp = template.marshalSendAndReceive(req);\r
+               return resp;\r
+       }\r
+\r
+       public static void manageSoapException(SoapFaultClientException e) {\r
+               log\r
+                               .error("WS root cause: "\r
+                                               + e.getSoapFault().getFaultStringOrReason());\r
+               if (log.isTraceEnabled()) {\r
+                       StringBuffer stack = new StringBuffer("");\r
+                       SoapFaultDetail detail = e.getSoapFault().getFaultDetail();\r
+                       if (detail != null) {\r
+                               Iterator<SoapFaultDetailElement> it = (Iterator<SoapFaultDetailElement>) detail\r
+                                               .getDetailEntries();\r
+                               while (it.hasNext()) {\r
+                                       SoapFaultDetailElement elem = it.next();\r
+                                       if (elem.getName().getLocalPart().equals("StackElement")) {\r
+                                               Source source = elem.getSource();\r
+                                               if (source instanceof DOMSource) {\r
+                                                       Node node = ((DOMSource) source).getNode();\r
+                                                       // stack.append(node.getTextContent()).append('\n');\r
+                                                       stack\r
+                                                                       .append(\r
+                                                                                       node.getChildNodes().item(0)\r
+                                                                                                       .getNodeValue()).append(\r
+                                                                                       '\n');\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               if (stack.length() > 0)\r
+                                       log.error("WS root cause stack: " + stack);\r
+                       }\r
+               }\r
+       }\r
+\r
+       private WebServiceUtils() {\r
+\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/process/WebServiceSlcExecutionNotifier.java
new file mode 100644 (file)
index 0000000..21bcf97
--- /dev/null
@@ -0,0 +1,118 @@
+package org.argeo.slc.ws.process;\r
+\r
+import java.util.List;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.process.SlcExecution;\r
+import org.argeo.slc.core.process.SlcExecutionNotifier;\r
+import org.argeo.slc.core.process.SlcExecutionStep;\r
+import org.argeo.slc.msg.process.SlcExecutionRequest;\r
+import org.argeo.slc.msg.process.SlcExecutionStatusRequest;\r
+import org.argeo.slc.msg.process.SlcExecutionStepsRequest;\r
+import org.argeo.slc.ws.client.WebServiceUtils;\r
+import org.springframework.ws.client.WebServiceIOException;\r
+import org.springframework.ws.client.core.WebServiceTemplate;\r
+import org.springframework.ws.soap.client.SoapFaultClientException;\r
+\r
+public class WebServiceSlcExecutionNotifier implements SlcExecutionNotifier {\r
+       private WebServiceTemplate template;\r
+\r
+       private Log log = LogFactory.getLog(getClass());\r
+\r
+       private Boolean cannotConnect = false;\r
+\r
+       public void newExecution(SlcExecution slcExecution) {\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               SlcExecutionRequest req = new SlcExecutionRequest();\r
+               req.setSlcExecution(slcExecution);\r
+               try {\r
+                       WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       if (log.isTraceEnabled())\r
+                               log.trace("Notified creation of slc execution "\r
+                                               + slcExecution.getUuid());\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void updateExecution(SlcExecution slcExecution) {\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               SlcExecutionRequest req = new SlcExecutionRequest();\r
+               req.setSlcExecution(slcExecution);\r
+               try {\r
+                       WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       if (log.isTraceEnabled())\r
+                               log.trace("Notified update of slc execution "\r
+                                               + slcExecution.getUuid());\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void updateStatus(SlcExecution slcExecution, String oldStatus,\r
+                       String newStatus) {\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               SlcExecutionStatusRequest req = new SlcExecutionStatusRequest(\r
+                               slcExecution.getUuid(), newStatus);\r
+               try {\r
+                       WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       if (log.isTraceEnabled())\r
+                               log.trace("Notified status update of slc execution "\r
+                                               + slcExecution.getUuid());\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void addSteps(SlcExecution slcExecution,\r
+                       List<SlcExecutionStep> additionalSteps) {\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               SlcExecutionStepsRequest req = new SlcExecutionStepsRequest();\r
+               req.setSlcExecutionUuid(slcExecution.getUuid());\r
+               req.setSteps(additionalSteps);\r
+               if (log.isTraceEnabled()) {\r
+                       for (SlcExecutionStep step : additionalSteps) {\r
+                               log.trace("Step " + step.getUuid() + ": " + step.logAsString());\r
+                       }\r
+               }\r
+\r
+               try {\r
+                       WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       if (log.isTraceEnabled())\r
+                               log.trace("Added steps to slc execution "\r
+                                               + slcExecution.getUuid());\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void setTemplate(WebServiceTemplate template) {\r
+               this.template = template;\r
+       }\r
+\r
+       protected void manageIoException(WebServiceIOException e) {\r
+               if (!cannotConnect) {\r
+                       log.error("Cannot connect to " + template.getDefaultUri()\r
+                                       + ". Won't try again.", e);\r
+                       cannotConnect = true;\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java b/runtime/org.argeo.slc.lib.detached/src/main/java/org/argeo/slc/ws/test/tree/WebServiceTreeTestResultNotifier.java
new file mode 100644 (file)
index 0000000..eba0b15
--- /dev/null
@@ -0,0 +1,109 @@
+package org.argeo.slc.ws.test.tree;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.test.TestResultListener;\r
+import org.argeo.slc.core.test.TestResultPart;\r
+import org.argeo.slc.core.test.tree.TreeTestResult;\r
+import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest;\r
+import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest;\r
+import org.argeo.slc.msg.test.tree.ResultPartRequest;\r
+import org.argeo.slc.ws.client.WebServiceUtils;\r
+import org.springframework.ws.client.WebServiceIOException;\r
+import org.springframework.ws.client.core.WebServiceTemplate;\r
+import org.springframework.ws.soap.client.SoapFaultClientException;\r
+\r
+public class WebServiceTreeTestResultNotifier implements\r
+               TestResultListener<TreeTestResult> {\r
+       private WebServiceTemplate template;\r
+       private Boolean onlyOnClose = false;\r
+\r
+       private Log log = LogFactory.getLog(getClass());\r
+\r
+       private Boolean cannotConnect = false;\r
+\r
+       public void resultPartAdded(TreeTestResult testResult,\r
+                       TestResultPart testResultPart) {\r
+               if (onlyOnClose)\r
+                       return;\r
+\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               try {\r
+                       if (testResult.getResultParts().size() == 1\r
+                                       && testResult.getResultParts().values().iterator().next()\r
+                                                       .getParts().size() == 1) {\r
+                               CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(\r
+                                               testResult);\r
+\r
+                               if (log.isDebugEnabled())\r
+                                       log.debug("Send create result request for result "\r
+                                                       + testResult.getUuid());\r
+\r
+                               WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       } else {\r
+                               ResultPartRequest req = new ResultPartRequest(testResult);\r
+\r
+                               if (log.isDebugEnabled())\r
+                                       log.debug("Send result parts for result "\r
+                                                       + testResult.getUuid());\r
+\r
+                               WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       }\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void close(TreeTestResult testResult) {\r
+               if (cannotConnect)\r
+                       return;\r
+\r
+               try {\r
+                       if (onlyOnClose) {\r
+                               CreateTreeTestResultRequest req = new CreateTreeTestResultRequest(\r
+                                               testResult);\r
+\r
+                               if (log.isDebugEnabled())\r
+                                       log.debug("Send create result request for result "\r
+                                                       + testResult.getUuid());\r
+\r
+                               WebServiceUtils.marshalSendAndReceive(template, req);\r
+                       } else {\r
+                               CloseTreeTestResultRequest req = new CloseTreeTestResultRequest(\r
+                                               testResult);\r
+\r
+                               if (log.isDebugEnabled())\r
+                                       log.debug("Send close result request for result "\r
+                                                       + testResult.getUuid());\r
+\r
+                               WebServiceUtils.marshalSendAndReceive(template, req);\r
+\r
+                       }\r
+               } catch (SoapFaultClientException e) {\r
+                       WebServiceUtils.manageSoapException(e);\r
+               } catch (WebServiceIOException e) {\r
+                       manageIoException(e);\r
+               }\r
+       }\r
+\r
+       public void setTemplate(WebServiceTemplate template) {\r
+               this.template = template;\r
+       }\r
+\r
+       public void setOnlyOnClose(Boolean onlyOnClose) {\r
+               this.onlyOnClose = onlyOnClose;\r
+       }\r
+\r
+       protected void manageIoException(WebServiceIOException e) {\r
+               if (!cannotConnect) {\r
+                       log.error("Cannot connect to " + template.getDefaultUri()\r
+                                       + ". Won't try again.", e);\r
+                       cannotConnect = true;\r
+               }\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF b/runtime/org.argeo.slc.lib.detached/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..d445f26
--- /dev/null
@@ -0,0 +1,124 @@
+Manifest-Version: 1.0\r
+Export-Package: org.argeo.slc.ws.client;uses:="org.springframework.ws.\r
+ client.core,org.springframework.oxm,org.apache.commons.logging,org.sp\r
+ ringframework.ws,org.springframework.ws.soap,org.springframework.ws.c\r
+ ontext,org.springframework.xml.transform,org.springframework.ws.clien\r
+ t,javax.xml.transform.dom,org.w3c.dom,org.springframework.xml.validat\r
+ ion,javax.xml.namespace,org.xml.sax,javax.xml.transform,org.springfra\r
+ mework.ws.soap.client,org.springframework.ws.client.support.intercept\r
+ or";version="0.11.2.SNAPSHOT",org.argeo.slc.ws.client.spring;version=\r
+ "0.11.2.SNAPSHOT",org.argeo.slc.ant.detached;uses:="org.argeo.slc.ant\r
+ .spring,org.apache.commons.logging,org.argeo.slc.core,org.argeo.slc.s\r
+ pring,org.springframework.context,org.argeo.slc.detached,org.argeo.sl\r
+ c.ant.structure,org.springframework.beans.factory";version="0.11.2.SN\r
+ APSHOT",org.argeo.slc.ws.test.tree;uses:="org.springframework.ws.clie\r
+ nt.core,org.apache.commons.logging,org.argeo.slc.msg.test.tree,org.ar\r
+ geo.slc.ws.client,org.springframework.ws.soap.client,org.springframew\r
+ ork.ws.client,org.argeo.slc.core.test.tree,org.argeo.slc.core.test";v\r
+ ersion="0.11.2.SNAPSHOT",org.argeo.slc.maven;uses:="org.argeo.slc.cor\r
+ e.build,org.argeo.slc.core.deploy";version="0.11.2.SNAPSHOT",org.arge\r
+ o.slc.ant.structure;uses:="org.argeo.slc.core.structure,org.argeo.slc\r
+ .ant.spring,org.argeo.slc.core,org.springframework.context,org.apache\r
+ .tools.ant,org.argeo.slc.core.structure.tree";version="0.11.2.SNAPSHO\r
+ T",org.argeo.slc.ant.unit;uses:="org.argeo.slc.ant,junit.framework,or\r
+ g.argeo.slc.unit,org.argeo.slc.runtime,org.argeo.slc.cli,org.springfr\r
+ amework.core.io,org.springframework.context,org.argeo.slc.core.proces\r
+ s";version="0.11.2.SNAPSHOT",org.argeo.slc.ant.deploy;uses:="org.arge\r
+ o.slc.ant.spring,org.apache.commons.logging,org.argeo.slc.core,org.ar\r
+ geo.slc.core.build,org.springframework.context,org.argeo.slc.core.dep\r
+ loy,org.argeo.slc.ant.structure,org.apache.tools.ant";version="0.11.2\r
+ .SNAPSHOT",org.argeo.slc.ant.spring;uses:="org.apache.commons.logging\r
+ ,org.argeo.slc.core,org.springframework.beans,org.apache.tools.ant.ty\r
+ pes,org.springframework.context,org.argeo.slc.core.process,org.apache\r
+ .tools.ant,org.springframework.beans.factory";version="0.11.2.SNAPSHO\r
+ T",org.argeo.slc.ant;uses:="org.apache.commons.logging,org.apache.log\r
+ 4j,org.springframework.context.support,org.apache.log4j.spi,org.sprin\r
+ gframework.beans.factory.config,org.springframework.beans.factory.sup\r
+ port,org.argeo.slc.core.structure,org.argeo.slc.core,org.apache.tools\r
+ .ant.util,org.apache.commons.io,org.argeo.slc.core.process,org.argeo.\r
+ slc.core.structure.tree,org.springframework.beans.factory,org.apache.\r
+ tools.ant.helper,org.springframework.util,org.springframework.core.io\r
+ ,org.springframework.context,org.argeo.slc.logging,org.springframewor\r
+ k.beans.factory.xml,org.apache.tools.ant,org.argeo.slc.runtime";versi\r
+ on="0.11.2.SNAPSHOT",org.argeo.slc.lib.detached;uses:="org.springfram\r
+ ework.oxm,org.apache.commons.logging,org.argeo.slc.detached.ui,org.sp\r
+ ringframework.beans,org.argeo.slc.detached,org.springframework.beans.\r
+ factory.config,org.argeo.slc.core.test,org.springframework.beans.fact\r
+ ory.support,org.argeo.slc.core,org.argeo.slc.core.test.context,javax.\r
+ xml.transform,org.argeo.slc.core.structure.tree,org.springframework.b\r
+ eans.factory";version="0.11.2.SNAPSHOT",org.argeo.slc.ws.process;uses\r
+ :="org.springframework.ws.client.core,org.apache.commons.logging,org.\r
+ argeo.slc.ws.client,org.springframework.ws.client,org.springframework\r
+ .ws.soap.client,org.argeo.slc.core.process,org.argeo.slc.msg.process"\r
+ ;version="0.11.2.SNAPSHOT",org.argeo.slc.cli;uses:="org.apache.common\r
+ s.logging,org.apache.commons.cli,org.springframework.core.io,org.arge\r
+ o.slc.logging,org.argeo.slc.ant,org.argeo.slc.core,org.argeo.slc.spri\r
+ ng,org.argeo.slc.runtime,org.apache.commons.io,org.argeo.slc.core.pro\r
+ cess";version="0.11.2.SNAPSHOT",org.argeo.slc.ant.test;uses:="org.apa\r
+ che.commons.logging,org.springframework.beans,org.springframework.con\r
+ text,org.argeo.slc.ant.structure,org.apache.tools.ant,org.argeo.slc.c\r
+ ore.test,org.argeo.slc.core.structure,org.argeo.slc.ant.spring,org.ar\r
+ geo.slc.core,org.argeo.slc.core.test.context,org.argeo.slc.spring,org\r
+ .apache.tools.ant.types,org.argeo.slc.core.deploy,org.argeo.slc.core.\r
+ process,org.argeo.slc.core.structure.tree,org.springframework.beans.f\r
+ actory";version="0.11.2.SNAPSHOT",org.argeo.slc.support.deploy.ant;ve\r
+ rsion="0.11.2.SNAPSHOT"\r
+Tool: Bnd-0.0.255\r
+Bundle-Name: Argeo SLC Agent\r
+Created-By: 1.6.0 (Sun Microsystems Inc.)\r
+Bundle-Vendor: Argeo\r
+Bundle-Version: 0.11.2.SNAPSHOT\r
+Bundle-ManifestVersion: 2\r
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt\r
+Bundle-Description: SLC Distribution\r
+Import-Package: javax.xml.namespace;version="1.3",javax.xml.transform;\r
+ version="1.3",javax.xml.transform.dom;version="1.3",junit.framework;v\r
+ ersion="3.8",org.apache.commons.cli;resolution:=optional;version="1.1\r
+ ",org.apache.commons.io;version="1.4",org.apache.commons.logging;vers\r
+ ion="1.1",org.apache.log4j;version="1.2",org.apache.log4j.spi;version\r
+ ="1.2",org.apache.tools.ant;version="1.7",org.apache.tools.ant.helper\r
+ ;version="1.7",org.apache.tools.ant.types;version="1.7",org.apache.to\r
+ ols.ant.util;version="1.7",org.argeo.slc.ant;version="0.11.2.SNAPSHOT\r
+ ",org.argeo.slc.ant.deploy;version="0.11.2.SNAPSHOT",org.argeo.slc.an\r
+ t.detached;version="0.11.2.SNAPSHOT",org.argeo.slc.ant.spring;version\r
+ ="0.11.2.SNAPSHOT",org.argeo.slc.ant.structure;version="0.11.2.SNAPSH\r
+ OT",org.argeo.slc.ant.test;version="0.11.2.SNAPSHOT",org.argeo.slc.an\r
+ t.unit;version="0.11.2.SNAPSHOT",org.argeo.slc.cli;version="0.11.2.SN\r
+ APSHOT",org.argeo.slc.core;version="0.11.2.SNAPSHOT",org.argeo.slc.co\r
+ re.build;version="0.11.2.SNAPSHOT",org.argeo.slc.core.deploy;version=\r
+ "0.11.2.SNAPSHOT",org.argeo.slc.core.process;version="0.11.2.SNAPSHOT\r
+ ",org.argeo.slc.core.structure;version="0.11.2.SNAPSHOT",org.argeo.sl\r
+ c.core.structure.tree;version="0.11.2.SNAPSHOT",org.argeo.slc.core.te\r
+ st;version="0.11.2.SNAPSHOT",org.argeo.slc.core.test.context;version=\r
+ "0.11.2.SNAPSHOT",org.argeo.slc.core.test.spring;version="0.11.2.SNAP\r
+ SHOT",org.argeo.slc.core.test.tree;version="0.11.2.SNAPSHOT",org.arge\r
+ o.slc.detached;version="0.11.2.SNAPSHOT",org.argeo.slc.detached.ui;ve\r
+ rsion="0.11.2.SNAPSHOT",org.argeo.slc.lib.detached;version="0.11.2.SN\r
+ APSHOT",org.argeo.slc.logging;version="0.11.2.SNAPSHOT",org.argeo.slc\r
+ .maven;version="0.11.2.SNAPSHOT",org.argeo.slc.msg.process;version="0\r
+ .11.2.SNAPSHOT",org.argeo.slc.msg.test.tree;version="0.11.2.SNAPSHOT"\r
+ ,org.argeo.slc.runtime;version="0.11.2.SNAPSHOT",org.argeo.slc.spring\r
+ ;version="0.11.2.SNAPSHOT",org.argeo.slc.support.deploy.ant;version="\r
+ 0.11.2.SNAPSHOT",org.argeo.slc.unit;version="0.11.2.SNAPSHOT",org.arg\r
+ eo.slc.ws.client;version="0.11.2.SNAPSHOT",org.argeo.slc.ws.client.sp\r
+ ring;version="0.11.2.SNAPSHOT",org.argeo.slc.ws.process;version="0.11\r
+ .2.SNAPSHOT",org.argeo.slc.ws.test.tree;version="0.11.2.SNAPSHOT",org\r
+ .springframework.beans;version="2.5.6.A",org.springframework.beans.fa\r
+ ctory;version="2.5.6.A",org.springframework.beans.factory.config;vers\r
+ ion="2.5.6.A",org.springframework.beans.factory.support;version="2.5.\r
+ 6.A",org.springframework.beans.factory.xml;version="2.5.6.A",org.spri\r
+ ngframework.context;version="2.5.6.A",org.springframework.context.sup\r
+ port;version="2.5.6.A",org.springframework.core.io;version="2.5.6.A",\r
+ org.springframework.oxm;version="1.5.5.A",org.springframework.util;ve\r
+ rsion="2.5.6.A",org.springframework.ws;version="1.5.5.A",org.springfr\r
+ amework.ws.client;version="1.5.5.A",org.springframework.ws.client.cor\r
+ e;version="1.5.5.A",org.springframework.ws.client.support.interceptor\r
+ ;version="1.5.5.A",org.springframework.ws.context;version="1.5.5.A",o\r
+ rg.springframework.ws.soap;version="1.5.5.A",org.springframework.ws.s\r
+ oap.client;version="1.5.5.A",org.springframework.xml.transform;versio\r
+ n="1.5.5.A",org.springframework.xml.validation;version="1.5.5.A",org.\r
+ w3c.dom;version="1.3",org.xml.sax;version="1.3"\r
+Bundle-SymbolicName: org.argeo.slc.agent\r
+Bundle-DocURL: http://www.argeo.org\r
+Originally-Created-By: 1.6.0 (Sun Microsystems Inc.)\r
+\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/defaultAppLog4j.properties
new file mode 100644 (file)
index 0000000..c13c36f
--- /dev/null
@@ -0,0 +1,23 @@
+log4j.rootLogger=WARN, console, file
+
+## Levels
+log4j.logger.org.argeo=INFO
+
+## Ant (Ant error logging is to verbose)
+log4j.logger.org.apache.tools.ant.UnknownElement=OFF
+log4j.logger.org.apache.tools.ant.Target=OFF
+log4j.logger.org.apache.tools.ant.Project=OFF
+
+## Appenders
+# console uses PatternLayout.
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
+
+# file uses PatternLayout
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.File=${slc.workDir}/log/slcApp.log
+log4j.appender.file.MaxFileSize=1MB
+log4j.appender.file.MaxBackupIndex=5
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/taskdefs.properties
new file mode 100644 (file)
index 0000000..ac489bf
--- /dev/null
@@ -0,0 +1,8 @@
+# Tasks\r
+slc.test=org.argeo.slc.ant.test.SlcTestTask\r
+slc.deploy=org.argeo.slc.ant.deploy.SlcDeployTask\r
+slc.manager=org.argeo.slc.ant.deploy.SlcManagerTask\r
+slc.closeResult=org.argeo.slc.ant.test.SlcCloseTestResultTask\r
+slc.report=org.argeo.slc.ant.test.SlcReportTask\r
+slc.register=org.argeo.slc.ant.spring.SpringRegister\r
+slc.detached=org.argeo.slc.ant.detached.SlcDetachedTask\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ant/typedefs.properties
new file mode 100644 (file)
index 0000000..0cb3b2c
--- /dev/null
@@ -0,0 +1,2 @@
+# Types\r
+slc.context=org.argeo.slc.ant.test.ParentContextType\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/cli/bootstrapLog4j.properties
new file mode 100644 (file)
index 0000000..7dcc3fd
--- /dev/null
@@ -0,0 +1,13 @@
+log4j.rootLogger=WARN, console\r
+\r
+## Levels\r
+log4j.logger.org.argeo=INFO\r
+\r
+## Appenders\r
+# console is set to be a ConsoleAppender.\r
+log4j.appender.console=org.apache.log4j.ConsoleAppender\r
+\r
+# console uses PatternLayout.\r
+log4j.appender.console.layout=org.apache.log4j.PatternLayout\r
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n\r
+\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/castor.xml
new file mode 100644 (file)
index 0000000..ce8eb43
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ENTITY slc-detached-namespace-uri "http://argeo.org/projects/slc/schemas/detached">
+<!ENTITY slc-detached-namespace-prefix "slc-det">
+]>
+
+<mapping>
+    <description>Mapping of SLC detached types</description>
+
+    <class name="org.argeo.slc.detached.DetachedRequest">
+        <map-to ns-uri="&slc-detached-namespace-uri;"
+            ns-prefix="&slc-detached-namespace-prefix;" />
+        <field name="uuid" />
+        <field name="ref" />
+        <field name="path" />
+        <field name="properties" collection="map">
+            <bind-xml name="prop" location="properties">
+                <class name="org.exolab.castor.mapping.MapItem">
+                    <map-to ns-uri="&slc-detached-namespace-uri;"
+                        ns-prefix="&slc-detached-namespace-prefix;" />
+                    <field name="key" type="string">
+                        <bind-xml name="key" node="attribute" />
+                    </field>
+                    <field name="value" type="string">
+                        <bind-xml node="text" />
+                    </field>
+                </class>
+            </bind-xml>
+        </field>
+    </class>
+
+    <class name="org.argeo.slc.detached.DetachedAnswer">
+        <map-to ns-uri="&slc-detached-namespace-uri;"
+            ns-prefix="&slc-detached-namespace-prefix;" />
+        <field name="uuid" />
+        <field name="status" />
+        <field name="log" />
+        <field name="properties" collection="map">
+            <bind-xml name="prop" location="properties">
+                <class name="org.exolab.castor.mapping.MapItem">
+                    <map-to ns-uri="&slc-detached-namespace-uri;"
+                        ns-prefix="&slc-detached-namespace-prefix;" />
+                    <field name="key" type="string">
+                        <bind-xml name="key" node="attribute" />
+                    </field>
+                    <field name="value" type="string">
+                        <bind-xml node="text" />
+                    </field>
+                </class>
+            </bind-xml>
+        </field>
+    </class>
+</mapping>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/lib/detached/spring.xml
new file mode 100644 (file)
index 0000000..41e994d
--- /dev/null
@@ -0,0 +1,41 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
+    default-lazy-init="true">
+
+    <bean id="slcTemplate.detached.testDefinition"
+        class="org.argeo.slc.lib.detached.DetachedTestDefinition"
+        abstract="true">
+    </bean>
+
+    <bean id="slcDefault.detached.xmlConverterCastor"
+        class="org.argeo.slc.lib.detached.DetachedXmlConverterSpring">
+        <property name="marshaller"
+            ref="slcDefault.detached.castor.marshaller" />
+        <property name="unmarshaller"
+            ref="slcDefault.detached.castor.marshaller" />
+    </bean>
+
+    <bean id="slcDefault.detached.castor.marshaller"
+        class="org.springframework.oxm.castor.CastorMarshaller">
+        <property name="mappingLocations">
+            <list>
+                <value>
+                    classpath:org/argeo/slc/lib/detached/castor.xml
+                </value>
+            </list>
+        </property>
+        <property name="whitespacePreserve" value="true" />
+    </bean>
+
+    <bean id="slcDefault.detached.xml.xsdValidator"
+        factory-bean="slcDefault.detached.xml.xsdSchema"
+        factory-method="createValidator" />
+
+    <bean id="slcDefault.detached.xml.xsdSchema"
+        class="org.springframework.xml.xsd.SimpleXsdSchema">
+        <property name="xsd"
+            value="classpath:/org/argeo/slc/detached/slc-detached.xsd" />
+    </bean>
+
+</beans>
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/support/deploy/ant/build.xml
new file mode 100644 (file)
index 0000000..693f5ec
--- /dev/null
@@ -0,0 +1,23 @@
+<project>\r
+\r
+       <target name="deployZip">
+               <unzip src="${src}" dest="${tempDir}" />
+               <copyFromTemp />
+       </target>
+
+       <target name="deployTarGz">
+               <untar src="${src}" dest="${tempDir}" compression="gzip" />
+               <copyFromTemp />
+       </target>
+
+       <macrodef name="copyFromTemp">
+               <sequential>
+                       <copy todir="${dest}" includeemptydirs="true">
+                               <fileset dir="${tempDir}">
+                                       <include name="**/*" />
+                               </fileset>
+                               <mapper classname="org.argeo.slc.ant.RemoveRootDirMapper" to="${removeRootDir}" />
+                       </copy>
+               </sequential>
+       </macrodef>
+</project>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/main/resources/org/argeo/slc/ws/client/spring/applicationContext.xml
new file mode 100644 (file)
index 0000000..7e9df7d
--- /dev/null
@@ -0,0 +1,65 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
+       default-lazy-init="true">
+
+       <import
+               resource="classpath:/org/argeo/slc/castor/spring/applicationContext.xml" />
+       <import
+               resource="classpath:/org/argeo/slc/xml/spring/applicationContext.xml" />
+
+       <bean id="slcDefault.ws.client.webServiceTemplate"
+               parent="slcTemplate.ws.client.webServiceTemplate">
+               <constructor-arg ref="slcDefault.ws.client.messageFactory" />
+               <property name="defaultUri" value="${slc.ws.uri}" />
+       </bean>
+
+       <bean
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
+               lazy-init="false">
+               <property name="systemPropertiesModeName"
+                       value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
+               <property name="ignoreUnresolvablePlaceholders" value="true" />
+               <property name="properties">
+                       <props>
+                               <prop key="slc.ws.uri">
+                                       http://localhost:9090/org.argeo.slc.webapp/slcService/
+                               </prop>
+                       </props>
+               </property>
+       </bean>
+
+       <bean id="slcTemplate.ws.client.webServiceTemplate"
+               class="org.springframework.ws.client.core.WebServiceTemplate"
+               abstract="true">
+               <property name="marshaller" ref="slcDefault.castor.marshaller" />
+               <property name="unmarshaller"
+                       ref="slcDefault.castor.marshaller" />
+               <property name="interceptors">
+                       <list>
+                               <bean
+                                       class="org.argeo.slc.ws.client.ValidatingClientInterceptor">
+                                       <property name="validator"
+                                               ref="slcDefault.xml.xsdValidator" />
+                               </bean>
+                       </list>
+               </property>
+       </bean>
+
+       <bean id="slcDefault.ws.client.messageFactory"
+               class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory" />
+
+       <bean name="slcDefault.ws.client.treeTestResultWsNotfier"
+               class="org.argeo.slc.ws.test.tree.WebServiceTreeTestResultNotifier">
+               <property name="template"
+                       ref="slcDefault.ws.client.webServiceTemplate" />
+               <property name="onlyOnClose" value="false" />
+       </bean>
+
+       <bean name="slcDefault.ws.client.slcExecutionNotifier"
+               class="org.argeo.slc.ws.process.WebServiceSlcExecutionNotifier">
+               <property name="template"
+                       ref="slcDefault.ws.client.webServiceTemplate" />
+       </bean>
+
+</beans>
diff --git a/runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt b/runtime/org.argeo.slc.lib.detached/src/site/apt/index.apt
new file mode 100644 (file)
index 0000000..f414460
--- /dev/null
@@ -0,0 +1 @@
+Argeo SLC Site
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/DummyObject.java
new file mode 100644 (file)
index 0000000..5998760
--- /dev/null
@@ -0,0 +1,55 @@
+package org.argeo.slc.ant;
+
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+public class DummyObject {
+       private String name;
+       private Long value;
+       private DummyObject other;
+       private List<DummyObject> children = new Vector<DummyObject>();
+       private Map<String, DummyObject> map = new TreeMap<String, DummyObject>();
+
+       public String getName() {
+               return name;
+       }
+
+       public void setName(String name) {
+               this.name = name;
+       }
+
+       public Long getValue() {
+               return value;
+       }
+
+       public void setValue(Long value) {
+               this.value = value;
+       }
+
+       public DummyObject getOther() {
+               return other;
+       }
+
+       public void setOther(DummyObject other) {
+               this.other = other;
+       }
+
+       public List<DummyObject> getChildren() {
+               return children;
+       }
+
+       public void setChildren(List<DummyObject> children) {
+               this.children = children;
+       }
+
+       public Map<String, DummyObject> getMap() {
+               return map;
+       }
+
+       public void setMap(Map<String, DummyObject> map) {
+               this.map = map;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/OverrideTest.java
new file mode 100644 (file)
index 0000000..d49521a
--- /dev/null
@@ -0,0 +1,64 @@
+package org.argeo.slc.ant;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.ant.unit.MinimalAntClasspathTestCase;
+
+public class OverrideTest extends MinimalAntClasspathTestCase {
+       private Log log = LogFactory.getLog(getClass());
+
+       public void testSimpleRun() {
+               execute("/org/argeo/slc/ant/buildOverride.xml");
+       }
+
+       @Override
+       public void postExecution(AntExecutionContext executionContext) {
+               log.info("Analyzing context after execution...");
+
+               DummyObject dummy1UnModified = executionContext
+                               .getAntRef("dummy1.unmodified");
+               assertEquals("dummy2", dummy1UnModified.getOther().getName());
+               assertEquals(2, dummy1UnModified.getChildren().size());
+               assertEquals(2, dummy1UnModified.getMap().size());
+
+               DummyObject dummy1Modif1 = executionContext.getAntRef("dummy1.modif1");
+               assertEquals("dummy1.modif1", dummy1Modif1.getName());
+               assertEquals("dummy3", dummy1Modif1.getOther().getName());
+
+               DummyObject dummy1Modif2 = executionContext.getAntRef("dummy1.modif2");
+               assertEquals(1, dummy1Modif2.getChildren().size());
+               assertEquals("dummy3", dummy1Modif2.getChildren().get(0).getName());
+
+               DummyObject dummy1Modif3 = executionContext.getAntRef("dummy1.modif3");
+               assertEquals(2, dummy1Modif3.getChildren().size());
+               assertEquals("dummy3", dummy1Modif3.getChildren().get(0).getName());
+               assertEquals("dummy2", dummy1Modif3.getChildren().get(1).getName());
+
+               DummyObject dummy1Modif4 = executionContext.getAntRef("dummy1.modif4");
+               assertEquals(2, dummy1Modif4.getChildren().size());
+               assertEquals("dummy3", dummy1Modif4.getChildren().get(0).getName());
+               assertEquals("dummy1.modif1", dummy1Modif4.getChildren().get(0)
+                               .getOther().getName());
+               assertEquals("dummy2", dummy1Modif4.getChildren().get(1).getName());
+               assertEquals(1, dummy1Modif4.getChildren().get(1).getChildren().size());
+               assertEquals("dummy3", dummy1Modif4.getChildren().get(1).getChildren()
+                               .get(0).getName());
+
+               DummyObject dummy1Modif5 = executionContext.getAntRef("dummy1.modif5");
+               assertEquals(2, dummy1Modif5.getMap().size());
+               assertEquals("dummy3", dummy1Modif5.getMap().get("key1").getName());
+               assertEquals("dummy2", dummy1Modif5.getMap().get("key2").getName());
+               
+               DummyObject dummy1Modif6 = executionContext.getAntRef("dummy1.modif6");
+               assertEquals(2, dummy1Modif6.getMap().size());
+               assertEquals("dummy2.merged", dummy1Modif6.getMap().get("key1").getName());
+               assertEquals("dummy3.merged", dummy1Modif6.getMap().get("key2").getName());
+               
+       }
+
+       @Override
+       protected String getApplicationContextLocation() {
+               return inPackage("acOverride.xml");
+       }
+
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/ant/SlcAntTest.java
new file mode 100644 (file)
index 0000000..5a58f1f
--- /dev/null
@@ -0,0 +1,11 @@
+package org.argeo.slc.ant;\r
+\r
+import org.argeo.slc.ant.unit.MinimalAntClasspathTestCase;\r
+\r
+public class SlcAntTest extends MinimalAntClasspathTestCase {\r
+       // private Log log = LogFactory.getLog(getClass());\r
+\r
+       public void testSimpleRun() {\r
+               execute("/org/argeo/slc/ant/build.xml");\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java b/runtime/org.argeo.slc.lib.detached/src/test/java/org/argeo/slc/lib/detached/DetachedCastorTest.java
new file mode 100644 (file)
index 0000000..0425ce0
--- /dev/null
@@ -0,0 +1,142 @@
+package org.argeo.slc.lib.detached;
+
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.detached.DetachedAnswer;
+import org.argeo.slc.detached.DetachedRequest;
+import org.argeo.slc.detached.DetachedXmlConverter;
+import org.argeo.slc.detached.DetachedXmlConverterCompat;
+import org.argeo.slc.unit.AbstractSpringTestCase;
+import org.argeo.slc.unit.UnitXmlUtils;
+import org.springframework.xml.transform.StringResult;
+import org.springframework.xml.transform.StringSource;
+import org.springframework.xml.validation.XmlValidator;
+
+public class DetachedCastorTest extends AbstractSpringTestCase {
+       private final Log log = LogFactory.getLog(getClass());
+
+       private DetachedXmlConverter converter = null;
+       private XmlValidator validator = null;
+       private DetachedXmlConverter converterCompat = null;
+
+       public void setUp() {
+               converter = getBean("slcDefault.detached.xmlConverterCastor");
+               validator = getBean("slcDefault.detached.xml.xsdValidator");
+               converterCompat = new DetachedXmlConverterCompat();
+       }
+
+       public void testRequest() throws Exception {
+               DetachedRequest request = createTestRequest();
+
+               StringResult result = new StringResult();
+               converter.marshallCommunication(request, result);
+               String xml = result.toString();
+               log.debug(xml + "\n");
+
+               UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml));
+               DetachedRequest requestUnm = (DetachedRequest) converter
+                               .unmarshallCommunication(new StringSource(xml));
+               assertDetachedRequest(request, requestUnm);
+       }
+
+       public void testRequestCompat() throws Exception {
+               DetachedRequest request = createTestRequest();
+
+               StringResult result = new StringResult();
+               converter.marshallCommunication(request, result);
+               String xml = result.toString();
+               log.debug(xml + "\n");
+
+               UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml));
+               DetachedRequest requestUnm = (DetachedRequest) converterCompat
+                               .unmarshallCommunication(new StringSource(xml));
+               assertDetachedRequest(request, requestUnm);
+       }
+
+       public void testAnswer() throws Exception {
+               DetachedAnswer answer = createTestAnswer();
+               StringResult result = new StringResult();
+               converter.marshallCommunication(answer, result);
+               String xml = result.toString();
+               log.debug(xml + "\n");
+
+               UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml));
+               DetachedAnswer answerUnm = (DetachedAnswer) converter
+                               .unmarshallCommunication(new StringSource(xml));
+               assertDetachedAnswer(answer, answerUnm);
+       }
+
+       public void testAnswerCompat() throws Exception {
+               DetachedAnswer answer = createTestAnswer();
+               StringResult result = new StringResult();
+               converterCompat.marshallCommunication(answer, result);
+               String xml = result.toString();
+               log.debug(xml + "\n");
+
+               UnitXmlUtils.assertXmlValidation(validator, new StringSource(xml));
+               DetachedAnswer answerUnm = (DetachedAnswer) converter
+                               .unmarshallCommunication(new StringSource(xml));
+               assertDetachedAnswer(answer, answerUnm);
+       }
+
+       public static DetachedRequest createTestRequest() {
+               DetachedRequest request = new DetachedRequest();
+               request.setUuid("12345");
+               request.setPath("/root/test");
+               request.setRef("testRef");
+               Properties properties = new Properties();
+               properties.setProperty("key1", "value1");
+               properties.setProperty("key2", "value2");
+               request.setProperties(properties);
+               return request;
+       }
+
+       public static DetachedAnswer createTestAnswer() {
+               DetachedAnswer answer = new DetachedAnswer();
+               answer.setUuid("12345");
+               answer.setStatus(DetachedAnswer.PROCESSED);
+               answer.setLog("my log\nline break.");
+               Properties properties = new Properties();
+               properties.setProperty("key1", "value1");
+               properties.setProperty("key2", "value2");
+               answer.setProperties(properties);
+               return answer;
+       }
+
+       public static void assertDetachedRequest(DetachedRequest expected,
+                       DetachedRequest reached) {
+               assertEquals(expected.getUuid(), reached.getUuid());
+               assertEquals(expected.getPath(), reached.getPath());
+               assertEquals(expected.getRef(), reached.getRef());
+               Properties expectedProps = expected.getProperties();
+               Properties reachedProps = reached.getProperties();
+               assertEquals(expectedProps.size(), reachedProps.size());
+               Enumeration<Object> keys = expectedProps.keys();
+               while (keys.hasMoreElements()) {
+                       String key = (String) keys.nextElement();
+                       assertTrue(reachedProps.containsKey(key));
+                       assertEquals(expectedProps.getProperty(key), reachedProps
+                                       .getProperty(key));
+               }
+       }
+
+       public static void assertDetachedAnswer(DetachedAnswer expected,
+                       DetachedAnswer reached) {
+               assertEquals(expected.getUuid(), reached.getUuid());
+               assertEquals(expected.getStatus(), reached.getStatus());
+               assertEquals(expected.getLog(), reached.getLog());
+               Properties expectedProps = expected.getProperties();
+               Properties reachedProps = reached.getProperties();
+               assertEquals(expectedProps.size(), reachedProps.size());
+               Enumeration<Object> keys = expectedProps.keys();
+               while (keys.hasMoreElements()) {
+                       String key = (String) keys.nextElement();
+                       assertTrue(reachedProps.containsKey(key));
+                       assertEquals(expectedProps.getProperty(key), reachedProps
+                                       .getProperty(key));
+               }
+       }
+}
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties b/runtime/org.argeo.slc.lib.detached/src/test/resources/log4j.properties
new file mode 100644 (file)
index 0000000..a583c59
--- /dev/null
@@ -0,0 +1,21 @@
+# Set root logger level to DEBUG and its only appender to A1.\r
+log4j.rootLogger=WARN, console\r
+\r
+## Levels\r
+# Slc\r
+log4j.logger.org.argeo=DEBUG\r
+\r
+# Castor\r
+log4j.logger.org.exolab.castor=WARN\r
+\r
+# Spring\r
+log4j.logger.org.springframework=WARN\r
+\r
+## Appenders\r
+# A1 is set to be a ConsoleAppender.\r
+log4j.appender.console=org.apache.log4j.ConsoleAppender\r
+\r
+# A1 uses PatternLayout.\r
+log4j.appender.console.layout=org.apache.log4j.PatternLayout\r
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n\r
+\r
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/acOverride.xml
new file mode 100644 (file)
index 0000000..c9c3911
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+
+       <bean id="dummy1" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy1" />
+               <property name="other" ref="dummy2" />
+               <property name="children">
+                       <list>
+                               <ref bean="dummy2" />
+                               <ref bean="dummy3" />
+                       </list>
+               </property>
+               <property name="map">
+                       <map>
+                               <entry key="key1">
+                                       <ref bean="dummy2" />
+                               </entry>
+                               <entry key="key2">
+                                       <ref bean="dummy3" />
+                               </entry>
+                       </map>
+               </property>
+       </bean>
+
+       <bean id="dummy2" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy2" />
+       </bean>
+
+       <bean id="dummy3" parent="template.dummy" scope="prototype">
+               <property name="name" value="dummy3" />
+       </bean>
+
+       <!-- Templates -->
+       <bean id="template.dummy" class="org.argeo.slc.ant.DummyObject"
+               abstract="true">
+       </bean>
+
+
+
+</beans>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/applicationContext.xml
new file mode 100644 (file)
index 0000000..6ff9b85
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+       <import resource="classpath:/org/argeo/slc/ant/nonDepContext.xml" />\r
+\r
+       <bean id="testResult"\r
+               parent="slcDefault.test.basicTreeTestResult">\r
+       </bean>\r
+\r
+</beans>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/build.xml
new file mode 100644 (file)
index 0000000..35de7be
--- /dev/null
@@ -0,0 +1,25 @@
+<project default="test">\r
+\r
+       <target name="test">\r
+               <echo message="Hello World!" />\r
+\r
+               <slc.test>\r
+                       <testDefinition bean="testDef" />\r
+                       <testData bean="testData1" />\r
+               </slc.test>\r
+\r
+               <slc.test>
+                       <testDefinition bean="testDef" />
+                       <testData bean="testData.context1" />
+               </slc.test>
+
+               <slc.test path="/testRoot/testContext">
+                       <testDefinition bean="testDef" />
+                       <testData bean="testData.context1" />
+               </slc.test>
+
+               <slc.closeResult>
+                       <result bean="testResult" />
+               </slc.closeResult>\r
+       </target>\r
+</project>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/buildOverride.xml
new file mode 100644 (file)
index 0000000..67f889a
--- /dev/null
@@ -0,0 +1,77 @@
+<project default="test">\r
+\r
+       <target name="test">\r
+               <slc.register>
+                       <object antid="dummy1.unmodified" bean="dummy1" />
+                       <object antid="dummy1.modif1" bean="dummy1">
+                               <override name="name" value="dummy1.modif1" />
+                               <override name="other" bean="dummy3" />
+                       </object>
+                       <object antid="dummy1.modif2" bean="dummy1">
+                               <override name="children">
+                                       <list>
+                                               <override bean="dummy3" />
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif3" bean="dummy1">
+                               <override name="children" merge="true">
+                                       <list>
+                                               <override>
+                                                       <override name="name" value="dummy3" />
+                                               </override>
+                                               <override>
+                                                       <override name="name" value="dummy2" />
+                                               </override>
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif4" bean="dummy1">
+                               <override name="children" merge="true">
+                                       <list>
+                                               <override>
+                                                       <override name="name" value="dummy3" />
+                                                       <override name="other" antref="dummy1.modif1" />
+                                               </override>
+                                               <override>
+                                                       <override name="name" value="dummy2" />
+                                                       <override name="children">
+                                                               <list>
+                                                                       <override bean="dummy3" />
+                                                               </list>
+                                                       </override>
+                                               </override>
+                                       </list>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif5" bean="dummy1">
+                               <override name="map">
+                                       <map>
+                                               <entry key="key1">
+                                                       <override bean="dummy3" />
+                                               </entry>
+                                               <entry key="key2">
+                                                       <override bean="dummy2" />
+                                               </entry>
+                                       </map>
+                               </override>
+                       </object>
+                       <object antid="dummy1.modif6" bean="dummy1">
+                               <override name="map" merge="true">
+                                       <map>
+                                               <entry key="key1">
+                                                       <override>
+                                                               <override name="name" value="dummy2.merged" />
+                                                       </override>
+                                               </entry>
+                                               <entry key="key2">
+                                                       <override>
+                                                               <override name="name" value="dummy3.merged" />
+                                                       </override>
+                                               </entry>
+                                       </map>
+                               </override>
+                       </object>
+               </slc.register>\r
+       </target>\r
+</project>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/ant/nonDepContext.xml
new file mode 100644 (file)
index 0000000..56da88a
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+       <import\r
+               resource="classpath:/org/argeo/slc/core/test/spring/applicationContext.xml" />\r
+\r
+       <bean name="testDef"\r
+               class="org.argeo.slc.core.test.BasicTestDefinition" scope="prototype" />\r
+\r
+       <bean name="testData1"\r
+               class="org.argeo.slc.core.test.BasicTestData">\r
+               <property name="expected">\r
+                       <value>toto</value>\r
+               </property>\r
+               <property name="reached">\r
+                       <value>toto</value>\r
+               </property>\r
+       </bean>\r
+\r
+       <bean id="testData.context1" parent="context.template">\r
+               <property name="values">\r
+                       <map>\r
+                               <entry key="reference" value="20" />\r
+                               <entry key="varIntern" value="60" />\r
+                       </map>\r
+               </property>\r
+               <property name="expectedValues">\r
+                       <map>\r
+                               <entry key="reference" value="21" />\r
+                               <entry key="varIntern" value="60" />\r
+                       </map>\r
+               </property>\r
+       </bean>\r
+\r
+       <bean id="context.template"\r
+               class="org.argeo.slc.core.test.context.DefaultContextTestData"\r
+               abstract="true">\r
+       </bean>\r
+\r
+</beans>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml b/runtime/org.argeo.slc.lib.detached/src/test/resources/org/argeo/slc/lib/detached/applicationContext.xml
new file mode 100644 (file)
index 0000000..88d6483
--- /dev/null
@@ -0,0 +1,7 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <import resource="classpath:/org/argeo/slc/lib/detached/spring.xml" />
+
+</beans>