From: Mathieu Baudier Date: Fri, 13 Feb 2015 09:12:46 +0000 (+0000) Subject: Move SLC Core X-Git-Tag: argeo-slc-2.1.7~114 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;ds=inline;h=a9b97cc33383ded70277f49aa287f84903334e70;p=gpl%2Fargeo-slc.git Move SLC Core git-svn-id: https://svn.argeo.org/slc/trunk@7836 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/org.argeo.slc.core/.classpath b/org.argeo.slc.core/.classpath index bc86c4239..70b08e830 100644 --- a/org.argeo.slc.core/.classpath +++ b/org.argeo.slc.core/.classpath @@ -1,7 +1,8 @@ + - >> + diff --git a/org.argeo.slc.core/META-INF/spring.handlers b/org.argeo.slc.core/META-INF/spring.handlers new file mode 100644 index 000000000..417a952e8 --- /dev/null +++ b/org.argeo.slc.core/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://www.argeo.org/schema/slc-flow=org.argeo.slc.core.execution.xml.FlowNamespaceHandler \ No newline at end of file diff --git a/org.argeo.slc.core/META-INF/spring.schemas b/org.argeo.slc.core/META-INF/spring.schemas new file mode 100644 index 000000000..229d4c5f6 --- /dev/null +++ b/org.argeo.slc.core/META-INF/spring.schemas @@ -0,0 +1,3 @@ +http\://www.argeo.org/schema/slc-flow.xsd=org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd +http\://www.argeo.org/schema/slc-flow-1.2.xsd=org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd +http\://www.argeo.org/schema/slc-flow-0.12.xsd=org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd diff --git a/org.argeo.slc.core/bin/log4j.properties b/org.argeo.slc.core/bin/log4j.properties new file mode 100644 index 000000000..0133bab88 --- /dev/null +++ b/org.argeo.slc.core/bin/log4j.properties @@ -0,0 +1,22 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=WARN, console + +## Levels +# Slc +log4j.logger.org.argeo=DEBUG + +# Castor +log4j.logger.org.exolab.castor=WARN + +# Spring +log4j.logger.org.springframework=WARN + + +## Appenders +# A1 is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/DefaultResourceSetTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/DefaultResourceSetTest.class new file mode 100644 index 000000000..296f6ef99 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/DefaultResourceSetTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/data/file1.txt b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/data/file1.txt new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/data/subdir/file2.txt b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/data/subdir/file2.txt new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/relativeResourceSet.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/relativeResourceSet.xml new file mode 100644 index 000000000..074c205a5 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/deploy/relativeResourceSet.xml @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.class new file mode 100644 index 000000000..8fdcba1e1 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/BasicExecutionFlowTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/BasicExecutionFlowTest.class new file mode 100644 index 000000000..6a1b8176a Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/BasicExecutionFlowTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/DefaultAgentCliTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/DefaultAgentCliTest.class new file mode 100644 index 000000000..a1e3b70fa Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/DefaultAgentCliTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.class new file mode 100644 index 000000000..e5553236c Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.class new file mode 100644 index 000000000..59737ac63 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesTest.class new file mode 100644 index 000000000..6371da2f7 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/FileExecutionResourcesTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ParameterRefTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ParameterRefTest.class new file mode 100644 index 000000000..f0913e54b Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/ParameterRefTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/applicationContext.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/applicationContext.xml new file mode 100644 index 000000000..d83c2c125 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/applicationContext.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-001.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-001.xml new file mode 100644 index 000000000..a1c59c9b1 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-001.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-002.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-002.xml new file mode 100644 index 000000000..57f0c8a89 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-002.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-003.error.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-003.error.xml new file mode 100644 index 000000000..6de881047 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-003.error.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-004.error.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-004.error.xml new file mode 100644 index 000000000..2638ed6ee --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic-004.error.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic.xml new file mode 100644 index 000000000..8d6af0ef1 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/canonic.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/executionResources.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/executionResources.xml new file mode 100644 index 000000000..654f8b420 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/executionResources.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/imports.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/imports.xml new file mode 100644 index 000000000..7ddb4ea80 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/imports.xml @@ -0,0 +1,36 @@ + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMap.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMap.xml new file mode 100644 index 000000000..8cf72e354 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMap.xml @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + myValue + _myValue_ + + myValue + + + myValue + + + + + + + + + + + + + + + + + + + + + @{testKey} + _@{testKey}_ + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml new file mode 100644 index 000000000..b8626f851 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + myValue + _myValue_ + + myValue + + + myValue + + + + + + + + + + + + + + + + + + + + + @{testKey} + _@{testKey}_ + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/minimal.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/minimal.xml new file mode 100644 index 000000000..5b166970b --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/minimal.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/multipleFlow.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/multipleFlow.xml new file mode 100644 index 000000000..58a43e418 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/multipleFlow.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/parameterRef.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/parameterRef.xml new file mode 100644 index 000000000..98cc14d3d --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/parameterRef.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml new file mode 100644 index 000000000..a36b4a167 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.xml new file mode 100644 index 000000000..893768be3 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/placeHolders.cascading.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/specOverriding.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/specOverriding.xml new file mode 100644 index 000000000..de1dc8504 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/specOverriding.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/SystemCallTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/SystemCallTest.class new file mode 100644 index 000000000..fe381e492 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/SystemCallTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/systemCall.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/systemCall.xml new file mode 100644 index 000000000..8d3565040 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/tasks/systemCall.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + echo + Hello + World + + + + + + + + + + + + + + + + + + + + + + + + + dir + + + + + + + ls + + + + + ls + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/test.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/test.xml new file mode 100644 index 000000000..d8bec3df0 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/test.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From basic @{testedComponentId} + + + testData1='@{testData1}' + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/FlowNamespaceTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/FlowNamespaceTest.class new file mode 100644 index 000000000..3e0cd7cb5 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/FlowNamespaceTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/advanced.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/advanced.xml new file mode 100644 index 000000000..49b6f7e1d --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/advanced.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + spec description + + + + + + + flow description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Would fail if param 2 is not changed at execution + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-001.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-001.xml new file mode 100644 index 000000000..aeef3a3af --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-001.xml @@ -0,0 +1,34 @@ + + + + + + Canonic 001 + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-002.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-002.xml new file mode 100644 index 000000000..ac5f085eb --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns-002.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns.xml new file mode 100644 index 000000000..facb27761 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/canonic-ns.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/containers.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/containers.xml new file mode 100644 index 000000000..61bfa0703 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/containers.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + val1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + val1 + val2 + + + + + val1 + val2 + + + + + + + + + + + + + + + + + + use default value for parameter "list1" + + + val1 + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/tests.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/tests.xml new file mode 100644 index 000000000..ee58a1869 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/execution/xml/tests.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.class b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.class new file mode 100644 index 000000000..0cad464a7 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/ContextTest.class b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/ContextTest.class new file mode 100644 index 000000000..4146eca03 Binary files /dev/null and b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/ContextTest.class differ diff --git a/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/applicationContext.xml b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/applicationContext.xml new file mode 100644 index 000000000..4949c4eb1 --- /dev/null +++ b/org.argeo.slc.core/bin/org/argeo/slc/core/test/context/applicationContext.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/bnd.bnd b/org.argeo.slc.core/bnd.bnd index e69de29bb..40b504bd2 100644 --- a/org.argeo.slc.core/bnd.bnd +++ b/org.argeo.slc.core/bnd.bnd @@ -0,0 +1,8 @@ +Import-Package: org.w3c.dom;version="0.0.0",\ +org.dbunit;resolution:="optional",\ +org.dbunit.database;resolution:="optional",\ +org.dbunit.dataset;resolution:="optional",\ +org.dbunit.dataset.xml;resolution:="optional",\ +org.dbunit.operation;resolution:="optional",\ +junit.framework;resolution:="optional",\ +* diff --git a/org.argeo.slc.core/build.properties b/org.argeo.slc.core/build.properties new file mode 100644 index 000000000..b7b3e4d43 --- /dev/null +++ b/org.argeo.slc.core/build.properties @@ -0,0 +1 @@ +additional.bundles = org.springframework.context diff --git a/org.argeo.slc.core/ext/test/log4j.properties b/org.argeo.slc.core/ext/test/log4j.properties new file mode 100644 index 000000000..0133bab88 --- /dev/null +++ b/org.argeo.slc.core/ext/test/log4j.properties @@ -0,0 +1,22 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=WARN, console + +## Levels +# Slc +log4j.logger.org.argeo=DEBUG + +# Castor +log4j.logger.org.exolab.castor=WARN + +# Spring +log4j.logger.org.springframework=WARN + + +## Appenders +# A1 is set to be a ConsoleAppender. +log4j.appender.console=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/DefaultResourceSetTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/DefaultResourceSetTest.java new file mode 100644 index 000000000..15fb42903 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/DefaultResourceSetTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.test.context.AbstractInternalSpringTestCase; +import org.springframework.core.io.Resource; + +public class DefaultResourceSetTest extends AbstractInternalSpringTestCase { + private final static Log log = LogFactory + .getLog(DefaultResourceSetTest.class); + + public void testListResources() { + DefaultResourceSet rrs = getBean("relativeResourceSet"); + Map res = rrs.listResources(); + for (String relativePath : res.keySet()) + log.debug(relativePath + "=" + res.get(relativePath)); + assertEquals(2, res.size()); + } + + @Override + protected String getApplicationContextLocation() { + return inPackage("relativeResourceSet.xml"); + } + +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/data/file1.txt b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/data/file1.txt new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/data/subdir/file2.txt b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/data/subdir/file2.txt new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/relativeResourceSet.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/relativeResourceSet.xml new file mode 100644 index 000000000..074c205a5 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/deploy/relativeResourceSet.xml @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java new file mode 100644 index 000000000..7cc8705f5 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.test.TestResultPart; +import org.argeo.slc.test.TestStatus; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public abstract class AbstractExecutionFlowTestCase extends TestCase { + + protected final Log log = LogFactory.getLog(getClass()); + + protected void logException(Throwable ex) { + log.info("Got Exception of class " + ex.getClass().toString() + + " with message '" + ex.getMessage() + "'."); + } + + protected void validateTestResult(SimpleTestResult testResult) { + validateTestResult(testResult, TestStatus.PASSED); + } + + protected void validateTestResult(SimpleTestResult testResult, + int expectedStatus) { + for (TestResultPart part : testResult.getParts()) { + if (part.getStatus() != expectedStatus) { + fail("Error found in TestResult: " + part.getMessage()); + } + } + } + + protected ConfigurableApplicationContext createApplicationContext( + String applicationContextSuffix) { + ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext( + inPackage(applicationContextSuffix)); + // applicationContext.start(); + return applicationContext; + } + + protected void configureAndExecuteSlcFlow(String applicationContextSuffix, + String beanName) { + ConfigurableApplicationContext applicationContext = createApplicationContext(applicationContextSuffix); + ExecutionFlow executionFlow = (ExecutionFlow) applicationContext + .getBean(beanName); + executionFlow.run(); + applicationContext.close(); + } + + protected String inPackage(String suffix) { + String prefix = getClass().getPackage().getName().replace('.', '/'); + return prefix + '/' + suffix; + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java new file mode 100644 index 000000000..91be3bdbe --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.HashMap; +import java.util.Map; + +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.test.TestStatus; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.ConfigurableApplicationContext; + +public class BasicExecutionFlowTest extends AbstractExecutionFlowTestCase { + // TO TEST + // - post-processing for @{} replacement in beans with complex properties + // - bean of scope other than execution are not resolved at execution + + // public void testMyTest() throws Exception { + // ConfigurableApplicationContext applicationContext = + // createApplicationContext("test.xml"); + // log.info("Start Execution"); + // ((ExecutionFlow) applicationContext.getBean("flow1")).execute(); + // applicationContext.close(); + // } + + public void testSpecOverriding() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("specOverriding.xml"); + ((ExecutionFlow) applicationContext.getBean("flow2")).run(); + SimpleTestResult res = (SimpleTestResult) applicationContext + .getBean("myTestResult"); + validateTestResult(res); + } + + public void testMultipleFlows() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("multipleFlow.xml"); + ((ExecutionFlow) applicationContext.getBean("flow1")).run(); + SimpleTestResult res = (SimpleTestResult) applicationContext + .getBean("myTestResult"); + validateTestResult(res); + res.getParts().clear(); + ((ExecutionFlow) applicationContext.getBean("flow2")).run(); + validateTestResult(res, TestStatus.FAILED); + applicationContext.close(); + } + + /** + * Test placeholder resolution in a context without scope execution or proxy + * and with cascading flows (the flow A contains the flow B) + * + * @throws Exception + */ + public void testPlaceHolders() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml"); + ((ExecutionFlow) applicationContext.getBean("flowA")).run(); + validateTestResult((SimpleTestResult) applicationContext + .getBean("myTestResult")); + applicationContext.close(); + } + + /** + * Test placeholder resolution in a context without scope execution or proxy + * and with cascading flows (the flow A contains the flow B) setting + * execution values (should have no effect) + * + * @throws Exception + */ + public void testPlaceHoldersWithExecutionValues() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml"); + + ExecutionContext executionContext = (ExecutionContext) applicationContext + .getBean("executionContext"); + Map executionParameters = new HashMap(); + executionParameters.put("p1", "e1"); + executionParameters.put("p2", "e2"); + executionParameters.put("p3", "e3"); + executionParameters.put("p4", "e4"); + executionParameters.put("p5", "e5"); + executionParameters.put("p6", "e6"); + executionParameters.put("p7", "e7"); + executionParameters.put("p8", "e8"); + addVariables(executionContext, executionParameters); + + ((ExecutionFlow) applicationContext.getBean("flowA")).run(); + validateTestResult((SimpleTestResult) applicationContext + .getBean("myTestResult")); + applicationContext.close(); + } + + public void testPlaceHoldersExec() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.exec.xml"); + + ExecutionContext executionContext = (ExecutionContext) applicationContext + .getBean("executionContext"); + Map executionParameters = new HashMap(); + executionParameters.put("p1", "e1"); + executionParameters.put("p2", "e2"); + executionParameters.put("p3", "e3"); + executionParameters.put("p4", "e4"); + executionParameters.put("p5", "e5"); + executionParameters.put("p6", "e6"); + addVariables(executionContext, executionParameters); + + ((ExecutionFlow) applicationContext.getBean("flowA")).run(); + validateTestResult((SimpleTestResult) applicationContext + .getBean("myTestResult")); + applicationContext.close(); + } + + public void testCanonicFlowParameters() throws Exception { + configureAndExecuteSlcFlow("canonic-001.xml", "canonic.001"); + } + + public void testCanonicDefaultValues() throws Exception { + configureAndExecuteSlcFlow("canonic-002.xml", "canonic.002"); + } + + public void testCanonicMissingValues() throws Exception { + try { + configureAndExecuteSlcFlow("canonic-003.error.xml", "canonic.003"); + fail("Parameter not set - should be rejected."); + } catch (BeanCreationException e) { + // exception expected + logException(e); + } + } + + public void testCanonicUnknownParameter() throws Exception { + try { + configureAndExecuteSlcFlow("canonic-004.error.xml", "canonic.004"); + fail("Unknown parameter set - should be rejected."); + } catch (BeanCreationException e) { + // exception expected + logException(e); + } + } + + public void testListSetMap() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMap.xml"); + ExecutionFlow executionFlow = (ExecutionFlow) applicationContext + .getBean("myFlow"); + executionFlow.run(); + + validateTestResult((SimpleTestResult) applicationContext + .getBean("myTestResult")); + + // BasicTestData res = (BasicTestData) + // applicationContext.getBean("cascadingComplex.testData"); + // log.info("res=" + res.getReached().toString()); + + applicationContext.close(); + } + + public void testListSetMapMultipleFlows() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMapMultipleFlow.xml"); + ((ExecutionFlow) applicationContext.getBean("flow1")).run(); + SimpleTestResult res = (SimpleTestResult) applicationContext + .getBean("myTestResult"); + validateTestResult(res); + res.getParts().clear(); + ((ExecutionFlow) applicationContext.getBean("flow2")).run(); + validateTestResult(res, TestStatus.FAILED); + applicationContext.close(); + } + + protected void addVariables(ExecutionContext executionContext, + Map vars) { + for (String key : vars.keySet()) + executionContext.setVariable(key, vars.get(key)); + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/DefaultAgentCliTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/DefaultAgentCliTest.java new file mode 100644 index 000000000..a7d9b8b78 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/DefaultAgentCliTest.java @@ -0,0 +1,18 @@ +package org.argeo.slc.core.execution; + +import java.net.URI; +import java.util.List; + +import junit.framework.TestCase; + +public class DefaultAgentCliTest extends TestCase { + public void testArgsToUris() { + String[] args = { "org.argeo.slc.demo.minimal", "HelloWorld/WithVar", + "--testKey", "555" }; + List uris = DefaultAgentCli.asURIs(args); + assertEquals(1, uris.size()); + assertEquals( + "flow:/org.argeo.slc.demo.minimal/HelloWorld/WithVar?testKey=555", + uris.get(0).toString()); + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java new file mode 100644 index 000000000..55afdc0c8 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.InitializingBean; + +public class ExceptionIfInitCalledTwice implements Runnable, InitializingBean { + private final static Log log = LogFactory + .getLog(ExceptionIfInitCalledTwice.class); + + private Boolean calledOnce = false; + + public void run() { + log.info(getClass().getSimpleName() + " ran properly"); + } + + public void afterPropertiesSet() throws Exception { + log.info(getClass().getSimpleName() + " init method called"); + + if (calledOnce) + throw new SlcException(getClass().getSimpleName() + + "init method called twice."); + else + calledOnce = true; + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java new file mode 100644 index 000000000..8b3d2ec25 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; + +public class FileExecutionResourcesSpringTest extends + AbstractExecutionFlowTestCase { + private String basePath = FileExecutionResources.DEFAULT_EXECUTION_RESOURCES_TMP_PATH; + + public void testSimple() throws Exception { + File file = getFile("subdir/writeTo"); + try { + assertFalse(file.exists()); + configureAndExecuteSlcFlow("executionResources.xml", + "executionResources.simple"); + assertTrue(file.exists()); + } finally { + file.deleteOnExit(); + } + } + + public void testPlaceholderPass() throws Exception { + File file = getFile("subdir/60"); + try { + assertFalse(file.exists()); + configureAndExecuteSlcFlow("executionResources.xml", + "executionResources.placeholderPass"); + assertTrue(file.exists()); + } finally { + file.deleteOnExit(); + } + } + + /** + * Test that it generate the wrong file because of issue when using + * execution placeholder in contructor-arg + */ + public void testPlaceholderFail() throws Exception { + File file = getFile("subdir/@{var}"); + try { + assertFalse(file.exists()); + configureAndExecuteSlcFlow("executionResources.xml", + "executionResources.placeholderFail"); + assertTrue(file.exists()); + } finally { + file.deleteOnExit(); + } + } + + protected File getFile(String relativePath) { + return new File(basePath + File.separator + + relativePath.replace('/', File.separatorChar)); + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesTest.java new file mode 100644 index 000000000..e2dae6564 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/FileExecutionResourcesTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; + +import junit.framework.TestCase; + +import org.apache.commons.io.FileUtils; +import org.argeo.slc.execution.ExecutionContext; +import org.springframework.core.io.Resource; + +public class FileExecutionResourcesTest extends TestCase { + public void testGetWritableFile() throws Exception { + FileExecutionResources executionResources = new FileExecutionResources(); + ExecutionContext executionContext = new MapExecutionContext(); + executionResources.setExecutionContext(executionContext); + + String expected = "TEST"; + String reached = ""; + try { + // Resource + Resource resource = executionResources + .getWritableResource("subdir1/textRes.txt"); + assertTrue(resource.getFile().getParentFile().exists()); + assertFalse(resource.getFile().exists()); + FileUtils.writeStringToFile(resource.getFile(), expected); + reached = FileUtils.readFileToString(resource.getFile()); + assertEquals(expected, reached); + + // File + File file = executionResources.getFile("subdir2/textFile.txt"); + assertFalse(file.getParentFile().exists()); + assertFalse(file.exists()); + FileUtils.writeStringToFile(file, expected); + reached = FileUtils.readFileToString(file); + assertEquals(expected, reached); + } finally { + if (executionResources.getBaseDir() != null + && executionResources.getBaseDir().exists()) + FileUtils.deleteDirectory(executionResources.getBaseDir()); + } + + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java new file mode 100644 index 000000000..35df7eb53 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.test.TestStatus; +import org.springframework.context.ConfigurableApplicationContext; + +public class ParameterRefTest extends AbstractExecutionFlowTestCase { + public void test001() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("parameterRef.xml"); + ((ExecutionFlow) applicationContext.getBean("parameterRef.001")).run(); + + SimpleTestResult res = (SimpleTestResult) applicationContext + .getBean("parameterRef.testResult"); + assertEquals(res.getParts().get(0).getStatus(), TestStatus.PASSED); + assertEquals(res.getParts().get(1).getStatus(), TestStatus.FAILED); + + applicationContext.close(); + } + +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/applicationContext.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/applicationContext.xml new file mode 100644 index 000000000..d83c2c125 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/applicationContext.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-001.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-001.xml new file mode 100644 index 000000000..a1c59c9b1 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-001.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-002.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-002.xml new file mode 100644 index 000000000..57f0c8a89 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-002.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-003.error.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-003.error.xml new file mode 100644 index 000000000..6de881047 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-003.error.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-004.error.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-004.error.xml new file mode 100644 index 000000000..2638ed6ee --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic-004.error.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic.xml new file mode 100644 index 000000000..8d6af0ef1 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/canonic.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/executionResources.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/executionResources.xml new file mode 100644 index 000000000..654f8b420 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/executionResources.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/imports.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/imports.xml new file mode 100644 index 000000000..7ddb4ea80 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/imports.xml @@ -0,0 +1,36 @@ + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMap.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMap.xml new file mode 100644 index 000000000..8cf72e354 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMap.xml @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + myValue + _myValue_ + + myValue + + + myValue + + + + + + + + + + + + + + + + + + + + + @{testKey} + _@{testKey}_ + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml new file mode 100644 index 000000000..b8626f851 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + myValue + _myValue_ + + + + + @{testKey} + _@{testKey}_ + + + + + + + + + myValue + _myValue_ + + myValue + + + + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + myValue + _myValue_ + + + myValue + _myValue_ + + myValue + + + myValue + + + + + + + + + + + + + + + + + + + + + @{testKey} + _@{testKey}_ + + + @{testKey} + _@{testKey}_ + + @{testKey} + + + @{testKey} + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/minimal.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/minimal.xml new file mode 100644 index 000000000..5b166970b --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/minimal.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/multipleFlow.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/multipleFlow.xml new file mode 100644 index 000000000..58a43e418 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/multipleFlow.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/parameterRef.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/parameterRef.xml new file mode 100644 index 000000000..98cc14d3d --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/parameterRef.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml new file mode 100644 index 000000000..a36b4a167 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml new file mode 100644 index 000000000..893768be3 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/specOverriding.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/specOverriding.xml new file mode 100644 index 000000000..de1dc8504 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/specOverriding.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/SystemCallTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/SystemCallTest.java new file mode 100644 index 000000000..8301b8517 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/SystemCallTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase; + +public class SystemCallTest extends AbstractExecutionFlowTestCase { + private final static Log log = LogFactory.getLog(SystemCallTest.class); + + private final String defFile = "systemCall.xml"; + + public void testSystemCallSimple() throws Exception { + if (isOsSupported()) + configureAndExecuteSlcFlow(defFile, "systemCallSimple"); + } + + public void testSystemCallList() throws Exception { + if (isOsSupported()) + configureAndExecuteSlcFlow(defFile, "systemCallList"); + } + + public void testSystemCallOsSpecific() throws Exception { + if (isOsSupported()) + configureAndExecuteSlcFlow(defFile, "systemCallOsSpecific"); + } + + public void testSystemCallWithVar() throws Exception { + if (isOsSupported()) + configureAndExecuteSlcFlow(defFile, "systemCallWithVar"); + } + + protected boolean isOsSupported() { + String osName = System.getProperty("os.name"); + final Boolean ret; + if (osName.contains("Windows")) + ret = false; + else + ret = true; + + if (ret == false) + log.warn("Skip test because OS '" + osName + "' is not supported."); + return ret; + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/systemCall.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/systemCall.xml new file mode 100644 index 000000000..8d3565040 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/tasks/systemCall.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + echo + Hello + World + + + + + + + + + + + + + + + + + + + + + + + + + dir + + + + + + + ls + + + + + ls + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/test.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/test.xml new file mode 100644 index 000000000..d8bec3df0 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/test.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From basic @{testedComponentId} + + + testData1='@{testData1}' + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java new file mode 100644 index 000000000..f673020e6 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase; +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.springframework.context.ConfigurableApplicationContext; + +public class FlowNamespaceTest extends AbstractExecutionFlowTestCase { + public void testCanonical() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("canonic-ns.xml"); + ((ExecutionFlow) applicationContext.getBean("canonic-ns.001")).run(); + ((ExecutionFlow) applicationContext.getBean("canonic-ns.002")).run(); + } + + public void testAdvanced() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("advanced.xml"); + ((ExecutionFlow) applicationContext.getBean("flow1")).run(); + ((ExecutionFlow) applicationContext.getBean("flow2")).run(); + ((ExecutionFlow) applicationContext.getBean("flow3")).run(); + + validateTestResult((SimpleTestResult) applicationContext + .getBean("testResult")); + } + + public void testAdvancedExecution() throws Exception { + ConfigurableApplicationContext applicationContext = createApplicationContext("advanced.xml"); + + ExecutionContext executionContext = (ExecutionContext) applicationContext + .getBean("executionContext"); + executionContext.setVariable("param2", 4); + + ((ExecutionFlow) applicationContext.getBean("flow4")).run(); + + validateTestResult((SimpleTestResult) applicationContext + .getBean("testResult")); + } + + // These tests causes pb when using Spring 3 + + // public void testContainers() throws Exception { + // ConfigurableApplicationContext applicationContext = + // createApplicationContext("containers.xml"); + // ((ExecutionFlow) applicationContext.getBean("test.list.flow1")).run(); + // ((ExecutionFlow) applicationContext.getBean("test.list.flow2")).run(); + // + // validateTestResult((SimpleTestResult) applicationContext + // .getBean("testResult")); + // } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/advanced.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/advanced.xml new file mode 100644 index 000000000..49b6f7e1d --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/advanced.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + spec description + + + + + + + flow description + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Would fail if param 2 is not changed at execution + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-001.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-001.xml new file mode 100644 index 000000000..aeef3a3af --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-001.xml @@ -0,0 +1,34 @@ + + + + + + Canonic 001 + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml new file mode 100644 index 000000000..ac5f085eb --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml new file mode 100644 index 000000000..facb27761 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/containers.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/containers.xml new file mode 100644 index 000000000..61bfa0703 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/containers.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + val1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + val1 + val2 + + + + + val1 + val2 + + + + + + + + + + + + + + + + + + use default value for parameter "list1" + + + val1 + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/tests.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/tests.xml new file mode 100644 index 000000000..ee58a1869 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/execution/xml/tests.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java new file mode 100644 index 000000000..61eb3b2b3 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** Helper for tests using a Spring application context. */ +public abstract class AbstractInternalSpringTestCase extends TestCase { + protected final Log log = LogFactory.getLog(getClass()); + private ConfigurableApplicationContext context; + + /** + * Gets (and create if necessary) the application context to use. Default + * implementation uses a class path xml application context and calls + * {@link #getApplicationContextLocation()}. + */ + protected ConfigurableApplicationContext getContext() { + if (context == null) { + context = new ClassPathXmlApplicationContext( + getApplicationContextLocation()); + } + return context; + } + + /** Returns a bean from the underlying context */ + @SuppressWarnings(value = { "unchecked" }) + protected T getBean(String beanId) { + return (T) getContext().getBean(beanId); + } + + protected T getBean(Class clss) { + T bean = loadSingleFromContext(getContext(), clss); + if (bean == null) { + throw new SlcException("Cannot retrieve a unique bean of type " + + clss); + } else { + return bean; + } + } + + /** + * Th location of the application to load. The default implementation + * returns applicationContext.xml found in the same package as the + * test. + */ + protected String getApplicationContextLocation() { + return inPackage("applicationContext.xml"); + } + + /** + * Prefixes the package of the class after converting the '.' to '/' in + * order to have a resource path. + */ + protected String inPackage(String suffix) { + String prefix = getClass().getPackage().getName().replace('.', '/'); + return prefix + '/' + suffix; + } + + @SuppressWarnings(value = { "unchecked" }) + protected T loadSingleFromContext(ListableBeanFactory context, + Class clss) { + Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( + context, clss, false, false); + if (beans.size() == 1) { + return beans.values().iterator().next(); + } else if (beans.size() > 1) { + if (log.isDebugEnabled()) { + log + .debug(("Found more that on bean for type " + clss + + ": " + beans.keySet())); + } + return null; + } else { + return null; + } + } + +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/ContextTest.java b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/ContextTest.java new file mode 100644 index 000000000..694851c82 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/ContextTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import java.util.List; + +import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.test.TestResultPart; +import org.argeo.slc.test.TestStatus; +import org.argeo.slc.test.context.ContextAware; + +public class ContextTest extends AbstractInternalSpringTestCase { + + public void testComplexContext() { + SimpleTestResult testResult = new SimpleTestResult(); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c1"), testResult); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c2"), testResult); + ContextUtils.compareReachedExpected( + (ContextAware) getBean("context.c3"), testResult); + + List parts = testResult.getParts(); + assertEquals(6, parts.size()); + assertEquals(TestStatus.PASSED, parts.get(0).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(1).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(2).getStatus()); + assertEquals(TestStatus.FAILED, parts.get(3).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(4).getStatus()); + assertEquals(TestStatus.PASSED, parts.get(5).getStatus()); + } +} diff --git a/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/applicationContext.xml b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/applicationContext.xml new file mode 100644 index 000000000..4949c4eb1 --- /dev/null +++ b/org.argeo.slc.core/ext/test/org/argeo/slc/core/test/context/applicationContext.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/pom.xml b/org.argeo.slc.core/pom.xml index 76aee0880..653884040 100644 --- a/org.argeo.slc.core/pom.xml +++ b/org.argeo.slc.core/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 org.argeo.slc @@ -8,4 +9,25 @@ org.argeo.slc.core SLC Runtime + + + + org.argeo.commons + org.argeo.util + ${version.argeo-commons} + + + org.argeo.commons + org.argeo.security.core + ${version.argeo-commons} + + + + + org.argeo.slc + org.argeo.slc.api + 2.1.1-SNAPSHOT + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/Attachment.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/Attachment.java new file mode 100644 index 000000000..ecde0b936 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/Attachment.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +public interface Attachment { + public String getUuid(); + + public void setUuid(String uuid); + + public String getName(); + + public String getContentType(); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentUploader.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentUploader.java new file mode 100644 index 000000000..eb484c92c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentUploader.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +import org.springframework.core.io.Resource; + +public interface AttachmentUploader { + public void upload(Attachment attachment, Resource resource); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsEnabled.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsEnabled.java new file mode 100644 index 000000000..780a6a483 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsEnabled.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +public interface AttachmentsEnabled { + public void addAttachment(Attachment attachment); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsStorage.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsStorage.java new file mode 100644 index 000000000..2214afabf --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/AttachmentsStorage.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +import java.io.InputStream; +import java.io.OutputStream; + +public interface AttachmentsStorage { + public void retrieveAttachment(Attachment attachment, + OutputStream outputStream); + + /** Does NOT close the provided input stream. */ + public void storeAttachment(Attachment attachment, InputStream inputStream); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/FileAttachmentsStorage.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/FileAttachmentsStorage.java new file mode 100644 index 000000000..3b7e62dac --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/FileAttachmentsStorage.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; + +public class FileAttachmentsStorage implements AttachmentsStorage, + AttachmentUploader, InitializingBean { + private final static Log log = LogFactory + .getLog(FileAttachmentsStorage.class); + + private File attachmentsDirectory; + + private String attachmentsTocFileName = "attachmentsToc.csv"; + + private DateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd"); + private DateFormat dateFormatTime = new SimpleDateFormat("HH:mm:ss"); + + public void afterPropertiesSet() { + if (attachmentsDirectory == null) { + + String osgiInstanceArea = System.getProperty("osgi.instance.area"); + if (osgiInstanceArea != null) { + if (osgiInstanceArea.startsWith("file:")) + osgiInstanceArea = osgiInstanceArea.substring("file:" + .length()); + attachmentsDirectory = new File(osgiInstanceArea + + File.separator + "slcAttachments"); + } + + if (attachmentsDirectory == null) { + String tempDir = System.getProperty("java.io.tmpdir"); + attachmentsDirectory = new File(tempDir + File.separator + + "slcAttachments"); + } + } + if (!attachmentsDirectory.exists()) + attachmentsDirectory.mkdirs(); + if (log.isDebugEnabled()) + log.debug("File attachment storage initialized in directory " + + attachmentsDirectory); + } + + public void retrieveAttachment(Attachment attachment, + OutputStream outputStream) { + File file = getFile(attachment); + InputStream in = null; + try { + byte[] buffer = new byte[1024 * 1024]; + in = new FileInputStream(file); + int read = -1; + while ((read = in.read(buffer)) >= 0) { + outputStream.write(buffer, 0, read); + } + if (log.isTraceEnabled()) + log.trace("Read " + attachment + " from " + file); + } catch (IOException e) { + throw new SlcException("Cannot write attachment " + attachment + + " to " + file, e); + } finally { + IOUtils.closeQuietly(in); + } + } + + public void storeAttachment(Attachment attachment, InputStream inputStream) { + File file = getFile(attachment); + FileOutputStream out = null; + try { + byte[] buffer = new byte[1024 * 1024]; + out = new FileOutputStream(file); + int read = -1; + while ((read = inputStream.read(buffer)) >= 0) { + out.write(buffer, 0, read); + } + if (log.isTraceEnabled()) + log.trace("Wrote " + attachment + " to " + file); + updateAttachmentToc(attachment, file); + } catch (IOException e) { + throw new SlcException("Cannot write attachment " + attachment + + " to " + file, e); + } finally { + IOUtils.closeQuietly(out); + } + + } + + public void upload(Attachment attachment, Resource resource) { + try { + storeAttachment(attachment, resource.getInputStream()); + } catch (IOException e) { + throw new SlcException("Cannot upload attachment " + attachment, e); + } + } + + /** For monitoring purposes only */ + protected void updateAttachmentToc(Attachment attachment, File file) { + Date date = new Date(file.lastModified()); + FileWriter writer = null; + try { + writer = new FileWriter(attachmentsDirectory + File.separator + + attachmentsTocFileName, true); + writer.append(dateFormatDay.format(date)); + writer.append(','); + writer.append(dateFormatTime.format(date)); + writer.append(','); + writer.append(attachment.getUuid()); + writer.append(','); + writer.append(attachment.getName()); + writer.append(','); + writer.append(attachment.getContentType()); + writer.append(','); + writer.append(Long.toString(file.length())); + writer.append(','); + writer.append(file.getCanonicalPath()); + writer.append('\n'); + } catch (IOException e) { + log.warn("Could not update attachments TOC for " + attachment + + " and file " + file, e); + } finally { + IOUtils.closeQuietly(writer); + } + + } + + protected File getFile(Attachment attachment) { + File file = new File(attachmentsDirectory + File.separator + + attachment.getUuid()); + return file; + } + + public void setAttachmentsDirectory(File attachmentsDirectory) { + this.attachmentsDirectory = attachmentsDirectory; + } + + public void setAttachmentsTocFileName(String attachmentsTocFileName) { + this.attachmentsTocFileName = attachmentsTocFileName; + } + + public void setDateFormatDay(DateFormat dateFormatDay) { + this.dateFormatDay = dateFormatDay; + } + + public void setDateFormatTime(DateFormat dateFormatTime) { + this.dateFormatTime = dateFormatTime; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/attachment/SimpleAttachment.java b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/SimpleAttachment.java new file mode 100644 index 000000000..6248dd71e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/attachment/SimpleAttachment.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.attachment; + +import java.io.Serializable; +import java.util.UUID; + +public class SimpleAttachment implements Attachment, Serializable { + private static final long serialVersionUID = 6615155908800610606L; + private String uuid = UUID.randomUUID().toString(); + private String name; + private String contentType = ""; + + public SimpleAttachment() { + } + + public SimpleAttachment(String uuid, String name, String contentType) { + super(); + this.uuid = uuid; + this.name = name; + this.contentType = contentType; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public String toString() { + return "Attachment #" + uuid + "(" + name + ", " + contentType + ")"; + } + + public boolean equals(Object obj) { + if (obj instanceof Attachment) { + Attachment attachment = (Attachment) obj; + if (uuid != null && attachment.getUuid() != null) + return uuid.equals(attachment.getUuid()); + + if (name != null && attachment.getName() != null) + return name.equals(attachment.getName()); + + return hashCode() == attachment.hashCode(); + } + return false; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/build/ResourceDistribution.java b/org.argeo.slc.core/src/org/argeo/slc/core/build/ResourceDistribution.java new file mode 100644 index 000000000..4ebbe92a4 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/build/ResourceDistribution.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.build; + +import java.io.IOException; +import java.io.InputStream; + +import org.argeo.slc.SlcException; +import org.argeo.slc.StreamReadable; +import org.argeo.slc.build.Distribution; +import org.springframework.core.io.Resource; + +/** A software distribution archive accessible via a {@link Resource}. */ +public class ResourceDistribution implements Distribution, StreamReadable { + private Resource resource; + + public ResourceDistribution() { + } + + public ResourceDistribution(Resource location) { + this.resource = location; + } + + public String getDistributionId() { + return resource.toString(); + } + + public Resource getResource() { + return resource; + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + public InputStream getInputStream() { + try { + return resource.getInputStream(); + } catch (IOException e) { + throw new SlcException("Cannot get input stream", e); + } + } + + @Override + public String toString() { + return resource.toString(); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionDistributionId.java b/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionDistributionId.java new file mode 100644 index 000000000..c11dc00ea --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionDistributionId.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.build; + +import java.util.StringTokenizer; + +/** + *

+ * An implementation of the distribution id using the standard + * Major.Minor.Release notation. And additional arbitrary string can also be + * added. + *

+ * + *

+ * Examples:
+ * 0.2.6
+ * 2.4.12.RC1 + *

+ */ +public class VersionDistributionId { + + private Integer major; + private Integer minor; + private Integer release; + private String additional; + + /** Parse the provided string in order to set the various components. */ + public void setVersionString(String str) { + StringTokenizer st = new StringTokenizer(str, "."); + if (st.hasMoreTokens()) + major = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + minor = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + release = Integer.parseInt(st.nextToken()); + if (st.hasMoreTokens()) + additional = st.nextToken(); + } + + public Integer getMajor() { + return major; + } + + public void setMajor(Integer major) { + this.major = major; + } + + public Integer getMinor() { + return minor; + } + + public void setMinor(Integer minor) { + this.minor = minor; + } + + public Integer getRelease() { + return release; + } + + public void setRelease(Integer release) { + this.release = release; + } + + public String getAdditional() { + return additional; + } + + public void setAdditional(String additional) { + this.additional = additional; + } + + @Override + public boolean equals(Object obj) { + // TODO Auto-generated method stub + return super.equals(obj); + } + + @Override + public String toString() { + return major + "." + minor + "." + release + + (additional != null ? "." + additional : ""); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionedResourceDistribution.java b/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionedResourceDistribution.java new file mode 100644 index 000000000..52307ec67 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/build/VersionedResourceDistribution.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.build; + +import org.argeo.slc.NameVersion; +import org.springframework.core.io.Resource; + +/** + * The distribution of a software package (jar, zip, RPM, etc.) which is + * versioned. The archive itself is accessible via a {@link Resource}. + */ +public class VersionedResourceDistribution extends ResourceDistribution + implements NameVersion { + private String name; + private String version; + + public VersionedResourceDistribution() { + super(); + } + + public VersionedResourceDistribution(NameVersion nameVersion, + Resource resource) { + this(nameVersion.getName(), nameVersion.getVersion(), resource); + } + + public VersionedResourceDistribution(String name, String version, + Resource resource) { + super(resource); + this.name = name; + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/build/package.html b/org.argeo.slc.core/src/org/argeo/slc/core/build/package.html new file mode 100644 index 000000000..5da205278 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/build/package.html @@ -0,0 +1,6 @@ + + + +SLC Build: building of software systems. + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DefaultResourceSet.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DefaultResourceSet.java new file mode 100644 index 000000000..abdcfeec3 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DefaultResourceSet.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +public class DefaultResourceSet implements ResourceLoaderAware, + InitializingBean, ResourceSet { + private final static Log log = LogFactory.getLog(DefaultResourceSet.class); + public final static String DEFAULT_EXCLUDES = "**/.svn/**"; + + private String base; + private String include; + private List includes = new ArrayList(); + private String exclude; + private List excludes = new ArrayList(); + private Boolean useDefaultExcludes = true; + private ResourcePatternResolver resourcePatternResolver; + private PathMatcher excludePathMatcher = new AntPathMatcher(); + + private ResourceLoader resourceLoader; + + /** List the resources, identified by their relative path. */ + public Map listResources() { + try { + Map res = new TreeMap(); + if (base == null) + return res; + String baseResUrl = getResourceLoaderToUse().getResource(base) + .getURL().toString(); + for (String includePattern : includes) + processInclude(res, includePattern, baseResUrl); + return res; + } catch (IOException e) { + throw new SlcException("Cannot list resource from " + base, e); + } + } + + protected void processInclude(Map res, String include, + String baseResUrl) throws IOException { + String pattern = base + "/" + include; + if (log.isTraceEnabled()) + log.trace("Look for resources with pattern '" + pattern + + "' in base url " + baseResUrl); + Resource[] resources = resourcePatternResolver.getResources(pattern); + resources: for (Resource resource : resources) { + String url = resource.getURL().toString(); + String relPath = url.substring(baseResUrl.length()); + + // skip dir + if (relPath.charAt(relPath.length() - 1) == '/') { + if (log.isTraceEnabled()) + log.trace("Skip directory " + relPath + "=" + resource); + continue resources; + } + + // make sure there is not starting '/' + if (relPath.charAt(0) == '/') + relPath = relPath.substring(1); + + // skip excludes + for (String exclude : excludes) + if (excludePathMatcher.match(exclude, relPath)) { + if (log.isTraceEnabled()) + log.trace("Exclude " + relPath + "=" + resource); + continue resources; + } + + // check if already exists + if (res.containsKey(relPath)) + log.warn(relPath + " already matched by " + res.get(relPath) + + ", " + resource + " will override it."); + + // store the marched resource + res.put(relPath, resource); + if (log.isTraceEnabled()) + log.trace(relPath + "=" + resource); + } + + } + + public void afterPropertiesSet() throws Exception { + if (resourcePatternResolver == null) + resourcePatternResolver = new PathMatchingResourcePatternResolver( + getResourceLoaderToUse()); + if (include != null) + addCommaSeparatedToList(include, includes); + if (exclude != null) + addCommaSeparatedToList(exclude, excludes); + + if (includes.size() == 0) + includes.add("**"); + + if (useDefaultExcludes) + addCommaSeparatedToList(DEFAULT_EXCLUDES, excludes); + } + + private void addCommaSeparatedToList(String str, List lst) { + StringTokenizer st = new StringTokenizer(str, ","); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (!lst.contains(token)) + lst.add(token); + } + } + + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + /** + * Can be overridden in order to provide the proper resource loader used to + * resolve resources. + */ + public ResourceLoader getResourceLoaderToUse() { + return resourceLoader; + } + + public void setBase(String base) { + this.base = base; + } + + public void setInclude(String include) { + this.include = include; + } + + public void setIncludes(List includes) { + this.includes = includes; + } + + public void setExclude(String exclude) { + this.exclude = exclude; + } + + public void setExcludes(List excludes) { + this.excludes = excludes; + } + + public void setUseDefaultExcludes(Boolean useDefaultExcludes) { + this.useDefaultExcludes = useDefaultExcludes; + } + + public void setExcludePathMatcher(PathMatcher excludePathMatcher) { + this.excludePathMatcher = excludePathMatcher; + } + + public void setResourcePatternResolver( + ResourcePatternResolver resourcePatternResolver) { + this.resourcePatternResolver = resourcePatternResolver; + } + + public ResourcePatternResolver getResourcePatternResolver() { + return resourcePatternResolver; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DigestCheck.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DigestCheck.java new file mode 100644 index 000000000..5df54232c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/DigestCheck.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.io.IOException; + +import org.argeo.slc.SlcException; +import org.argeo.util.security.DigestUtils; +import org.springframework.core.io.Resource; + +/** Add Spring capabilities to {@link DigestUtils} */ +public class DigestCheck extends DigestUtils { + public static String digest(String algorithm, Resource resource) { + try { + File file = resource.getFile(); + return digest(algorithm, file); + } catch (IOException e) { + try { + return digest(algorithm, resource.getInputStream()); + } catch (IOException e1) { + throw new SlcException("Cannot digest " + resource + + " with algorithm " + algorithm, e); + } + } + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/LocalFilesDeployment.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/LocalFilesDeployment.java new file mode 100644 index 000000000..79ad83597 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/LocalFilesDeployment.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.argeo.slc.SlcException; +import org.springframework.core.io.Resource; + +public class LocalFilesDeployment implements Runnable { + private String targetBase = ""; + private ResourceSet resourceSet; + + public LocalFilesDeployment() { + } + + public LocalFilesDeployment(ResourceSet resourceSet) { + this.resourceSet = resourceSet; + } + + public void run() { + Map resources = resourceSet.listResources(); + for (String relPath : resources.keySet()) { + File targetFile = new File(targetBase + File.separator + relPath); + File parentDir = targetFile.getParentFile(); + if (!parentDir.exists()) + parentDir.mkdirs(); + + Resource resource = resources.get(relPath); + + InputStream in = null; + OutputStream out = null; + try { + in = resource.getInputStream(); + out = FileUtils.openOutputStream(targetFile); + IOUtils.copy(in, out); + } catch (IOException e) { + throw new SlcException("Cannot extract " + resource + " to " + + targetFile, e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + } + + public void setTargetBase(String targetBase) { + this.targetBase = targetBase; + } + + public void setResourceSet(ResourceSet resourceSet) { + this.resourceSet = resourceSet; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/MultiResourceSet.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/MultiResourceSet.java new file mode 100644 index 000000000..8da17ba42 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/MultiResourceSet.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.core.io.Resource; + +public class MultiResourceSet implements ResourceSet { + private List resourceSets = new ArrayList(); + + public Map listResources() { + Map res = new HashMap(); + for (ResourceSet resourceSet : resourceSets) { + res.putAll(resourceSet.listResources()); + } + return res; + } + + /** Last listed override previous for the same relative paths. */ + public void setResourceSets(List resourceSets) { + this.resourceSets = resourceSets; + } + + public List getResourceSets() { + return resourceSets; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/ResourceSet.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/ResourceSet.java new file mode 100644 index 000000000..01c01abae --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/ResourceSet.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.util.Map; + +import org.springframework.core.io.Resource; + +public interface ResourceSet { + /** + * List the resources, identified by their relative path. Relative paths + * must NOT start with a '/'. + */ + public Map listResources(); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/SimpleExecutables.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/SimpleExecutables.java new file mode 100644 index 000000000..5a5b8259f --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/SimpleExecutables.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.build.Distribution; +import org.argeo.slc.deploy.DeploymentData; +import org.argeo.slc.deploy.InstalledExecutables; +import org.argeo.slc.deploy.TargetData; + +public class SimpleExecutables implements InstalledExecutables { + private final static Log log = LogFactory.getLog(SimpleExecutables.class); + + private String baseDir; + private Map paths = new TreeMap(); + + private Distribution distribution; + + public String getExecutablePath(String key) { + String path = paths.get(key); + if (path == null) { + if (log.isDebugEnabled()) + log.debug("No executable path found for key " + key + + ", using the key as executable name."); + path = key; + } + + if (baseDir != null) + path = baseDir + File.separator + path; + return path; + } + + public String getDeployedSystemId() { + // TODO Auto-generated method stub + return null; + } + + public DeploymentData getDeploymentData() { + // TODO Auto-generated method stub + return null; + } + + public Distribution getDistribution() { + return distribution; + } + + public TargetData getTargetData() { + // TODO Auto-generated method stub + return null; + } + + public String getBaseDir() { + return baseDir; + } + + public void setBaseDir(String baseDir) { + this.baseDir = baseDir; + } + + public Map getPaths() { + return paths; + } + + public void setPaths(Map paths) { + this.paths = paths; + } + + public void setDistribution(Distribution distribution) { + this.distribution = distribution; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/VersionedDirSync.java b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/VersionedDirSync.java new file mode 100644 index 000000000..13d254366 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/VersionedDirSync.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.deploy; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.deploy.VersioningDriver; + +/** + * Synchronizes an URL to a local directory, taking into account versioning + * information if possible. + */ +public class VersionedDirSync implements Runnable { + private final static Log log = LogFactory.getLog(VersionedDirSync.class); + + private VersioningDriver versioningDriver; + private File dir; + private String url; + private Boolean clean = false; + + private Boolean changed = null; + + public void run() { + changed = null; + if (clean) { + try { + log.info("Clean " + dir); + FileUtils.deleteDirectory(dir); + } catch (IOException e) { + throw new SlcException("Cannot delete checkout directory " + + dir, e); + } + dir.mkdirs(); + } + log.info("Checkout " + url + " to " + dir); + changed = versioningDriver.checkout(url, dir, true); + if (log.isDebugEnabled()) + log.debug("Synchronized " + url + " to " + dir); + } + + public void setVersioningDriver(VersioningDriver versioningDriver) { + this.versioningDriver = versioningDriver; + } + + public void setDir(File dir) { + this.dir = dir; + } + + public void setUrl(String url) { + this.url = url; + } + + /** Delete before checkout */ + public void setClean(Boolean clean) { + this.clean = clean; + } + + /** Whether last call has changed the directory */ + public Boolean getChanged() { + if (changed == null) + throw new SlcException("Sync has not run"); + return changed; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/deploy/package.html b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/package.html new file mode 100644 index 000000000..f3a4c5bd6 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/deploy/package.html @@ -0,0 +1,6 @@ + + + +SLC Deploy: deployment of software systems. + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java new file mode 100644 index 000000000..dc55b40f9 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; + +public abstract class AbstractExecutionFlowGenerator implements + BeanFactoryPostProcessor, PriorityOrdered { + private final Log log = LogFactory.getLog(getClass()); + + protected abstract Map createExecutionFlowDefinitions( + ConfigurableListableBeanFactory beanFactory); + + public void postProcessBeanFactory( + ConfigurableListableBeanFactory beanFactory) throws BeansException { + if (!(beanFactory instanceof BeanDefinitionRegistry)) { + throw new SlcException("Can only work on " + + BeanDefinitionRegistry.class); + } + + Map definitions = createExecutionFlowDefinitions(beanFactory); + + for (String beanName : definitions.keySet()) { + if (log.isTraceEnabled()) + log.debug("Registering execution flow " + beanName); + ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition( + beanName, definitions.get(beanName)); + } + } + + protected GenericBeanDefinition createDefaultFlowDefinition( + List executables) { + GenericBeanDefinition bd = new GenericBeanDefinition(); + bd.setBeanClass(DefaultExecutionFlow.class); + + MutablePropertyValues mpv = new MutablePropertyValues(); + mpv.addPropertyValue("executables", executables); + + bd.setPropertyValues(mpv); + return bd; + } + + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java new file mode 100644 index 000000000..1a07313f0 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.RealizedFlow; + +/** Provides the base feature of an execution module manager. */ +public abstract class AbstractExecutionModulesManager implements + ExecutionModulesManager { + private final static Log log = LogFactory + .getLog(AbstractExecutionModulesManager.class); + +// private List filteredNotifiers = Collections +// .synchronizedList(new ArrayList()); + + protected abstract ExecutionFlow findExecutionFlow(String moduleName, + String moduleVersion, String flowName); + + protected abstract ExecutionContext findExecutionContext(String moduleName, + String moduleVersion); + + protected abstract ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter( + String moduleName, String moduleVersion); + + public void execute(RealizedFlow realizedFlow) { + if (log.isTraceEnabled()) + log.trace("Executing " + realizedFlow); + + String moduleName = realizedFlow.getModuleName(); + String moduleVersion = realizedFlow.getModuleVersion(); + + Map variablesToAdd = getExecutionFlowDescriptorConverter( + moduleName, moduleVersion).convertValues( + realizedFlow.getFlowDescriptor()); + ExecutionContext executionContext = findExecutionContext(moduleName, + moduleVersion); + for (String key : variablesToAdd.keySet()) + executionContext.setVariable(key, variablesToAdd.get(key)); + + ExecutionFlow flow = findExecutionFlow(moduleName, moduleVersion, + realizedFlow.getFlowDescriptor().getName()); + + // + // Actually runs the flow, IN THIS THREAD + // + flow.run(); + // + // + // + } + +// public void dispatchUpdateStatus(ExecutionProcess process, +// String oldStatus, String newStatus) { +// // filtered notifiers +// for (Iterator it = filteredNotifiers.iterator(); it +// .hasNext();) { +// FilteredNotifier filteredNotifier = it.next(); +// if (filteredNotifier.receiveFrom(process)) +// filteredNotifier.getNotifier().updateStatus(process, oldStatus, +// newStatus); +// } +// +// } + +// public void dispatchAddSteps(ExecutionProcess process, +// List steps) { +// process.addSteps(steps); +// for (Iterator it = filteredNotifiers.iterator(); it +// .hasNext();) { +// FilteredNotifier filteredNotifier = it.next(); +// if (filteredNotifier.receiveFrom(process)) +// filteredNotifier.getNotifier().addSteps(process, steps); +// } +// } + +// public void registerProcessNotifier(ExecutionProcessNotifier notifier, +// Map properties) { +// filteredNotifiers.add(new FilteredNotifier(notifier, properties)); +// } +// +// public void unregisterProcessNotifier(ExecutionProcessNotifier notifier, +// Map properties) { +// filteredNotifiers.remove(notifier); +// } + +// protected class FilteredNotifier { +// private final ExecutionProcessNotifier notifier; +// private final String processId; +// +// public FilteredNotifier(ExecutionProcessNotifier notifier, +// Map properties) { +// super(); +// this.notifier = notifier; +// if (properties == null) +// properties = new HashMap(); +// if (properties.containsKey(SLC_PROCESS_ID)) +// processId = properties.get(SLC_PROCESS_ID); +// else +// processId = null; +// } +// +// /** +// * Whether event from this process should be received by this listener. +// */ +// public Boolean receiveFrom(ExecutionProcess process) { +// if (processId != null) +// if (process.getUuid().equals(processId)) +// return true; +// else +// return false; +// return true; +// } +// +// @Override +// public int hashCode() { +// return notifier.hashCode(); +// } +// +// @Override +// public boolean equals(Object obj) { +// if (obj instanceof FilteredNotifier) { +// FilteredNotifier fn = (FilteredNotifier) obj; +// return notifier.equals(fn.notifier); +// } else if (obj instanceof ExecutionProcessNotifier) { +// ExecutionProcessNotifier epn = (ExecutionProcessNotifier) obj; +// return notifier.equals(epn); +// } else +// return false; +// } +// +// public ExecutionProcessNotifier getNotifier() { +// return notifier; +// } +// +// } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionValue.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionValue.java new file mode 100644 index 000000000..131ffec75 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractExecutionValue.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.Serializable; + +/** Value to be used by an execution */ +public abstract class AbstractExecutionValue implements Serializable { + private static final long serialVersionUID = 1558444746120706961L; +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpecAttribute.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpecAttribute.java new file mode 100644 index 000000000..109c0335e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpecAttribute.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.Serializable; + +import org.argeo.slc.execution.ExecutionSpecAttribute; + +/** Canonical implementation of the execution spec attribute booleans. */ +public abstract class AbstractSpecAttribute implements ExecutionSpecAttribute, + Serializable { + private static final long serialVersionUID = 6494963738891709440L; + private Boolean isImmutable = false; + private Boolean isConstant = false; + private Boolean isHidden = false; + + private String description; + + /** Has to be set at instantiation */ + public Boolean getIsImmutable() { + return isImmutable; + } + + public void setIsImmutable(Boolean isImmutable) { + this.isImmutable = isImmutable; + } + + /** Cannot be overridden at runtime */ + public Boolean getIsConstant() { + return isConstant; + } + + public void setIsConstant(Boolean isConstant) { + this.isConstant = isConstant; + } + + /** Should not be shown to the end user */ + public Boolean getIsHidden() { + return isHidden; + } + + public void setIsHidden(Boolean isHidden) { + this.isHidden = isHidden; + } + + /* + * DEPRECATED + */ + /** @deprecated use {@link #getIsImmutable()} instead */ + public Boolean getIsParameter() { + return isImmutable; + } + + /** @deprecated use {@link #getIsConstant()} instead */ + public Boolean getIsFrozen() { + return isConstant; + } + + /** @deprecated use {@link #setIsImmutable(Boolean)} instead */ + public void setIsParameter(Boolean isParameter) { + this.isImmutable = isParameter; + } + + /** @deprecated use {@link #setIsConstant(Boolean)} instead */ + public void setIsFrozen(Boolean isFrozen) { + this.isConstant = isFrozen; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java new file mode 100644 index 000000000..b2252f6a2 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.argeo.slc.execution.ExecutionModule; + +@Deprecated +public abstract class AbstractSpringExecutionModule implements ExecutionModule + { +/* + protected ApplicationContext applicationContext; + + protected ExecutionContext executionContext; + + protected ExecutionFlowDescriptorConverter descriptorConverter = new DefaultDescriptorConverter(); + + public ExecutionModuleDescriptor getDescriptor() { + ExecutionModuleDescriptor md = new ExecutionModuleDescriptor(); + md.setName(getName()); + md.setVersion(getVersion()); + + Map executionFlows = listFlows(); + for (String name : executionFlows.keySet()) { + ExecutionFlow executionFlow = executionFlows.get(name); + + Assert.notNull(executionFlow.getName()); + Assert.state(name.equals(executionFlow.getName())); + + ExecutionSpec executionSpec = executionFlow.getExecutionSpec(); + Assert.notNull(executionSpec); + Assert.notNull(executionSpec.getName()); + + Map values = new TreeMap(); + for (String key : executionSpec.getAttributes().keySet()) { + ExecutionSpecAttribute attribute = executionSpec + .getAttributes().get(key); + + if (executionFlow.isSetAsParameter(key)) { + Object value = executionFlow.getParameter(key); + if (attribute instanceof PrimitiveSpecAttribute) { + PrimitiveValue primitiveValue = new PrimitiveValue(); + primitiveValue + .setType(((PrimitiveSpecAttribute) attribute) + .getType()); + primitiveValue.setValue(value); + values.put(key, primitiveValue); + } else if (attribute instanceof RefSpecAttribute) { + RefValue refValue = new RefValue(); + if (value instanceof ScopedObject) { + refValue.setLabel("RUNTIME " + + value.getClass().getName()); + } else { + refValue.setLabel("STATIC " + + value.getClass().getName()); + } + values.put(key, refValue); + } else if (attribute instanceof ResourceSpecAttribute) { + PrimitiveValue primitiveValue = new PrimitiveValue(); + primitiveValue + .setType(((ResourceSpecAttribute) attribute) + .getType()); + primitiveValue.setValue(value); + values.put(key, primitiveValue); + } else { + throw new SlcException("Unkown spec attribute type " + + attribute.getClass()); + } + } + + } + + ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name, + values, executionSpec); + if (executionFlow.getPath() != null) + efd.setPath(executionFlow.getPath()); + + // Add execution spec if necessary + if (!md.getExecutionSpecs().contains(executionSpec)) + md.getExecutionSpecs().add(executionSpec); + + // Add execution flow + md.getExecutionFlows().add(efd); + } + + return md; + } + + protected Map listFlows() { + GenericBeanFactoryAccessor accessor = new GenericBeanFactoryAccessor( + applicationContext); + Map executionFlows = accessor + .getBeansOfType(ExecutionFlow.class); + return executionFlows; + } + + public void execute(ExecutionFlowDescriptor executionFlowDescriptor) { + if (descriptorConverter != null) + executionContext.addVariables(descriptorConverter + .convertValues(executionFlowDescriptor)); + ExecutionFlow flow = (ExecutionFlow) applicationContext.getBean( + executionFlowDescriptor.getName(), ExecutionFlow.class); + flow.run(); + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + public void setDescriptorConverter( + ExecutionFlowDescriptorConverter descriptorConverter) { + this.descriptorConverter = descriptorConverter; + }*/ + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgent.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgent.java new file mode 100644 index 000000000..aaa687fd7 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgent.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLDecoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.argeo.slc.BasicNameVersion; +import org.argeo.slc.NameVersion; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.execution.SlcAgent; + +/** Implements the base methods of an SLC agent. */ +public class DefaultAgent implements SlcAgent { + // private final static Log log = LogFactory.getLog(DefaultAgent.class); + /** UTF-8 charset for encoding. */ + private final static String UTF8 = "UTF-8"; + + private String agentUuid = null; + private ExecutionModulesManager modulesManager; + + private ThreadGroup processesThreadGroup; + private Map runningProcesses = Collections + .synchronizedMap(new HashMap()); + + private String defaultModulePrefix = null; + + /* + * LIFECYCLE + */ + /** Initialization */ + public void init() { + agentUuid = initAgentUuid(); + processesThreadGroup = new ThreadGroup("SLC Processes of Agent #" + + agentUuid); + } + + /** Clean up (needs to be called by overriding method) */ + public void destroy() { + } + + /** + * Called during initialization in order to determines the agent UUID. To be + * overridden. By default creates a new one per instance. + */ + protected String initAgentUuid() { + return UUID.randomUUID().toString(); + } + + /* + * SLC AGENT + */ + public void process(ExecutionProcess process) { + ProcessThread processThread = createProcessThread(processesThreadGroup, + modulesManager, process); + processThread.start(); + runningProcesses.put(process.getUuid(), processThread); + + // clean up old processes + Iterator it = runningProcesses.values().iterator(); + while (it.hasNext()) { + ProcessThread pThread = it.next(); + if (!pThread.isAlive()) + it.remove(); + } + } + + public String process(List uris) { + DefaultProcess process = new DefaultProcess(); + for (URI uri : uris) { + String[] path = uri.getPath().split("/"); + if (path.length < 3) + throw new SlcException("Badly formatted URI: " + uri); + NameVersion nameVersion = new BasicNameVersion(path[1]); + StringBuilder flow = new StringBuilder(); + for (int i = 2; i < path.length; i++) + flow.append('/').append(path[i]); + + Map values = getQueryMap(uri.getQuery()); + // Get execution module descriptor + ExecutionModuleDescriptor emd = getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + process.getRealizedFlows().add( + emd.asRealizedFlow(flow.toString(), values)); + } + process(process); + return process.getUuid(); + } + + public void kill(String processUuid) { + if (runningProcesses.containsKey(processUuid)) { + runningProcesses.get(processUuid).interrupt(); + } else { + // assume is finished + } + } + + public void waitFor(String processUuid, Long millis) { + if (runningProcesses.containsKey(processUuid)) { + try { + if (millis != null) + runningProcesses.get(processUuid).join(millis); + else + runningProcesses.get(processUuid).join(); + } catch (InterruptedException e) { + // silent + } + } else { + // assume is finished + } + } + + /** Creates the thread which will coordinate the execution for this agent. */ + protected ProcessThread createProcessThread( + ThreadGroup processesThreadGroup, + ExecutionModulesManager modulesManager, ExecutionProcess process) { + ProcessThread processThread = new ProcessThread(processesThreadGroup, + modulesManager, process); + return processThread; + } + + public ExecutionModuleDescriptor getExecutionModuleDescriptor( + String moduleName, String moduleVersion) { + // Get execution module descriptor + ExecutionModuleDescriptor emd; + try { + modulesManager + .start(new BasicNameVersion(moduleName, moduleVersion)); + emd = modulesManager.getExecutionModuleDescriptor(moduleName, + moduleVersion); + } catch (SlcException e) { + if (defaultModulePrefix != null) { + moduleName = defaultModulePrefix + "." + moduleName; + modulesManager.start(new BasicNameVersion(moduleName, + moduleVersion)); + emd = modulesManager.getExecutionModuleDescriptor(moduleName, + moduleVersion); + } else + throw e; + } + return emd; + } + + public List listExecutionModuleDescriptors() { + return modulesManager.listExecutionModules(); + } + + public boolean ping() { + return true; + } + + /* + * UTILITIES + */ + /** + * @param query + * can be null + */ + static Map getQueryMap(String query) { + Map map = new LinkedHashMap(); + if (query == null) + return map; + String[] params = query.split("&"); + for (String param : params) { + String[] arr = param.split("="); + String name = arr[0]; + Object value = arr.length > 1 ? param.split("=")[1] : Boolean.TRUE; + try { + map.put(URLDecoder.decode(name, UTF8), + URLDecoder.decode(value.toString(), UTF8)); + } catch (UnsupportedEncodingException e) { + throw new SlcException("Cannot decode '" + param + "'", e); + } + } + return map; + } + + /* + * BEAN + */ + public void setModulesManager(ExecutionModulesManager modulesManager) { + this.modulesManager = modulesManager; + } + + public void setDefaultModulePrefix(String defaultModulePrefix) { + this.defaultModulePrefix = defaultModulePrefix; + } + + public String getAgentUuid() { + return agentUuid; + } + + @Override + public String toString() { + return "Agent #" + getAgentUuid(); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgentCli.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgentCli.java new file mode 100644 index 000000000..d53b725a5 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultAgentCli.java @@ -0,0 +1,242 @@ +package org.argeo.slc.core.execution; + +import java.net.URI; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.security.OsAuthenticationToken; +import org.argeo.slc.BasicNameVersion; +import org.argeo.slc.NameVersion; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.argeo.slc.execution.SlcAgent; +import org.argeo.slc.execution.SlcAgentCli; +import org.springframework.security.core.Authentication; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Authenticates thread and executes synchronously a command line execution. + * Reference implementation of args to URIs algorithm. + */ +public class DefaultAgentCli implements SlcAgentCli { + private final static Log log = LogFactory.getLog(DefaultAgentCli.class); + + private final static String UTF8 = "UTF-8"; + private SlcAgent agent; + private AuthenticationManager authenticationManager; + + private Long timeout = 24 * 60 * 60 * 1000l; + + public String process(String[] args) { + if (SecurityContextHolder.getContext().getAuthentication() == null) { + OsAuthenticationToken oat = new OsAuthenticationToken(); + Authentication authentication = authenticationManager + .authenticate(oat); + SecurityContextHolder.getContext() + .setAuthentication(authentication); + } + + if (args.length > 0 && args[0].equals("help")) { + StringBuilder buf = new StringBuilder(); + help(args, buf); + log.info("\n" + buf); + return buf.toString(); + } else { + List uris = asURIs(args); + String processUuid = agent.process(uris); + agent.waitFor(processUuid, timeout); + return processUuid; + } + } + + protected void help(String[] rawArgs, StringBuilder buf) { + String[] args = Arrays.copyOfRange(rawArgs, 1, rawArgs.length); + if (args.length == 0) {// modules + for (ExecutionModuleDescriptor emd : agent + .listExecutionModuleDescriptors()) { + appendModule(emd, buf); + } + } else if (args.length == 1 && !args[0].contains("/")) {// single module + NameVersion nameVersion = new BasicNameVersion(args[0]); + ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + appendModule(emd, buf); + + // flows + for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { + buf.append(" ").append(efd.getName()); + if (efd.getDescription() != null + && !efd.getDescription().trim().equals("")) + buf.append(" : ").append(" ").append(efd.getDescription()); + buf.append('\n'); + } + return; + } else { + List uris = asURIs(args); + for (URI uri : uris) { + appendUriHelp(uri, buf); + } + } + } + + protected void appendUriHelp(URI uri, StringBuilder buf) { + String[] path = uri.getPath().split("/"); + NameVersion nameVersion = new BasicNameVersion(path[1]); + ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( + nameVersion.getName(), nameVersion.getVersion()); + + StringBuilder flow = new StringBuilder(); + for (int i = 2; i < path.length; i++) + flow.append('/').append(path[i]); + String flowPath = flow.toString(); + ExecutionFlowDescriptor efd = findExecutionFlowDescriptor(emd, flowPath); + if (efd == null) + throw new SlcException("Flow " + uri + " not found"); + + appendModule(emd, buf); + + buf.append(" ").append(efd.getName()); + if (efd.getDescription() != null + && !efd.getDescription().trim().equals("")) + buf.append(" : ").append(" ").append(efd.getDescription()); + buf.append('\n'); + Map values = DefaultAgent.getQueryMap(uri.getQuery()); + ExecutionSpec spec = efd.getExecutionSpec(); + for (String attrKey : spec.getAttributes().keySet()) { + ExecutionSpecAttribute esa = spec.getAttributes().get(attrKey); + buf.append(" --").append(attrKey); + if (values.containsKey(attrKey)) + buf.append(" ").append(values.get(attrKey)); + if (esa.getValue() != null) + buf.append(" (").append(esa.getValue()).append(')'); + buf.append('\n'); + } + } + + private void appendModule(ExecutionModuleDescriptor emd, StringBuilder buf) { + buf.append("# ").append(emd.getName()); + if (emd.getDescription() != null + && !emd.getDescription().trim().equals("")) + buf.append(" : ").append(emd.getDescription()); + if (emd.getVersion() != null) + buf.append(" (v").append(emd.getVersion()).append(")"); + buf.append('\n'); + } + + public static List asURIs(String[] args) { + try { + List uris = new ArrayList(); + List leftOvers = new ArrayList(); + + Boolean hasArgs = false; + String currKey = null; + StringBuilder currUri = null; + Iterator argIt = Arrays.asList(args).iterator(); + while (argIt.hasNext()) { + String arg = argIt.next(); + if (!arg.startsWith("-")) { + if (currKey != null) {// value + currUri.append(URLEncoder.encode(arg, UTF8)); + currKey = null; + } else { // module + if (currUri != null) { + uris.add(new URI(currUri.toString())); + } + currUri = new StringBuilder("flow:"); + + String currModule = arg; + currUri.append('/').append(currModule); + if (!arg.contains("/")) { + // flow path not in arg go to next arg + if (!argIt.hasNext()) + throw new SlcException("No flow found"); + String currFlow = argIt.next(); + if (!currFlow.startsWith("/")) + currFlow = "/" + currFlow; + currUri.append(currFlow); + } + } + } else { + if (currUri == null) {// first args + leftOvers.add(arg); + } else { + String key; + if (arg.startsWith("--")) + key = arg.substring(2); + else if (arg.startsWith("-")) + key = arg.substring(1); + else { + throw new SlcException("Cannot intepret key: " + + arg); + } + + if (!hasArgs) { + currUri.append('?'); + hasArgs = true; + } else { + currUri.append('&'); + } + + // deal with boolean keys + if (currKey != null) {// value + currUri.append(URLEncoder.encode("true", UTF8)); + currKey = null; + } + + currKey = key; + currUri.append(URLEncoder.encode(key, UTF8)) + .append('='); + } + } + } + if (currUri != null) + uris.add(new URI(currUri.toString())); + return uris; + } catch (Exception e) { + throw new SlcException("Cannot convert " + Arrays.toString(args) + + " to flow URI", e); + } + } + + private ExecutionFlowDescriptor findExecutionFlowDescriptor( + ExecutionModuleDescriptor emd, String flowPath) { + ExecutionFlowDescriptor flowDescriptor = null; + for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { + String name = efd.getName(); + // normalize name as flow path + if (!name.startsWith("/")) + name = "/" + name; + if (name.endsWith("/")) + name = name.substring(0, name.length() - 1); + if (name.equals(flowPath)) { + flowDescriptor = efd; + break; + } + } + return flowDescriptor; + } + + public void setAgent(SlcAgent agent) { + this.agent = agent; + } + + public void setAuthenticationManager( + AuthenticationManager authenticationManager) { + this.authenticationManager = authenticationManager; + } + + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java new file mode 100644 index 000000000..535c42dad --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlow.java @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.validation.MapBindingResult; + +/** Default implementation of an execution flow. */ +public class DefaultExecutionFlow implements ExecutionFlow, InitializingBean, + BeanNameAware { + private final static Log log = LogFactory + .getLog(DefaultExecutionFlow.class); + + private final ExecutionSpec executionSpec; + private String name = null; + private Map parameters = new HashMap(); + private List executables = new ArrayList(); + + private String path; + + private Boolean failOnError = true; + + public DefaultExecutionFlow() { + this.executionSpec = new DefaultExecutionSpec(); + } + + public DefaultExecutionFlow(ExecutionSpec executionSpec) { + this.executionSpec = executionSpec; + } + + public DefaultExecutionFlow(ExecutionSpec executionSpec, + Map parameters) { + // be sure to have an execution spec + this.executionSpec = (executionSpec == null) ? new DefaultExecutionSpec() + : executionSpec; + + // only parameters contained in the executionSpec can be set + for (String parameter : parameters.keySet()) { + if (!executionSpec.getAttributes().containsKey(parameter)) { + throw new SlcException("Parameter " + parameter + + " is not defined in the ExecutionSpec"); + } + } + + // set the parameters + this.parameters.putAll(parameters); + + // check that all the required parameters are defined + MapBindingResult errors = new MapBindingResult(parameters, "execution#" + + getName()); + for (String key : executionSpec.getAttributes().keySet()) { + ExecutionSpecAttribute attr = executionSpec.getAttributes() + .get(key); + + if (attr.getIsImmutable() && !isSetAsParameter(key)) { + errors.rejectValue(key, "Immutable but not set"); + break; + } + + if (attr.getIsConstant() && !isSetAsParameter(key)) { + errors.rejectValue(key, "Constant but not set as parameter"); + break; + } + + if (attr.getIsHidden() && !isSetAsParameter(key)) { + errors.rejectValue(key, "Hidden but not set as parameter"); + break; + } + } + + if (errors.hasErrors()) + throw new SlcException("Could not prepare execution flow: " + + errors.toString()); + + } + + public void run() { + try { + for (Runnable executable : executables) { + if (Thread.interrupted()) { + log.error("Flow '" + getName() + "' killed before '" + + executable + "'"); + Thread.currentThread().interrupt(); + return; + // throw new ThreadDeath(); + } + this.doExecuteRunnable(executable); + } + } catch (RuntimeException e) { + if (Thread.interrupted()) { + log.error("Flow '" + getName() + + "' killed while receiving an unrelated exception", e); + Thread.currentThread().interrupt(); + return; + // throw new ThreadDeath(); + } + if (failOnError) + throw e; + else { + log.error("Execution flow failed," + + " but process did not fail" + + " because failOnError property" + + " is set to false: " + e); + if (log.isTraceEnabled()) + e.printStackTrace(); + } + } + } + + /** + * List sub-runnables that would be executed if run() method would be + * called. + */ + public Iterator runnables() { + return executables.iterator(); + } + + /** + * If there is one and only one runnable wrapped return it, throw an + * exeception otherwise. + */ + public Runnable getRunnable() { + if (executables.size() == 1) + return executables.get(0); + else + throw new SlcException("There are " + executables.size() + + " runnables in flow " + getName()); + } + + public void doExecuteRunnable(Runnable runnable) { + runnable.run(); + } + + public void afterPropertiesSet() throws Exception { + if (path == null) { + if (name.charAt(0) == '/') { + path = name.substring(0, name.lastIndexOf('/')); + } + } + + if (path != null) { + for (Runnable executable : executables) { + if (executable instanceof DefaultExecutionFlow) { + // so we don't need to have DefaultExecutionFlow + // implementing StructureAware + // FIXME: probably has side effects + DefaultExecutionFlow flow = (DefaultExecutionFlow) executable; + String newPath = path + '/' + flow.getName(); + flow.setPath(newPath); + log.warn(newPath + " was forcibly set on " + flow); + } + } + } + } + + public void setBeanName(String name) { + this.name = name; + } + + public void setExecutables(List executables) { + this.executables = executables; + } + + public void setParameters(Map attributes) { + this.parameters = attributes; + } + + public String getName() { + return name; + } + + public ExecutionSpec getExecutionSpec() { + return executionSpec; + } + + public Object getParameter(String parameterName) { + // Verify that there is a spec attribute + ExecutionSpecAttribute specAttr = null; + if (executionSpec.getAttributes().containsKey(parameterName)) { + specAttr = executionSpec.getAttributes().get(parameterName); + } else { + throw new SlcException("Key " + parameterName + + " is not defined in the specifications of " + toString()); + } + + if (parameters.containsKey(parameterName)) { + Object paramValue = parameters.get(parameterName); + return paramValue; + } else { + if (specAttr.getValue() != null) { + return specAttr.getValue(); + } + } + throw new SlcException("Key " + parameterName + + " is not set as parameter in " + toString()); + } + + public Boolean isSetAsParameter(String key) { + return parameters.containsKey(key) + || (executionSpec.getAttributes().containsKey(key) && executionSpec + .getAttributes().get(key).getValue() != null); + } + + @Override + public String toString() { + return new StringBuffer("Execution flow ").append(name).toString(); + } + + @Override + public boolean equals(Object obj) { + return ((ExecutionFlow) obj).getName().equals(name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Boolean getFailOnError() { + return failOnError; + } + + public void setFailOnError(Boolean failOnError) { + this.failOnError = failOnError; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java new file mode 100644 index 000000000..433da9f14 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; +import org.argeo.slc.execution.ExecutionModuleDescriptor; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.springframework.aop.scope.ScopedObject; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.util.StringUtils; + +/** + * Performs conversion in both direction between data exchanged with the agent + * and the data in the application context. + */ +public class DefaultExecutionFlowDescriptorConverter implements + ExecutionFlowDescriptorConverter, ApplicationContextAware { + public final static String REF_VALUE_TYPE_BEAN_NAME = "beanName"; + + /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */ + private final static String REF_VALUE_INTERNAL = "[internal]"; + + private final static Log log = LogFactory + .getLog(DefaultExecutionFlowDescriptorConverter.class); + + private ApplicationContext applicationContext; + + @SuppressWarnings("unused") + public Map convertValues( + ExecutionFlowDescriptor executionFlowDescriptor) { + Map values = executionFlowDescriptor.getValues(); + Map convertedValues = new HashMap(); + ExecutionSpec executionSpec = executionFlowDescriptor + .getExecutionSpec(); + + if (executionSpec == null && log.isTraceEnabled()) + log.warn("Execution spec is null for " + executionFlowDescriptor); + + if (values != null && executionSpec != null) { + values: for (String key : values.keySet()) { + ExecutionSpecAttribute attribute = executionSpec + .getAttributes().get(key); + + if (attribute == null) + throw new FlowConfigurationException( + "No spec attribute defined for '" + key + "'"); + + if (attribute.getIsConstant()) + continue values; + + Object value = values.get(key); + if (value instanceof PrimitiveValue) { + PrimitiveValue primitiveValue = (PrimitiveValue) value; + // TODO: check class <=> type + convertedValues.put(key, primitiveValue.getValue()); + } else if (value instanceof RefValue) { + RefValue refValue = (RefValue) value; + String type = refValue.getType(); + if (REF_VALUE_TYPE_BEAN_NAME.equals(type)) { + // FIXME: UI should send all information about spec + // - targetClass + // - name + // String executionSpecName = executionSpec.getName(); + // ExecutionSpec localSpec = (ExecutionSpec) + // applicationContext + // .getBean(executionSpecName); + // RefSpecAttribute localAttr = (RefSpecAttribute) + // localSpec + // .getAttributes().get(key); + // Class targetClass = localAttr.getTargetClass(); + // + // String primitiveType = PrimitiveUtils + // .classAsType(targetClass); + String primitiveType = null; + if (primitiveType != null) { + // not active + String ref = refValue.getRef(); + Object obj = PrimitiveUtils.convert(primitiveType, + ref); + convertedValues.put(key, obj); + } else { + String ref = refValue.getRef(); + if (ref != null && !ref.equals(REF_VALUE_INTERNAL)) { + Object obj = null; + if (applicationContext.containsBean(ref)) { + obj = applicationContext.getBean(ref); + } else { + // FIXME: hack in order to pass primitive + obj = ref; + } + convertedValues.put(key, obj); + } else { + log.warn("Cannot interpret " + refValue); + } + } + } else if (PrimitiveUtils.typeAsClass(type) != null) { + String ref = refValue.getRef(); + Object obj = PrimitiveUtils.convert(type, ref); + convertedValues.put(key, obj); + } else { + throw new FlowConfigurationException( + "Ref value type not supported: " + + refValue.getType()); + } + } else { + // default is to take the value as is + convertedValues.put(key, value); + } + } + } + return convertedValues; + } + + public void addFlowsToDescriptor(ExecutionModuleDescriptor md, + Map executionFlows) { + SortedSet set = new TreeSet( + new ExecutionFlowDescriptorComparator()); + for (String name : executionFlows.keySet()) { + ExecutionFlow executionFlow = executionFlows.get(name); + + ExecutionFlowDescriptor efd = getExecutionFlowDescriptor(executionFlow); + ExecutionSpec executionSpec = efd.getExecutionSpec(); + + // Add execution spec if necessary + if (!md.getExecutionSpecs().contains(executionSpec)) + md.getExecutionSpecs().add(executionSpec); + + // Add execution flow + set.add(efd); + // md.getExecutionFlows().add(efd); + } + md.getExecutionFlows().addAll(set); + } + + @SuppressWarnings("deprecation") + public ExecutionFlowDescriptor getExecutionFlowDescriptor( + ExecutionFlow executionFlow) { + if (executionFlow.getName() == null) + throw new FlowConfigurationException("Flow name is null: " + + executionFlow); + String name = executionFlow.getName(); + + ExecutionSpec executionSpec = executionFlow.getExecutionSpec(); + if (executionSpec == null) + throw new FlowConfigurationException("Execution spec is null: " + + executionFlow); + if (executionSpec.getName() == null) + throw new FlowConfigurationException( + "Execution spec name is null: " + executionSpec); + + Map values = new TreeMap(); + for (String key : executionSpec.getAttributes().keySet()) { + ExecutionSpecAttribute attribute = executionSpec.getAttributes() + .get(key); + + if (attribute instanceof PrimitiveSpecAttribute) { + if (executionFlow.isSetAsParameter(key)) { + Object value = executionFlow.getParameter(key); + PrimitiveValue primitiveValue = new PrimitiveValue(); + primitiveValue.setType(((PrimitiveSpecAttribute) attribute) + .getType()); + primitiveValue.setValue(value); + values.put(key, primitiveValue); + } else { + // no need to add a primitive value if it is not set, + // all necessary information is in the spec + } + } else if (attribute instanceof RefSpecAttribute) { + if (attribute.getIsConstant()) { + values.put(key, new RefValue(REF_VALUE_INTERNAL)); + } else + values.put( + key, + buildRefValue((RefSpecAttribute) attribute, + executionFlow, key)); + } else { + throw new FlowConfigurationException( + "Unkown spec attribute type " + attribute.getClass()); + } + + } + + ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name, null, + values, executionSpec); + if (executionFlow.getPath() != null) + efd.setPath(executionFlow.getPath()); + else + efd.setPath(""); + + // Takes description from spring + BeanFactory bf = getBeanFactory(); + if (bf != null) { + BeanDefinition bd = getBeanFactory().getBeanDefinition(name); + efd.setDescription(bd.getDescription()); + } + return efd; + } + + @SuppressWarnings(value = { "unchecked" }) + protected RefValue buildRefValue(RefSpecAttribute rsa, + ExecutionFlow executionFlow, String key) { + RefValue refValue = new RefValue(); + // FIXME: UI should be able to deal with other types + refValue.setType(REF_VALUE_TYPE_BEAN_NAME); + Class targetClass = rsa.getTargetClass(); + String primitiveType = PrimitiveUtils.classAsType(targetClass); + if (primitiveType != null) { + if (executionFlow.isSetAsParameter(key)) { + Object value = executionFlow.getParameter(key); + refValue.setRef(value.toString()); + } + refValue.setType(primitiveType); + return refValue; + } else { + + if (executionFlow.isSetAsParameter(key)) { + String ref = null; + Object value = executionFlow.getParameter(key); + if (applicationContext == null) { + log.warn("No application context declared, cannot scan ref value."); + ref = value.toString(); + } else { + + // look for a ref to the value + Map beans = getBeanFactory() + .getBeansOfType(targetClass, false, false); + // TODO: also check scoped beans + beans: for (String beanName : beans.keySet()) { + Object obj = beans.get(beanName); + if (value instanceof ScopedObject) { + // don't call methods of the target of the scope + if (obj instanceof ScopedObject) + if (value == obj) { + ref = beanName; + break beans; + } + } else { + if (obj.equals(value)) { + ref = beanName; + break beans; + } + } + } + } + if (ref == null) { + if (log.isTraceEnabled()) + log.trace("Cannot define reference for ref spec attribute " + + key + + " in " + + executionFlow + + " (" + + rsa + + ")." + + " If it is an inner bean consider put it frozen."); + ref = REF_VALUE_INTERNAL; + } else { + if (log.isTraceEnabled()) + log.trace(ref + + " is the reference for ref spec attribute " + + key + " in " + executionFlow + " (" + rsa + + ")"); + } + refValue.setRef(ref); + } + return refValue; + } + } + + /** @return can be null */ + private ConfigurableListableBeanFactory getBeanFactory() { + if (applicationContext == null) + return null; + return ((ConfigurableApplicationContext) applicationContext) + .getBeanFactory(); + } + + /** Must be use within the execution application context */ + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + + private static class ExecutionFlowDescriptorComparator implements + Comparator { + @SuppressWarnings("deprecation") + public int compare(ExecutionFlowDescriptor o1, + ExecutionFlowDescriptor o2) { + // TODO: write unit tests for this + + String name1 = o1.getName(); + String name2 = o2.getName(); + + String path1 = o1.getPath(); + String path2 = o2.getPath(); + + // Check whether name include path + int lastIndex1 = name1.lastIndexOf('/'); + // log.debug(name1+", "+lastIndex1); + if (!StringUtils.hasText(path1) && lastIndex1 >= 0) { + path1 = name1.substring(0, lastIndex1); + name1 = name1.substring(lastIndex1 + 1); + } + + int lastIndex2 = name2.lastIndexOf('/'); + if (!StringUtils.hasText(path2) && lastIndex2 >= 0) { + path2 = name2.substring(0, lastIndex2); + name2 = name2.substring(lastIndex2 + 1); + } + + // Perform the actual comparison + if (StringUtils.hasText(path1) && StringUtils.hasText(path2)) { + if (path1.equals(path2)) + return name1.compareTo(name2); + else if (path1.startsWith(path2)) + return -1; + else if (path2.startsWith(path1)) + return 1; + else + return path1.compareTo(path2); + } else if (!StringUtils.hasText(path1) + && StringUtils.hasText(path2)) { + return 1; + } else if (StringUtils.hasText(path1) + && !StringUtils.hasText(path2)) { + return -1; + } else if (!StringUtils.hasText(path1) + && !StringUtils.hasText(path2)) { + return name1.compareTo(name2); + } else { + return 0; + } + } + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java new file mode 100644 index 000000000..2bce12577 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionSpec.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.springframework.beans.factory.BeanNameAware; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; + +/** Spring based implementation of execution specifications. */ +public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware, + ApplicationContextAware, InitializingBean, Serializable { + private static final long serialVersionUID = 5159882223926926539L; + private final static Log log = LogFactory + .getLog(DefaultExecutionSpec.class); + private transient ApplicationContext applicationContext; + + private String description; + private Map attributes = new HashMap(); + + private String name = INTERNAL_NAME; + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + public void setBeanName(String name) { + this.name = name; + } + + /** + * The Spring bean name (only relevant for specs declared has high-level + * beans) + */ + public String getName() { + return name; + } + + public boolean equals(Object obj) { + return ((ExecutionSpec) obj).getName().equals(name); + } + + /** + * The Spring bean description (only relevant for specs declared has + * high-level beans) + */ + public String getDescription() { + return description; + } + + private ConfigurableListableBeanFactory getBeanFactory() { + return ((ConfigurableApplicationContext) applicationContext) + .getBeanFactory(); + } + + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + public void afterPropertiesSet() throws Exception { + if (description == null) { + try { + description = getBeanFactory().getBeanDefinition(name) + .getDescription(); + } catch (NoSuchBeanDefinitionException e) { + // silent + } + } + + for (String key : attributes.keySet()) { + ExecutionSpecAttribute attr = attributes.get(key); + if (attr instanceof RefSpecAttribute) { + RefSpecAttribute rsa = (RefSpecAttribute) attr; + if (rsa.getChoices() == null) { + List choices = buildRefValueChoices(rsa); + rsa.setChoices(choices); + } + if (log.isTraceEnabled()) + log.debug("Spec attr " + key + " has " + + rsa.getChoices().size() + " choices"); + } + } + } + + /** + * Generates a list of ref value choices based on the bean available in the + * application ocntext. + */ + protected List buildRefValueChoices(RefSpecAttribute rsa) { + List choices = new ArrayList(); + if (applicationContext == null) { + log.warn("No application context declared," + + " cannot scan ref value choices."); + return choices; + } + + beanNames: for (String beanName : getBeanFactory().getBeanNamesForType( + rsa.getTargetClass(), true, false)) { + + // Since Spring 3, systemProperties is implicitly defined but has no + // bean definition + if (beanName.equals("systemProperties")) + continue beanNames; + + BeanDefinition bd = getBeanFactory().getBeanDefinition(beanName); + RefValueChoice choice = new RefValueChoice(); + choice.setName(beanName); + choice.setDescription(bd.getDescription()); + if (log.isTraceEnabled()) + log.debug("Found choice " + beanName + " for " + rsa); + + choices.add(choice); + + } + return choices; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionStack.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionStack.java new file mode 100644 index 000000000..d1d06c698 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultExecutionStack.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; +import java.util.UUID; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpecAttribute; +import org.argeo.slc.execution.ExecutionStack; + +/** Canonical implementation of an execution stack. */ +public class DefaultExecutionStack implements ExecutionStack { + + private final static Log log = LogFactory + .getLog(DefaultExecutionStack.class); + + private final Stack stack = new Stack(); + + public synchronized void enterFlow(ExecutionFlow executionFlow) { + ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow); + stack.push(runtime); + + Map specAttrs = executionFlow + .getExecutionSpec().getAttributes(); + for (String key : specAttrs.keySet()) { + if (executionFlow.isSetAsParameter(key)) { + runtime.getLocalVariables().put(key, + executionFlow.getParameter(key)); + } + } + } + + public synchronized String getCurrentStackLevelUuid() { + return stack.peek().getUuid(); + } + + public synchronized Integer getStackSize() { + return stack.size(); + } + + /** + * Looks for a set variable in the stack, starting at the upper flows + * + * @return the variable or null if not found + */ + public synchronized Object findLocalVariable(String key) { + Object obj = null; + for (int i = 0; i < stack.size(); i++) { + if (stack.get(i).getLocalVariables().containsKey(key)) { + obj = stack.get(i).getLocalVariables().get(key); + break; + } + } + return obj; + } + + public synchronized void leaveFlow(ExecutionFlow executionFlow) { + ExecutionFlowRuntime leftEf = stack.pop(); + + if (!leftEf.getExecutionFlow().getName() + .equals(executionFlow.getName())) + throw new SlcException("Asked to leave " + executionFlow + + " but last is " + leftEf); + + leftEf.getScopedObjects().clear(); + leftEf.getLocalVariables().clear(); + } + + public synchronized void addScopedObject(String name, Object obj) { + ExecutionFlowRuntime runtime = stack.peek(); + // TODO: check that the object is not set yet ? + if (log.isDebugEnabled()) { + Object existing = findScopedObject(name); + if (existing != null) + log.warn("Scoped object " + name + " of type " + obj.getClass() + + " already registered in " + runtime); + } + runtime.getScopedObjects().put(name, obj); + } + + /** @return null if not found */ + public synchronized Object findScopedObject(String name) { + Object obj = null; + for (int i = stack.size() - 1; i >= 0; i--) { + if (stack.get(i).getScopedObjects().containsKey(name)) { + obj = stack.get(i).getScopedObjects().get(name); + break; + } + } + return obj; + } + + protected static class ExecutionFlowRuntime { + private final ExecutionFlow executionFlow; + private final Map scopedObjects = new HashMap(); + private final Map localVariables = new HashMap(); + private final String uuid = UUID.randomUUID().toString(); + + public ExecutionFlowRuntime(ExecutionFlow executionFlow) { + this.executionFlow = executionFlow; + } + + public ExecutionFlow getExecutionFlow() { + return executionFlow; + } + + public Map getScopedObjects() { + return scopedObjects; + } + + public String getUuid() { + return uuid; + } + + public Map getLocalVariables() { + return localVariables; + } + + @Override + public String toString() { + return "Stack Level #" + uuid; + } + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultProcess.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultProcess.java new file mode 100644 index 000000000..30211800f --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/DefaultProcess.java @@ -0,0 +1,55 @@ +package org.argeo.slc.core.execution; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.execution.RealizedFlow; + +/** Canonical implementation of an {@link ExecutionProcess} as a bean. */ +public class DefaultProcess implements ExecutionProcess { + private String uuid = UUID.randomUUID().toString(); + private String status = ExecutionProcess.NEW; + + private List steps = new ArrayList(); + private List realizedFlows = new ArrayList(); + + public String getUuid() { + return uuid; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public void addSteps(List steps) { + steps.addAll(steps); + } + + public List getRealizedFlows() { + return realizedFlows; + } + + public List getSteps() { + return steps; + } + + public void setSteps(List steps) { + this.steps = steps; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public void setRealizedFlows(List realizedFlows) { + this.realizedFlows = realizedFlows; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionAspect.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionAspect.java new file mode 100644 index 000000000..b50b78f51 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionAspect.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionStack; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +@Aspect +/** Aspect intercepting calls on execution flows and contexts. */ +public class ExecutionAspect { + private final static Log log = LogFactory.getLog(ExecutionAspect.class); + + private ExecutionStack executionStack; + private ExecutionContext executionContext; + + @Around("flowExecution()") + public void aroundFlow(ProceedingJoinPoint pjp) throws Throwable { + // IMPORTANT: Make sure that the execution context is called before the + // execution stack + executionContext.getUuid(); + + ExecutionFlow executionFlow = (ExecutionFlow) pjp.getTarget(); + executionStack.enterFlow(executionFlow); + executionContext.setVariable(ExecutionContext.VAR_FLOW_ID, + executionStack.getCurrentStackLevelUuid()); + executionContext.setVariable(ExecutionContext.VAR_FLOW_NAME, + executionFlow.getName()); + + logStackEvent("=> ", executionFlow); + try { + // Actually execute the flow + pjp.proceed(); + } finally { + logStackEvent("<= ", executionFlow); + executionStack.leaveFlow(executionFlow); + } + } + + @Around("getVariable()") + public Object aroundGetVariable(ProceedingJoinPoint pjp) throws Throwable { + Object obj = pjp.proceed(); + // if the variable was not found, look in the stack starting at the + // upper flows + if (obj == null) { + String key = pjp.getArgs()[0].toString(); + obj = executionStack.findLocalVariable(key); + } + return obj; + } + + @Pointcut("execution(void org.argeo.slc.execution.ExecutionFlow.run())") + public void flowExecution() { + } + + @Pointcut("execution(* org.argeo.slc.execution.ExecutionContext.getVariable(..))") + public void getVariable() { + } + + public void setExecutionStack(ExecutionStack executionStack) { + this.executionStack = executionStack; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + protected void logStackEvent(String symbol, ExecutionFlow executionFlow) { + Integer stackSize = executionStack.getStackSize(); + if (log.isTraceEnabled()) + log.debug(depthSpaces(stackSize) + symbol + executionFlow + " #" + + executionStack.getCurrentStackLevelUuid() + ", depth=" + + stackSize); + if (log.isDebugEnabled()) + log.debug(depthSpaces(stackSize) + symbol + executionFlow); + } + + protected void logRunnableExecution(ExecutionFlow executionFlow, + Runnable runnable) { + Integer stackSize = executionStack.getStackSize(); + if (log.isDebugEnabled()) + log.debug(depthSpaces(stackSize + 1) + + runnable.getClass().getSimpleName() + " in " + + executionFlow); + } + + private String depthSpaces(int depth) { + StringBuffer buf = new StringBuffer(depth * 2); + for (int i = 0; i < depth; i++) + buf.append(" "); + return buf.toString(); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java new file mode 100644 index 000000000..1365e6bc6 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.beans.PropertyDescriptor; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.ManagedMap; +import org.springframework.beans.factory.support.ManagedSet; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +/** + * Spring post processor which ensures that execution parameters are properly + * set. It is used at two levels: first during instantiation for instantiation + * parameters which allow to implement templates, then at runtime in order to + * interpret @{} placeholders when object of scope execution are instantiated. + */ +public class ExecutionParameterPostProcessor extends + InstantiationAwareBeanPostProcessorAdapter { + + private final static Log log = LogFactory + .getLog(ExecutionParameterPostProcessor.class); + + private ExecutionContext executionContext; + private InstantiationManager instantiationManager; + + private String placeholderPrefix = "@{"; + private String placeholderSuffix = "}"; + private String nullValue; + + @Override + public PropertyValues postProcessPropertyValues(PropertyValues pvs, + PropertyDescriptor[] pds, Object bean, String beanName) + throws BeansException { + + // TODO: resolve at execution only if scope is execution + // TODO: deal with placeholders in RuntimeBeanReference and + // RuntimeBeanNameReference + + MutablePropertyValues newPvs = new MutablePropertyValues(); + + boolean changesOccured = false; + + for (PropertyValue pv : pvs.getPropertyValues()) { + Object convertedValue = resolveValue(beanName, bean, pv.getValue()); + newPvs.addPropertyValue(new PropertyValue(pv, convertedValue)); + if (convertedValue != pv.getValue()) { + changesOccured = true; + } + } + + return changesOccured ? newPvs : pvs; + } + + @Override + public boolean postProcessAfterInstantiation(Object bean, String beanName) + throws BeansException { + if (bean instanceof ExecutionFlow) + instantiationManager.flowInitializationStarted( + (ExecutionFlow) bean, beanName); + return true; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof ExecutionFlow) + instantiationManager.flowInitializationFinished( + (ExecutionFlow) bean, beanName); + return bean; + } + + protected String resolvePlaceholder(Object bean, String placeholder) { + if (instantiationManager.isInFlowInitialization()) + return instantiationManager.getInitializingFlowParameter( + placeholder).toString(); + + else {// execution + // next call fail if no execution context available + Object obj = executionContext.getVariable(placeholder); + if (obj != null) { + return obj.toString(); + } + } + + return null; + } + + @SuppressWarnings(value = { "unchecked" }) + public Object resolveValue(String beanName, Object bean, Object value) { + if (value instanceof TypedStringValue) { + TypedStringValue tsv = (TypedStringValue) value; + String originalValue = tsv.getValue(); + + String convertedValue = resolveString(beanName, bean, originalValue); + if (convertedValue == null) + return null; + return convertedValue.equals(originalValue) ? value + : new TypedStringValue(convertedValue); + } else if (value instanceof String) { + String originalValue = value.toString(); + String convertedValue = resolveString(beanName, bean, originalValue); + if (convertedValue == null) + return null; + return convertedValue.equals(originalValue) ? value + : convertedValue; + } else if (value instanceof ManagedMap) { + Map mapVal = (Map) value; + + Map newContent = new ManagedMap(); + boolean entriesModified = false; + for (Iterator it = mapVal.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); + Object key = entry.getKey(); + int keyHash = (key != null ? key.hashCode() : 0); + Object newKey = resolveValue(beanName, bean, key); + int newKeyHash = (newKey != null ? newKey.hashCode() : 0); + Object val = entry.getValue(); + Object newVal = resolveValue(beanName, bean, val); + newContent.put(newKey, newVal); + entriesModified = entriesModified + || (newVal != val || newKey != key || newKeyHash != keyHash); + } + + return entriesModified ? newContent : value; + } else if (value instanceof ManagedList) { + List listVal = (List) value; + List newContent = new ManagedList(); + boolean valueModified = false; + + for (int i = 0; i < listVal.size(); i++) { + Object elem = listVal.get(i); + Object newVal = resolveValue(beanName, bean, elem); + newContent.add(newVal); + if (!ObjectUtils.nullSafeEquals(newVal, elem)) { + valueModified = true; + } + } + return valueModified ? newContent : value; + } else if (value instanceof ManagedSet) { + Set setVal = (Set) value; + Set newContent = new ManagedSet(); + boolean entriesModified = false; + for (Iterator it = setVal.iterator(); it.hasNext();) { + Object elem = it.next(); + int elemHash = (elem != null ? elem.hashCode() : 0); + Object newVal = resolveValue(beanName, bean, elem); + int newValHash = (newVal != null ? newVal.hashCode() : 0); + newContent.add(newVal); + entriesModified = entriesModified + || (newVal != elem || newValHash != elemHash); + } + return entriesModified ? newContent : value; + } else { + // log.debug(beanName + ": " + value.getClass() + " : " + value); + return value; + } + + } + + private String resolveString(String beanName, Object bean, String strVal) { + // in case is passed + if (strVal == null) + return null; + + String value = parseStringValue(bean, strVal, new HashSet()); + + if (value == null) + throw new SlcException("Could not resolve placeholder '" + strVal + + "' in bean '" + beanName + "'"); + + return (value.equals(nullValue) ? null : value); + } + + public void setPlaceholderPrefix(String placeholderPrefix) { + this.placeholderPrefix = placeholderPrefix; + } + + public void setPlaceholderSuffix(String placeholderSuffix) { + this.placeholderSuffix = placeholderSuffix; + } + + public void setNullValue(String nullValue) { + this.nullValue = nullValue; + } + + public void setInstantiationManager( + InstantiationManager instantiationManager) { + this.instantiationManager = instantiationManager; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + // + // Following methods hacked from the internals of + // PropertyPlaceholderConfigurer + // + + protected String parseStringValue(Object bean, String strVal, + Set visitedPlaceholders) + throws BeanDefinitionStoreException { + + // in case is passed + if (strVal == null) + return null; + + StringBuffer buf = new StringBuffer(strVal); + + int startIndex = strVal.indexOf(placeholderPrefix); + while (startIndex != -1) { + int endIndex = findPlaceholderEndIndex(buf, startIndex); + if (endIndex != -1) { + String placeholder = buf.substring(startIndex + + placeholderPrefix.length(), endIndex); + if (!visitedPlaceholders.add(placeholder)) { + throw new BeanDefinitionStoreException( + "Circular placeholder reference '" + placeholder + + "' in property definitions"); + } + // Recursive invocation, parsing placeholders contained in + // the placeholder key. + placeholder = parseStringValue(bean, placeholder, + visitedPlaceholders); + // Now obtain the value for the fully resolved key... + String propVal = resolvePlaceholder(bean, placeholder); + if (propVal != null) { + // Recursive invocation, parsing placeholders contained + // in the + // previously resolved placeholder value. + propVal = parseStringValue(bean, propVal, + visitedPlaceholders); + buf.replace(startIndex, + endIndex + placeholderSuffix.length(), propVal); + if (log.isTraceEnabled()) { + log.trace("Resolved placeholder '" + placeholder + "'"); + } + startIndex = buf.indexOf(placeholderPrefix, startIndex + + propVal.length()); + } else { + throw new BeanDefinitionStoreException( + "Could not resolve placeholder '" + placeholder + + "'"); + } + visitedPlaceholders.remove(placeholder); + } else { + startIndex = -1; + } + } + + return buf.toString(); + } + + private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { + int index = startIndex + placeholderPrefix.length(); + int withinNestedPlaceholder = 0; + while (index < buf.length()) { + if (StringUtils.substringMatch(buf, index, placeholderSuffix)) { + if (withinNestedPlaceholder > 0) { + withinNestedPlaceholder--; + index = index + placeholderSuffix.length(); + } else { + return index; + } + } else if (StringUtils + .substringMatch(buf, index, placeholderPrefix)) { + withinNestedPlaceholder++; + index = index + placeholderPrefix.length(); + } else { + index++; + } + } + return -1; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResources.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResources.java new file mode 100644 index 000000000..759a12542 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResources.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; + +import org.springframework.core.io.Resource; + +/** Provides write access to resources during execution */ +public interface ExecutionResources { + /** The base directory where this execution can write */ + public File getWritableBaseDir(); + + /** Allocates a local file in the writable area and return it as a resource. */ + public Resource getWritableResource(String relativePath); + + /** + * Allocates a local file in the writable area and return it as a fully + * qualified OS path. + */ + public String getWritableOsPath(String relativePath); + + /** + * Allocates a local file in the writable area and return it as a + * {@link File}. + */ + public File getWritableOsFile(String relativePath); + + /** + * Returns the resource as a file path. If the resource is not writable it + * is copied as a file in the writable area and the path to this local file + * is returned. + */ + public String getAsOsPath(Resource resource, Boolean overwrite); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java new file mode 100644 index 000000000..bf5ffef12 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** Workaround when execution placedholders needs to be passed.*/ +public class ExecutionResourcesFactoryBean implements FactoryBean { + private ExecutionResources executionResources; + private String relativePath; + + public Object getObject() throws Exception { + Assert.notNull(executionResources, "executionResources is null"); + Assert.notNull(relativePath, "relativePath is null"); + return executionResources.getWritableResource(relativePath); + } + + public Class getObjectType() { + return Resource.class; + } + + public boolean isSingleton() { + return true; + } + + public void setExecutionResources(ExecutionResources executionResources) { + this.executionResources = executionResources; + } + + public void setRelativePath(String relativePath) { + this.relativePath = relativePath; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionScope.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionScope.java new file mode 100644 index 000000000..a2a5a9b0c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionScope.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionStack; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; + +/** + * When Spring beans are instantiated with this scope, the same instance is + * reused across an execution. + */ +public class ExecutionScope implements Scope { + private final static Log log = LogFactory.getLog(ExecutionScope.class); + + private final ThreadLocal executionStack = new ThreadLocal(); + public final ThreadLocal executionStackBeanName = new ThreadLocal(); + + private final ThreadLocal executionContext = new ThreadLocal(); + private final ThreadLocal executionContextBeanName = new ThreadLocal(); + + public Object get(String name, ObjectFactory objectFactory) { + if (log.isTraceEnabled()) + log.debug("Get execution scoped bean " + name); + + // shortcuts + if (executionStackBeanName.get() != null + && name.equals(executionStackBeanName.get())) { + return executionStack.get(); + } + + if (executionContextBeanName.get() != null + && name.equals(executionContextBeanName.get())) { + return executionContext.get(); + } + + // execution context must be defined first + if (executionContext.get() == null) { + Object obj = objectFactory.getObject(); + if (obj instanceof ExecutionContext) { + return dealWithSpecialScopedObject(name, executionContext, + executionContextBeanName, (ExecutionContext) obj); + } else { + // TODO: use execution context wrapper + throw new SlcException("No execution context has been defined."); + } + } + + // for other scoped objects, an executions stack must be available + if (executionStack.get() == null) { + Object obj = objectFactory.getObject(); + if (obj instanceof ExecutionStack) { + return dealWithSpecialScopedObject(name, executionStack, + executionStackBeanName, (ExecutionStack) obj); + } else { + throw new SlcException("No execution stack has been defined."); + } + } + + // see if the execution stack already knows the object + Object obj = executionStack.get().findScopedObject(name); + if (obj == null) { + obj = objectFactory.getObject(); + if (obj instanceof ExecutionContext) + throw new SlcException( + "Only one execution context can be defined per thread"); + if (obj instanceof ExecutionStack) + throw new SlcException( + "Only one execution stack can be defined per thread"); + + checkForbiddenClasses(obj); + + executionStack.get().addScopedObject(name, obj); + } + return obj; + + } + + protected T dealWithSpecialScopedObject(String name, + ThreadLocal threadLocal, + ThreadLocal threadLocalBeanName, T newObj) { + + T obj = threadLocal.get(); + if (obj == null) { + obj = newObj; + threadLocal.set(obj); + threadLocalBeanName.set(name); + if (log.isTraceEnabled()) { + log.debug(obj.getClass() + " instantiated. (beanName=" + name + + ")"); + } + return obj; + } else { + throw new SlcException("Only one scoped " + obj.getClass() + + " can be defined per thread"); + } + + } + + protected void checkForbiddenClasses(Object obj) { + Class clss = obj.getClass(); + if (ExecutionFlow.class.isAssignableFrom(clss) + || ExecutionSpec.class.isAssignableFrom(clss)) { + throw new UnsupportedException("Execution scoped object", clss); + } + } + + public String getConversationId() { + // TODO: is it the most relevant? + return executionContext.get().getUuid(); + } + + public void registerDestructionCallback(String name, Runnable callback) { + if (Thread.currentThread() instanceof ExecutionThread) { + ExecutionThread executionThread = (ExecutionThread) Thread + .currentThread(); + executionThread.registerDestructionCallback(name, callback); + } + } + + public Object remove(String name) { + if (log.isDebugEnabled()) + log.debug("Remove object " + name); + throw new UnsupportedOperationException(); + } + + public Object resolveContextualObject(String key) { + return executionContext.get().getVariable(key); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionThread.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionThread.java new file mode 100644 index 000000000..48a5df38b --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionThread.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlowDescriptor; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.execution.RealizedFlow; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** Thread of a single execution */ +public class ExecutionThread extends Thread { + public final static String SYSPROP_EXECUTION_AUTO_UPGRADE = "slc.execution.autoupgrade"; + private final static Log log = LogFactory.getLog(ExecutionThread.class); + + private ExecutionModulesManager executionModulesManager; + private final RealizedFlow realizedFlow; + + private List destructionCallbacks = new ArrayList(); + + public ExecutionThread(ProcessThreadGroup processThreadGroup, + ExecutionModulesManager executionModulesManager, + RealizedFlow realizedFlow) { + super(processThreadGroup, "Flow " + + realizedFlow.getFlowDescriptor().getName()); + this.realizedFlow = realizedFlow; + this.executionModulesManager = executionModulesManager; + } + + public void run() { + // authenticate thread + Authentication authentication = getProcessThreadGroup() + .getAuthentication(); + if (authentication == null) + throw new SlcException("Can only execute authenticated threads"); + SecurityContextHolder.getContext().setAuthentication(authentication); + + // Retrieve execution flow descriptor + ExecutionFlowDescriptor executionFlowDescriptor = realizedFlow + .getFlowDescriptor(); + String flowName = executionFlowDescriptor.getName(); + + getProcessThreadGroup().dispatchAddStep( + new ExecutionStep(realizedFlow.getModuleName(), + ExecutionStep.PHASE_START, "Flow " + flowName)); + + try { + String autoUpgrade = System + .getProperty(SYSPROP_EXECUTION_AUTO_UPGRADE); + if (autoUpgrade != null && autoUpgrade.equals("true")) + executionModulesManager.upgrade(realizedFlow + .getModuleNameVersion()); + executionModulesManager.start(realizedFlow.getModuleNameVersion()); + // + // START FLOW + // + executionModulesManager.execute(realizedFlow); + // END FLOW + } catch (FlowConfigurationException e) { + String msg = "Configuration problem with flow " + flowName + ":\n" + + e.getMessage(); + log.error(msg); + getProcessThreadGroup().dispatchAddStep( + new ExecutionStep(realizedFlow.getModuleName(), + ExecutionStep.ERROR, msg + " " + e.getMessage())); + } catch (Exception e) { + // TODO: re-throw exception ? + String msg = "Execution of flow " + flowName + " failed."; + log.error(msg, e); + getProcessThreadGroup().dispatchAddStep( + new ExecutionStep(realizedFlow.getModuleName(), + ExecutionStep.ERROR, msg + " " + e.getMessage())); + } finally { + getProcessThreadGroup().dispatchAddStep( + new ExecutionStep(realizedFlow.getModuleName(), + ExecutionStep.PHASE_END, "Flow " + flowName)); + processDestructionCallbacks(); + } + } + + private synchronized void processDestructionCallbacks() { + for (int i = destructionCallbacks.size() - 1; i >= 0; i--) { + try { + destructionCallbacks.get(i).run(); + } catch (Exception e) { + log.warn("Could not process destruction callback " + i + + " in thread " + getName(), e); + } + } + } + + /** + * Gather object destruction callback to be called in reverse order at the + * end of the thread + */ + synchronized void registerDestructionCallback(String name, Runnable callback) { + destructionCallbacks.add(callback); + } + + protected ProcessThreadGroup getProcessThreadGroup() { + return (ProcessThreadGroup) getThreadGroup(); + } +} \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/FileExecutionResources.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/FileExecutionResources.java new file mode 100644 index 000000000..d225cd193 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/FileExecutionResources.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionContext; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** Implements write access to resources based on standard Java {@link File} */ +public class FileExecutionResources implements ExecutionResources { + private final static Log log = LogFactory + .getLog(FileExecutionResources.class); + protected final static String DEFAULT_EXECUTION_RESOURCES_DIRNAME = "executionResources"; + public final static String DEFAULT_EXECUTION_RESOURCES_TMP_PATH = System + .getProperty("java.io.tmpdir") + + File.separator + + System.getProperty("user.name") + + File.separator + + "slc" + + File.separator + DEFAULT_EXECUTION_RESOURCES_DIRNAME; + + private File baseDir; + private ExecutionContext executionContext; + private String prefixDatePattern = "yyMMdd_HHmmss_SSS"; + private SimpleDateFormat sdf = null; + + private Boolean withExecutionSubdirectory = true; + + public FileExecutionResources() { + // Default base directory + String osgiInstanceArea = System.getProperty("osgi.instance.area"); + String osgiInstanceAreaDefault = System + .getProperty("osgi.instance.area.default"); + + if (osgiInstanceArea != null) { + // within OSGi with -data specified + osgiInstanceArea = removeFilePrefix(osgiInstanceArea); + baseDir = new File(osgiInstanceArea + File.separator + + DEFAULT_EXECUTION_RESOURCES_DIRNAME); + } else if (osgiInstanceAreaDefault != null) { + // within OSGi without -data specified + osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault); + baseDir = new File(osgiInstanceAreaDefault + File.separator + + DEFAULT_EXECUTION_RESOURCES_DIRNAME); + } else {// outside OSGi + baseDir = new File(DEFAULT_EXECUTION_RESOURCES_TMP_PATH); + } + } + + protected SimpleDateFormat sdf() { + // Lazy init in case prefix has been externally set + if (sdf == null) + sdf = new SimpleDateFormat(prefixDatePattern); + return sdf; + } + + public Resource getWritableResource(String relativePath) { + File file = getFile(relativePath); + File parentDir = file.getParentFile(); + + if (!parentDir.exists()) { + // Creates if necessary + if (log.isTraceEnabled()) + log.trace("Creating parent directory " + parentDir); + parentDir.mkdirs(); + } + Resource resource = new FileSystemResource(file); + + if (log.isTraceEnabled()) + log.trace("Returns writable resource " + resource); + return resource; + } + + public String getWritableOsPath(String relativePath) { + try { + return getFile(relativePath).getCanonicalPath(); + } catch (IOException e) { + throw new SlcException("Cannot find canonical path", e); + } + } + + public File getWritableOsFile(String relativePath) { + return getFile(relativePath); + } + + public String getAsOsPath(Resource resource, Boolean overwrite) { + File file = fileFromResource(resource); + if (file != null) + try { + if (log.isTraceEnabled()) + log.debug("Directly interpret " + resource + " as OS file " + + file); + return file.getCanonicalPath(); + } catch (IOException e1) { + // silent + } + + if (log.isTraceEnabled()) + log.trace("Resource " + resource + + " is not available on the file system. Retrieving it..."); + + InputStream in = null; + OutputStream out = null; + try { + String path = resource.getURL().getPath(); + file = getFile(path); + if (file.exists() && !overwrite) + return file.getCanonicalPath(); + + file.getParentFile().mkdirs(); + in = resource.getInputStream(); + out = new FileOutputStream(file); + IOUtils.copy(in, out); + if (log.isDebugEnabled()) + log.debug("Retrieved " + resource + " to OS file " + file); + return file.getCanonicalPath(); + } catch (IOException e) { + throw new SlcException("Could not make resource " + resource + + " an OS file.", e); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + + /** + * Extract the underlying file from the resource. + * + * @return the file or null if no files support this resource. + */ + protected File fileFromResource(Resource resource) { + try { + return resource.getFile(); + } catch (IOException e) { + return null; + } + + } + + protected File getFile(String relativePath) { + File writableBaseDir = getWritableBaseDir(); + return new File(writableBaseDir.getPath() + File.separator + + relativePath.replace('/', File.separatorChar)); + } + + public File getWritableBaseDir() { + if (withExecutionSubdirectory) { + Date executionContextCreationDate = (Date) executionContext + .getVariable(ExecutionContext.VAR_EXECUTION_CONTEXT_CREATION_DATE); + Assert.notNull(executionContext, "execution context is null"); + String path = baseDir.getPath() + File.separator + + sdf().format(executionContextCreationDate); + // TODO write execution id somewhere? like in a txt file + return new File(path); + } else { + return baseDir; + } + } + + protected String removeFilePrefix(String url) { + if (url.startsWith("file:")) + return url.substring("file:".length()); + else if (url.startsWith("reference:file:")) + return url.substring("reference:file:".length()); + else + return url; + } + + public void setBaseDir(File baseDir) { + this.baseDir = baseDir; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + public void setPrefixDatePattern(String prefixDatePattern) { + this.prefixDatePattern = prefixDatePattern; + } + + public File getBaseDir() { + return baseDir; + } + + public ExecutionContext getExecutionContext() { + return executionContext; + } + + public String getPrefixDatePattern() { + return prefixDatePattern; + } + + /** Default is true. */ + public void setWithExecutionSubdirectory(Boolean withExecutionSubdirectory) { + this.withExecutionSubdirectory = withExecutionSubdirectory; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/FlowConfigurationException.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/FlowConfigurationException.java new file mode 100644 index 000000000..aeda5aca5 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/FlowConfigurationException.java @@ -0,0 +1,12 @@ +package org.argeo.slc.core.execution; + +import org.argeo.slc.SlcException; + +/** The stack trace of such exceptions does not need to be displayed */ +public class FlowConfigurationException extends SlcException { + private static final long serialVersionUID = 8456260596346797321L; + + public FlowConfigurationException(String message) { + super(message); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/InstantiationManager.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/InstantiationManager.java new file mode 100644 index 000000000..60e93ec15 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/InstantiationManager.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.Stack; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpecAttribute; + +/** Manage parameters that need to be set during the instantiation of a flow */ +public class InstantiationManager { + + private final static Log log = LogFactory + .getLog(InstantiationManager.class); + + private ThreadLocal> flowStack = new ThreadLocal>(); + + public Object createRef(String name) { + + if ((flowStack.get() == null) || flowStack.get().empty()) { + throw new SlcException("No flow is currently initializing." + + " Declare ParameterRef as inner beans or prototypes."); + } + + return getInitializingFlowParameter(name); + } + + public void flowInitializationStarted(ExecutionFlow flow, String flowName) { + // set the flow name if it is DefaultExecutionFlow + if (flow instanceof DefaultExecutionFlow) { + ((DefaultExecutionFlow) flow).setBeanName(flowName); + } + + if (log.isTraceEnabled()) + log.trace("Start initialization of " + flow.hashCode() + " (" + + flow + " - " + flow.getClass() + ")"); + + // log.info("# flowInitializationStarted " + flowName); + // create a stack for this thread if there is none + if (flowStack.get() == null) { + flowStack.set(new Stack()); + } + flowStack.get().push(flow); + } + + public void flowInitializationFinished(ExecutionFlow flow, String flowName) { + if (log.isTraceEnabled()) + log.trace("Finish initialization of " + flow.hashCode() + " (" + + flow + " - " + flow.getClass() + ")"); + + if (flowStack.get() != null) { + ExecutionFlow registeredFlow = flowStack.get().pop(); + if (registeredFlow != null) { + if (!flow.getName().equals(registeredFlow.getName())) + throw new SlcException("Current flow is " + flow); + // log.info("# flowInitializationFinished " + flowName); + // initializingFlow.set(null); + } + } else { + // happens for flows imported as services + log.warn("flowInitializationFinished - Flow Stack is null"); + } + } + + protected ExecutionFlow findInitializingFlowWithParameter(String key) { + if ((flowStack.get() == null) || flowStack.get().empty()) + throw new SlcException("No initializing flow available."); + + // first look in the outer flow (that may override parameters) + for (int i = 0; i < flowStack.get().size(); i++) { + if (flowStack.get().elementAt(i).isSetAsParameter(key)) { + return flowStack.get().elementAt(i); + } + } + throw new SlcException("Key " + key + " is not set as parameter in " + + flowStack.get().firstElement().toString() + " (stack size=" + + flowStack.get().size() + ")"); + + } + + public Object getInitializingFlowParameter(String key) { + return findInitializingFlowWithParameter(key).getParameter(key); + } + + public Class getInitializingFlowParameterClass(String key) { + ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key) + .getExecutionSpec().getAttributes().get(key); + if (attr instanceof RefSpecAttribute) + return ((RefSpecAttribute) attr).getTargetClass(); + else if (attr instanceof PrimitiveSpecAttribute) { + String type = ((PrimitiveSpecAttribute) attr).getType(); + Class clss = PrimitiveUtils.typeAsClass(type); + if (clss == null) + throw new SlcException("Cannot convert type " + type + + " to class."); + return clss; + } else + return null; + } + + public Boolean isInFlowInitialization() { + return (flowStack.get() != null) && !flowStack.get().empty(); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/MapExecutionContext.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/MapExecutionContext.java new file mode 100644 index 000000000..0bbc3f0df --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/MapExecutionContext.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionContext; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +public class MapExecutionContext implements ExecutionContext, + ApplicationContextAware { + private final Map variables = Collections + .synchronizedMap(new HashMap()); + + private final String uuid; + + private ApplicationContext applicationContext; + + public MapExecutionContext() { + uuid = UUID.randomUUID().toString(); + variables.put(VAR_EXECUTION_CONTEXT_ID, uuid); + variables.put(VAR_EXECUTION_CONTEXT_CREATION_DATE, new Date()); + } + + public void setVariable(String key, Object value) { + // check if we do not refer to a bean + int lastInd = key.lastIndexOf('.'); + if (applicationContext != null && lastInd > 0) { + String beanName = key.substring(0, lastInd); + String propertyName = key.substring(lastInd + 1); + if (applicationContext.containsBean(beanName)) { + BeanWrapper beanWrapper = new BeanWrapperImpl( + applicationContext.getBean(beanName)); + if (!beanWrapper.isWritableProperty(propertyName)) + throw new SlcException("No writable property " + + propertyName + " in bean " + beanName); + beanWrapper.setPropertyValue(propertyName, value); + } + } + + variables.put(key, value); + } + + public Object getVariable(String key) { + // check if we do not refer to a bean + int lastInd = key.lastIndexOf('.'); + if (applicationContext != null && lastInd > 0) { + String beanName = key.substring(0, lastInd); + String propertyName = key.substring(lastInd + 1); + if (applicationContext.containsBean(beanName)) { + BeanWrapper beanWrapper = new BeanWrapperImpl( + applicationContext.getBean(beanName)); + if (!beanWrapper.isReadableProperty(propertyName)) + throw new SlcException("No readable property " + + propertyName + " in bean " + beanName); + Object obj = beanWrapper.getPropertyValue(propertyName); + return obj; + } + } + + Object value = variables.get(key); + // try system property in last resort + if (value == null) + value = System.getProperty(key); + return value; + } + + public String getUuid() { + return uuid; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ExecutionContext) + return uuid.equals(((ExecutionContext) obj).getUuid()); + return false; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "#" + uuid; + } + + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + this.applicationContext = applicationContext; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/OsFileFactoryBean.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/OsFileFactoryBean.java new file mode 100644 index 000000000..52f91e1d5 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/OsFileFactoryBean.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; + +/** Retrieve an OS File from the given resource. */ +public class OsFileFactoryBean implements FactoryBean { + private ExecutionResources executionResources; + private Resource resource; + private Boolean overwrite = false; + + /** Return an existing file on the file system. */ + public Object getObject() throws Exception { + Assert.notNull(executionResources, "executionResources is null"); + Assert.notNull(resource, "resource is null"); + return executionResources.getAsOsPath(resource, overwrite); + } + + /** Return {@link Object} because CGLIB is unable to proxy {@link File}.*/ + public Class getObjectType() { + return CharSequence.class; + } + + public boolean isSingleton() { + return false; + } + + /** The execution resources object. */ + public void setExecutionResources(ExecutionResources executionResources) { + this.executionResources = executionResources; + } + + /** The resource to access. */ + public void setResource(Resource resource) { + this.resource = resource; + } + + /** + * Whether to overwrite the resource if it already exists. Default is + * false. + */ + public void setOverwrite(Boolean overwrite) { + this.overwrite = overwrite; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ParameterRef.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ParameterRef.java new file mode 100644 index 000000000..5a9d9adcf --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ParameterRef.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.FactoryBean; + +public class ParameterRef implements FactoryBean { + private final static Log log = LogFactory.getLog(ParameterRef.class); + + private InstantiationManager instantiationManager; + private String name; + + /** Cached object. */ + private Object object; + + public ParameterRef() { + } + + public ParameterRef(String name) { + this.name = name; + } + + public Object getObject() throws Exception { + if (log.isTraceEnabled()) + log.debug("Parameter ref called for " + name); + + if (object == null) + object = instantiationManager.getInitializingFlowParameter(name); + return object; + } + + public Class getObjectType() { + if (object == null) + return instantiationManager.getInitializingFlowParameterClass(name); + else + return object.getClass(); + } + + public boolean isSingleton() { + return true; + } + + public void setInstantiationManager( + InstantiationManager instantiationManager) { + this.instantiationManager = instantiationManager; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveAccessor.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveAccessor.java new file mode 100644 index 000000000..18d1b9894 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveAccessor.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +/** Abstraction of access to primitive values */ +public interface PrimitiveAccessor { + public final static String TYPE_STRING = "string"; + /** + * As of Argeo 1, passwords are NOT stored encrypted, just hidden in the UI, + * but stored in plain text in JCR. Use keyring instead. + */ + public final static String TYPE_PASSWORD = "password"; + public final static String TYPE_INTEGER = "integer"; + public final static String TYPE_LONG = "long"; + public final static String TYPE_FLOAT = "float"; + public final static String TYPE_DOUBLE = "double"; + public final static String TYPE_BOOLEAN = "boolean"; + + public String getType(); + + public Object getValue(); + + public void setValue(Object value); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java new file mode 100644 index 000000000..fe8412c81 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import org.argeo.slc.SlcException; + +/** + * A spec attribute wrapping a primitive value. + * + * @see PrimitiveAccessor + */ +public class PrimitiveSpecAttribute extends AbstractSpecAttribute implements + PrimitiveAccessor { + private static final long serialVersionUID = -566676381839825483L; + private String type = "string"; + private Object value = null; + + public PrimitiveSpecAttribute() { + } + + public PrimitiveSpecAttribute(String type, Object value) { + this.type = type; + this.value = value; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + // check whether type is recognized. + if (PrimitiveUtils.typeAsClass(type) == null) + throw new SlcException("Unrecognized type " + type); + this.type = type; + + } + + @Override + public String toString() { + return "Primitive spec attribute [" + type + "]" + + (value != null ? "=" + value : ""); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveUtils.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveUtils.java new file mode 100644 index 000000000..4268b8b03 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveUtils.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +/** Converts to and from primitive types. */ +public class PrimitiveUtils { + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_STRING} instead + */ + public final static String TYPE_STRING = PrimitiveAccessor.TYPE_STRING; + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_INTEGER} instead + */ + public final static String TYPE_INTEGER = PrimitiveAccessor.TYPE_INTEGER; + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_LONG} instead + */ + public final static String TYPE_LONG = PrimitiveAccessor.TYPE_LONG; + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_FLOAT} instead + */ + public final static String TYPE_FLOAT = PrimitiveAccessor.TYPE_FLOAT; + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_DOUBLE} instead + */ + public final static String TYPE_DOUBLE = PrimitiveAccessor.TYPE_DOUBLE; + /** + * @deprecated Use {@link PrimitiveAccessor#TYPE_BOOLEAN} instead + */ + public final static String TYPE_BOOLEAN = PrimitiveAccessor.TYPE_BOOLEAN; + + private PrimitiveUtils() { + + } + + /** @return the class or null if the provided type is not a primitive */ + public static Class typeAsClass(String type) { + if (PrimitiveAccessor.TYPE_STRING.equals(type)) + return String.class; + else if (PrimitiveAccessor.TYPE_PASSWORD.equals(type)) + return char[].class; + else if (PrimitiveAccessor.TYPE_INTEGER.equals(type)) + return Integer.class; + else if (PrimitiveAccessor.TYPE_LONG.equals(type)) + return Long.class; + else if (PrimitiveAccessor.TYPE_FLOAT.equals(type)) + return Float.class; + else if (PrimitiveAccessor.TYPE_DOUBLE.equals(type)) + return Double.class; + else if (PrimitiveAccessor.TYPE_BOOLEAN.equals(type)) + return Boolean.class; + else + return null; + } + + /** @return the type or null if the provided class is not a primitive */ + public static String classAsType(Class clss) { + if (String.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_STRING; + else if (char[].class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_PASSWORD; + else if (Integer.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_INTEGER; + else if (Long.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_LONG; + else if (Float.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_FLOAT; + else if (Double.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_DOUBLE; + else if (Boolean.class.isAssignableFrom(clss)) + return PrimitiveAccessor.TYPE_BOOLEAN; + else + return null; + } + + /** Parse string as an object. Passwords are returned as String.*/ + public static Object convert(String type, String str) { + if (PrimitiveAccessor.TYPE_STRING.equals(type)) { + return str; + } else if (PrimitiveAccessor.TYPE_PASSWORD.equals(type)) { + return str; + } else if (PrimitiveAccessor.TYPE_INTEGER.equals(type)) { + return (Integer.parseInt(str)); + } else if (PrimitiveAccessor.TYPE_LONG.equals(type)) { + return (Long.parseLong(str)); + } else if (PrimitiveAccessor.TYPE_FLOAT.equals(type)) { + return (Float.parseFloat(str)); + } else if (PrimitiveAccessor.TYPE_DOUBLE.equals(type)) { + return (Double.parseDouble(str)); + } else if (PrimitiveAccessor.TYPE_BOOLEAN.equals(type)) { + return (Boolean.parseBoolean(str)); + } else { + return str; + } + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveValue.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveValue.java new file mode 100644 index 000000000..3dedb9c22 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/PrimitiveValue.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +/** Primitive value to be used by an execution. */ +public class PrimitiveValue extends AbstractExecutionValue implements + PrimitiveAccessor { + private static final long serialVersionUID = 533414290998374166L; + + private String type; + + private Object value; + + public PrimitiveValue() { + } + + public PrimitiveValue(String type, Object value) { + super(); + this.type = type; + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThread.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThread.java new file mode 100644 index 000000000..9b8f9cc3f --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThread.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.execution.ExecutionModulesManager; +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.execution.ExecutionStep; +import org.argeo.slc.execution.RealizedFlow; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** + * Main thread coordinating an {@link ExecutionProcess}, launching parallel or + * sequential {@link ExecutionThread}s. + */ +public class ProcessThread extends Thread { + private final static Log log = LogFactory.getLog(ProcessThread.class); + + private final ExecutionModulesManager executionModulesManager; + private final ExecutionProcess process; + private final ProcessThreadGroup processThreadGroup; + + private Set executionThreads = Collections + .synchronizedSet(new HashSet()); + + // private Boolean hadAnError = false; + private Boolean killed = false; + + public ProcessThread(ThreadGroup processesThreadGroup, + ExecutionModulesManager executionModulesManager, + ExecutionProcess process) { + super(processesThreadGroup, "SLC Process #" + process.getUuid()); + this.executionModulesManager = executionModulesManager; + this.process = process; + processThreadGroup = new ProcessThreadGroup(process); + } + + public final void run() { + // authenticate thread + Authentication authentication = getProcessThreadGroup() + .getAuthentication(); + if (authentication == null) + throw new SlcException("Can only execute authenticated threads"); + SecurityContextHolder.getContext().setAuthentication(authentication); + + log.info("\n##\n## SLC Process #" + process.getUuid() + + " STARTED\n##\n"); + + // Start logging + new LoggingThread().start(); + + process.setStatus(ExecutionProcess.RUNNING); + try { + process(); + } catch (InterruptedException e) { + die(); + return; + } catch (Exception e) { + String msg = "Process " + getProcess().getUuid() + + " failed unexpectedly."; + log.error(msg, e); + getProcessThreadGroup().dispatchAddStep( + new ExecutionStep("Process", ExecutionStep.ERROR, msg + " " + + e.getMessage())); + } + + // waits for all execution threads to complete (in case they were + // started asynchronously) + for (ExecutionThread executionThread : executionThreads) { + if (executionThread.isAlive()) { + try { + executionThread.join(); + } catch (InterruptedException e) { + die(); + return; + } + } + } + + computeFinalStatus(); + } + + /** Make sure this is called BEFORE all the threads are interrupted. */ + private void computeFinalStatus() { + // String oldStatus = process.getStatus(); + // TODO: error management at flow level? + if (killed) + process.setStatus(ExecutionProcess.KILLED); + else if (processThreadGroup.hadAnError()) + process.setStatus(ExecutionProcess.ERROR); + else + process.setStatus(ExecutionProcess.COMPLETED); + // executionModulesManager.dispatchUpdateStatus(process, oldStatus, + // process.getStatus()); + log.info("\n## SLC Process #" + process.getUuid() + " " + + process.getStatus() + "\n"); + } + + /** Called when being killed */ + private synchronized void die() { + killed = true; + computeFinalStatus(); + for (ExecutionThread executionThread : executionThreads) { + try { + executionThread.interrupt(); + } catch (Exception e) { + log.error("Cannot interrupt " + executionThread); + } + } + processThreadGroup.interrupt(); + } + + /** + * Implementation specific execution. To be overridden in order to deal with + * custom process types. Default expects an {@link SlcExecution}. + */ + protected void process() throws InterruptedException { + List flowsToProcess = new ArrayList(); + flowsToProcess.addAll(process.getRealizedFlows()); + while (flowsToProcess.size() > 0) { + RealizedFlow realizedFlow = flowsToProcess.remove(0); + execute(realizedFlow, true); + } + } + + /** @return the (distinct) thread used for this execution */ + protected final void execute(RealizedFlow realizedFlow, Boolean synchronous) + throws InterruptedException { + if (killed) + return; + + ExecutionThread thread = new ExecutionThread(processThreadGroup, + executionModulesManager, realizedFlow); + executionThreads.add(thread); + thread.start(); + + if (synchronous) + thread.join(); + + return; + } + + // public void notifyError() { + // hadAnError = true; + // } + // + // public synchronized void flowCompleted() { + // // notifyAll(); + // } + + public ExecutionProcess getProcess() { + return process; + } + + public ProcessThreadGroup getProcessThreadGroup() { + return processThreadGroup; + } + + public ExecutionModulesManager getExecutionModulesManager() { + return executionModulesManager; + } + + private class LoggingThread extends Thread { + + public LoggingThread() { + super("SLC Process Logger #" + process.getUuid()); + } + + public void run() { + boolean run = true; + while (run) { + List newSteps = new ArrayList(); + processThreadGroup.getSteps().drainTo(newSteps); + if (newSteps.size() > 0) { + // System.out.println(steps.size() + " steps"); + process.addSteps(newSteps); + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + + if (!ProcessThread.this.isAlive() + && processThreadGroup.getSteps().size() == 0) + run = false; + } + } + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThreadGroup.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThreadGroup.java new file mode 100644 index 000000000..c18eaedbb --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/ProcessThreadGroup.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +import org.argeo.slc.execution.ExecutionProcess; +import org.argeo.slc.execution.ExecutionStep; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** The thread group attached to a given {@link SlcExecution}. */ +public class ProcessThreadGroup extends ThreadGroup { + // private final ExecutionModulesManager executionModulesManager; + // private final ProcessThread processThread; + private final Authentication authentication; + private final static Integer STEPS_BUFFER_CAPACITY = 5000; + + private BlockingQueue steps = new ArrayBlockingQueue( + STEPS_BUFFER_CAPACITY); + + private Boolean hadAnError = false; + + public ProcessThreadGroup(ExecutionProcess executionProcess) { + super("SLC Process #" + executionProcess.getUuid() + " thread group"); + // this.executionModulesManager = executionModulesManager; + // this.processThread = processThread; + this.authentication = SecurityContextHolder.getContext() + .getAuthentication(); + } + + public Authentication getAuthentication() { + return authentication; + } + + public void dispatchAddStep(ExecutionStep step) { + // ExecutionProcess slcProcess = processThread.getProcess(); + // List steps = new ArrayList(); + // steps.add(step); + // TODO clarify why we don't dispatch steps, must be a reason + // dispatchAddSteps(steps); + // slcProcess.addSteps(steps); + if (step.getType().equals(ExecutionStep.ERROR)) + hadAnError = true; + this.steps.add(step); + } + + // public void dispatchAddSteps(List steps) { + // ExecutionProcess slcProcess = processThread.getProcess(); + // executionModulesManager.dispatchAddSteps(slcProcess, steps); + // } + + public BlockingQueue getSteps() { + return steps; + } + + public Boolean hadAnError() { + return hadAnError; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefSpecAttribute.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefSpecAttribute.java new file mode 100644 index 000000000..8e4f617c8 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefSpecAttribute.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.util.List; + +/** A spec attribute whose value is a reference to a full fledged object. */ +public class RefSpecAttribute extends AbstractSpecAttribute implements + Cloneable { + private static final long serialVersionUID = -3427797452955753574L; + private transient Class targetClass = String.class; + /** Read only. */ + private String targetClassName; + private transient Object value = null; + + /** List to be chosen from */ + private List choices = null; + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + /** Default is {@link String} */ + public Class getTargetClass() { + return targetClass; + } + + public void setTargetClass(Class targetClass) { + this.targetClass = targetClass; + this.targetClassName = targetClass.getName(); + } + + public String getTargetClassName() { + return targetClassName; + } + + /** @return can be null */ + public List getChoices() { + return choices; + } + + public void setChoices(List choices) { + this.choices = choices; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + RefSpecAttribute rsa = new RefSpecAttribute(); + rsa.setTargetClass(targetClass); + rsa.setChoices(choices); + return rsa; + } + + @Override + public String toString() { + return "Ref spec attribute [" + targetClass + "]" + + (value != null ? "=" + value : ""); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValue.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValue.java new file mode 100644 index 000000000..0a24bc4b4 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValue.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +/** Reference value to be used by an execution */ +public class RefValue extends AbstractExecutionValue { + private static final long serialVersionUID = -8951231456757181687L; + private String ref; + private String type; + + public RefValue() { + } + + public RefValue(String ref) { + super(); + this.ref = ref; + } + + public String getRef() { + return ref; + } + + public void setRef(String ref) { + this.ref = ref; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public String toString() { + return "Ref Value [" + type + "=" + ref + "]"; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValueChoice.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValueChoice.java new file mode 100644 index 000000000..5e1f9c2ab --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/RefValueChoice.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.Serializable; + +/** A choice of ref value to be shown to the end user. */ +public class RefValueChoice implements Serializable { + private static final long serialVersionUID = -1133645722307507774L; + private String name; + private String description; + + public RefValueChoice() { + } + + public RefValueChoice(String name, String description) { + this.name = name; + this.description = description; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/SedFilteredResource.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/SedFilteredResource.java new file mode 100644 index 000000000..676918e98 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/SedFilteredResource.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.io.IOUtils; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; + +/** Experimental and suboptimal */ +public class SedFilteredResource implements FactoryBean, InitializingBean { + private Resource source; + + private List filters = new ArrayList(); + private Map patterns = new HashMap(); + + private String charset = "UTF-8"; + private Charset cs; + private CharsetDecoder decoder; + + // private CharsetEncoder encoder; + + public Object getObject() throws Exception { + if (filters.size() == 0) + return source; + + // int capacity = 100 * 1024;// 100 KB + ByteBuffer bb; + if (source instanceof ByteArrayResource) { + bb = ByteBuffer.wrap(((ByteArrayResource) source).getByteArray()); + } else { + FileInputStream fis = null; + try { + File file = source.getFile(); + fis = new FileInputStream(file); + FileChannel fc = fis.getChannel(); + + // Get the file's size and then map it into memory + int sz = (int) fc.size(); + bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz); + } catch (IOException e) { + // ReadableByteChannel channel = Channels.newChannel(source + // .getInputStream()); + // bb = ByteBuffer.allocateDirect(capacity); + // int read = 0; + // do { + // read = channel.read(bb); + // } while (read > 0); + // FIXME : use nio to parse the stream as it goes + bb = ByteBuffer.wrap(IOUtils.toByteArray(source + .getInputStream())); + } finally { + IOUtils.closeQuietly(fis); + } + } + CharBuffer cb = decoder.decode(bb); + for (Pattern pattern : patterns.keySet()) { + Matcher matcher = pattern.matcher(cb); + String output = matcher.replaceAll(patterns.get(pattern)); + cb = CharBuffer.wrap(output); + } + // ByteBuffer bbout = encoder.encode(cb); + // ByteArrayOutputStream out = new ByteArrayOutputStream(capacity); + // WritableByteChannel wchannel = Channels.newChannel(out); + // wchannel.write(bbout); + ByteArrayResource res = new ByteArrayResource(cb.toString().getBytes()); + return res; + } + + public Class getObjectType() { + return Resource.class; + } + + public boolean isSingleton() { + return true; + } + + public void afterPropertiesSet() throws Exception { + cs = Charset.forName(charset); + decoder = cs.newDecoder(); + // encoder = cs.newEncoder(); + + for (String sedStr : filters) { + sedStr = sedStr.trim(); + if (sedStr.length() < 4) + throw new SlcException(sedStr + " not properly formatted."); + if (sedStr.charAt(0) != 's') + throw new SlcException(sedStr + " not properly formatted."); + Character sep = sedStr.charAt(1); + List tokens = new ArrayList(4); + StringTokenizer st = new StringTokenizer(sedStr, sep.toString()); + while (st.hasMoreTokens()) + tokens.add(st.nextToken()); + if (tokens.size() != 3 && tokens.size() != 4) + throw new SlcException(sedStr + " not properly formatted."); + patterns.put(Pattern.compile(tokens.get(1)), tokens.get(2)); + } + } + + public void setSource(Resource source) { + this.source = source; + } + + public void setFilters(List filters) { + this.filters = filters; + } + + public void setCharset(String charset) { + this.charset = charset; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/defaults.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/defaults.xml new file mode 100644 index 000000000..d84ba10eb --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/defaults.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java new file mode 100644 index 000000000..6504a3de3 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.doc; + +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +public class ConsoleContextDescriber implements ContextDescriber { + public void describeContext(BeanDefinitionRegistry registry) { + String[] beanNames = registry.getBeanDefinitionNames(); + for (String beanName : beanNames) { + log("\n## BEAN: " + beanName); + describeBean(registry.getBeanDefinition(beanName)); + } + } + + public void describeBean(BeanDefinition beanDefinition) { + log("BeanDefinition class: "+beanDefinition.getClass()); + log("# ATTRIBUTES"); + for(String attr:beanDefinition.attributeNames()){ + log(attr+"="+beanDefinition.getAttribute(attr)); + } + log("# PROPERTIES"); + MutablePropertyValues pValues = beanDefinition.getPropertyValues(); + for (PropertyValue pv : pValues.getPropertyValues()) { + log(pv.getName() + "= (" + pv.getValue().getClass() + ") " + + pv.getValue()); + } + } + + protected void log(Object obj){ + System.out.println(obj); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ContextDescriber.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ContextDescriber.java new file mode 100644 index 000000000..713019b37 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/doc/ContextDescriber.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.doc; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +public interface ContextDescriber { + public void describeContext(BeanDefinitionRegistry registry); + public void describeBean(BeanDefinition bd); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java new file mode 100644 index 000000000..f1e80d390 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.Map; + +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +/** + * Composite RunnableFactory, redirecting the Runnable + * creation to on of the configured RunnableFactory depending + * on an entry of the data of the RunnableDataNode. + */ +public class CompositeRunnableFactory implements RunnableFactory { + + /** + * Key used to access factory ID in the data of the RunnableDataNode + */ + private String factoryKey; + + /** + * Maps a factory ID to an ExecutionFlowFactory + */ + private Map factories; + + public void createAndRegisterRunnable(RunnableDataNode node, + BeanDefinitionRegistry beanDefinitionRegistry) { + findFactory(node).createAndRegisterRunnable(node, beanDefinitionRegistry); + } + + /** + * Finds the RunnableFactory to use for a RunnableDataNode + * @param node + * @return the RunnableFactory to use for the RunnableDataNode + */ + private RunnableFactory findFactory(RunnableDataNode node) { + // get the factory ID from the data of the RunnableDescriptor + Map data = node.getData(); + if (!data.containsKey(factoryKey)) { + throw new SlcException("No data value for key '" + factoryKey + "'"); + } + String factoryId = data.get(factoryKey).toString(); + + // see if we have a factory for the factory ID + if ((factories != null) && factories.containsKey(factoryId)) { + return factories.get(factoryId); + } + // if not, look for a bean of name equals to the factory ID + else { + throw new SlcException("Not implemented"); + } + } + + public void setFactoryKey(String factoryKey) { + this.factoryKey = factoryKey; + } + + public void setFactories(Map factories) { + this.factories = factories; + } + + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java new file mode 100644 index 000000000..daed350b2 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Default implementation of RunnableDataNode + * + */ +public class DefaultRunnableDataNode implements RunnableDataNode { + + private List children = new ArrayList(); + + private RunnableDataNode parent; + + /** + * Data of the RunnableDataNode. Does not contain + * parent data. + */ + private Map properData = new HashMap(); + + private String path; + + private String beanName; + + public boolean isLeaf() { + return children.size() == 0; + } + + public List getChildren() { + return children; + } + + public void addChild(RunnableDataNode child) { + child.setParent(this); + children.add(child); + } + + public Map getData() { + Map data = new HashMap(); + if(parent != null) { + Map parentData = parent.getData(); + if(parentData != null) { + data.putAll(parentData); + } + } + // entries defined in parentData can be overridden + // in properData + if(properData != null) { + data.putAll(properData); + } + return data; + } + + public Map getProperData() { + return properData; + } + + public void setProperData(Map properData) { + this.properData = properData; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } + + public void setParent(RunnableDataNode parent) { + this.parent = parent; + } + + public RunnableDataNode getParent() { + return parent; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java new file mode 100644 index 000000000..d9400e42e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.HashMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.core.Ordered; + +/** + * Generates ExecutionFlows and Runnables as + * beans in the Spring Application Context. + * Called by the Application Context as a BeanFactoryPostProcessor. + * Two kinds of beans are generated: + * RunnableCallFlow, calling a list of Runnables from the + * Application Context after configuring the ExecutionContext, + * and outputs of a RunnableFactory. + */ +public class ExecutionFlowGenerator implements BeanFactoryPostProcessor, + Ordered { + + private final Log log = LogFactory.getLog(getClass()); + + /** + * Source providing a list of RunnableCallFlowDescriptor + * used to create RunnableCallFlow and a list of + * RunnableDataNode used to create any kind of flow via a factory + */ + protected ExecutionFlowGeneratorSource source; + + /** + * Factory used to create Runnables in the Application context from + * the RunnableDataNode provided from the source. + */ + protected RunnableFactory runnableFactory; + + /** + * Bean name of the ExecutionContext. + * Used to provide the created RunnableCallFlow beans + * with a RuntimeBeanReference to + * the ExecutionContext + */ + private String executionContextBeanName = "executionContext"; + + /** + * Bean name of the context values Map. + * A bean of class HashMap is created with this name, and a + * RuntimeBeanReference is provided to the created + * RunnableCallFlow beans. + */ + private String contextValuesBeanName = "executionFlowGenerator.contextValues"; + + /** + * Prefix added to the bean names defined in each + * RunnableCallFlowDescriptor + */ + private String flowBeanNamesPrefix = ""; + + private int order = Ordered.HIGHEST_PRECEDENCE; + + public void postProcessBeanFactory( + ConfigurableListableBeanFactory beanFactory) throws BeansException { + + // assert that the beanFactory is a BeanDefinitionRegistry + if (!(beanFactory instanceof BeanDefinitionRegistry)) { + throw new SlcException("Can only work on " + + BeanDefinitionRegistry.class); + } + + // add bean for the Context Values Map + createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory); + + // add beans for each RunnableDataNode + for(RunnableDataNode node : source.getRunnableDataNodes()) { + runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory); + } + + // add beans for each RunnableCallFlowDescriptor of the source to the application context + for (RunnableCallFlowDescriptor descriptor : source + .getRunnableCallFlowDescriptors()) { + createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory); + } + } + + /** + * Creates a RunnableCallFlow bean + * for a RunnableCallFlowDescriptor and registers + * it in the BeanDefinitionRegistry + * @param flowDescriptor + * @param registry + */ + private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) { + // create the flow bean + GenericBeanDefinition flowBean = new GenericBeanDefinition(); + flowBean.setBeanClass(RunnableCallFlow.class); + + String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName(); + + MutablePropertyValues mpv = new MutablePropertyValues(); + mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls()); + mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName)); + + mpv.addPropertyValue("name", beanName); + mpv.addPropertyValue("path", flowDescriptor.getPath()); + + mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName)); + + flowBean.setPropertyValues(mpv); + + // register it + if(log.isDebugEnabled()) { + log.debug("Registering bean definition for RunnableCallFlow " + beanName); + } + registry.registerBeanDefinition(beanName, flowBean); + } + + /** + * Creates the Context Values bean and register it in the + * BeanDefinitionRegistry + * @param registry + */ + private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) { + GenericBeanDefinition contextValuesBean = new GenericBeanDefinition(); + contextValuesBean.setBeanClass(HashMap.class); + + BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true); + registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition()); + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public void setSource(ExecutionFlowGeneratorSource source) { + this.source = source; + } + + public void setRunnableFactory(RunnableFactory runnableFactory) { + this.runnableFactory = runnableFactory; + } + + public void setExecutionContextBeanName(String executionContextBeanName) { + this.executionContextBeanName = executionContextBeanName; + } + + public void setContextValuesBeanName(String contextValuesBeanName) { + this.contextValuesBeanName = contextValuesBeanName; + } + + public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) { + this.flowBeanNamesPrefix = flowBeanNamesPrefix; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java new file mode 100644 index 000000000..8d699c660 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.List; + +/** + * Provides 2 types of information required by an ExecutionFlowGenerator: + * a list of RunnableCallFlowDescriptor used to create RunnableCallFlow + * and a list of RunnableDataNode used to create any kind of flow via a factory. + */ +public interface ExecutionFlowGeneratorSource { + + /** + * @return a list of RunnableCallFlowDescriptor used + * by a ExecutionFlowGenerator to create RunnableCallFlow + */ + public List getRunnableCallFlowDescriptors(); + + /** + * @return a list of RunnableDataNode used + * by a ExecutionFlowGenerator to create any kind of flow via a factory + */ + public List getRunnableDataNodes(); + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCall.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCall.java new file mode 100644 index 000000000..c3fd5f2d8 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCall.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.Map; + +/** + * Storage class for information required to call a flow + * of the Spring execution context: + * bean name of the flow, + * variables to add to the Execution Context before the call + * and variables (context values) to add to a Map + * potentially referenced by the called flow + */ +public class RunnableCall { + + /** + * Bean name of the flow to call + */ + private String beanName; + + /** + * Variables to add to the execution context before the call + */ + private Map executionVariables; + + /** + * Variables to add to the Map potentially referenced by + * the called flow + */ + private Map contextValues; + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } + + public Map getExecutionVariables() { + return executionVariables; + } + + public void setExecutionVariables(Map executionVariables) { + this.executionVariables = executionVariables; + } + + public Map getContextValues() { + return contextValues; + } + + public void setContextValues(Map contextValues) { + this.contextValues = contextValues; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java new file mode 100644 index 000000000..695606c21 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlow.java @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.DefaultExecutionSpec; +import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * Execution Flow calling a list of Runnable (identified by their + * bean name in the Spring Application Context) after configuring the Execution + * context and a Map potentially shared by the called Runnable + * + */ +public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware { + + private final static Log log = LogFactory.getLog(RunnableCallFlow.class); + + /** + * Key in the execution context for the index of the call (e.g. 0 for the + * first runnable called, ...) + */ + public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex"; + + /** + * Name of the flow. Also bean name + */ + private String name; + + /** + * Path of the flow + */ + private String path; + + /** + * Whether an exception in a Runnable shall stop the execution + * of the flow + */ + private Boolean failOnError = true; + + /** + * List of Runnable to call, with bean name, execution + * variables and context values + */ + private List runnableCalls; + + /** + * Map potentially referenced by called flows. Updated with the context + * values of a Runnable before calling it. + */ + private Map sharedContextValuesMap; + + /** + * ExecutionSpec of the flow. Does not contain any attribute. + */ + private ExecutionSpec executionSpec = new DefaultExecutionSpec(); + + /** + * Reference to the ExecutionContext + */ + private ExecutionContext executionContext; + + /** + * Reference to the Spring ApplicationContext. Set via + * setApplicationContext, the class implementing + * ApplicationContextAware + */ + private ApplicationContext applicationContext; + + /** + * Runs a Runnable after configuring the Execution Context and + * sharedContextValuesMap + * + * @param runnable + * the Runnable to call + * @param executionVariables + * the variables to add to the ExecutionContext + * @param contextValues + * the variables to add to sharedContextValuesMap + * @param callIndex + * index of the call (0 for the first called + * Runnable) set as variable of the + * ExecutionContext + */ + private void run(Runnable runnable, Map executionVariables, + Map contextValues, int callIndex) { + // add all variables to the Execution Context + for (Map.Entry entry : executionVariables.entrySet()) { + executionContext.setVariable(entry.getKey(), entry.getValue()); + } + + // add call Index Variable + executionContext.setVariable(VAR_CALL_INDEX, callIndex); + + // clear sharedContextValues and add all values of contextValues + if (sharedContextValuesMap != null) { + sharedContextValuesMap.clear(); + sharedContextValuesMap.putAll(contextValues); + } + + // then run the runnable + doExecuteRunnable(runnable); + } + + public void doExecuteRunnable(Runnable runnable) { + runnable.run(); + } + + /** + * Executes the flow. For each RunnableCall, the corresponding + * flow is retrieved from the Spring Application Context, the + * ExecutionContext and sharedContextValuesMap are + * configured and the Runnable is called. + */ + public void run() { + if (applicationContext == null) { + throw new SlcException("No ApplicationContext defined"); + } + + try { + for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { + RunnableCall runnableCall = runnableCalls.get(callIndex); + Object bean = applicationContext.getBean( + runnableCall.getBeanName(), Runnable.class); + if (log.isDebugEnabled()) + log.debug("Running flow '" + runnableCall.getBeanName() + + "'"); + run((Runnable) bean, runnableCall.getExecutionVariables(), + runnableCall.getContextValues(), callIndex); + } + } catch (RuntimeException e) { + if (failOnError) + throw e; + else { + log.error("Execution flow failed," + + " but process did not fail" + + " because failOnError property" + + " is set to false: " + e); + if (log.isTraceEnabled()) + e.printStackTrace(); + } + } + } + + public Iterator runnables() { + List runnables = new ArrayList(); + for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { + RunnableCall runnableCall = runnableCalls.get(callIndex); + Object bean = applicationContext.getBean( + runnableCall.getBeanName(), Runnable.class); + runnables.add((Runnable) bean); + } + return runnables.iterator(); + } + + public Runnable getRunnable() { + if (runnableCalls.size() == 1) + return runnables().next(); + else + throw new SlcException("There are " + runnableCalls.size() + + " runnables in flow " + getName()); + } + + @Override + public String toString() { + return new StringBuffer("RunnableCallFlow ").append(name).toString(); + } + + public ExecutionSpec getExecutionSpec() { + return executionSpec; + } + + public String getName() { + return name; + } + + public Object getParameter(String key) { + throw new SlcException("RunnableCallFlow have no parameters"); + } + + public String getPath() { + return path; + } + + public Boolean isSetAsParameter(String key) { + // The ExecutionSpec having no attribute, + // always return false + return false; + } + + public void setName(String name) { + this.name = name; + } + + public void setPath(String path) { + this.path = path; + } + + public void setExecutionContext(ExecutionContext executionContext) { + this.executionContext = executionContext; + } + + public void setRunnableCalls(List runnableCalls) { + this.runnableCalls = runnableCalls; + } + + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + public void setSharedContextValuesMap(Map contextValues) { + this.sharedContextValuesMap = contextValues; + } + + public void setFailOnError(Boolean failOnError) { + this.failOnError = failOnError; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java new file mode 100644 index 000000000..e0bbbdda9 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Storage Class for information required to + * instantiate a RunnableCallFlow: + * bean name of the flow, + * path of the flow + * and list of RunnableCall. + * + */ +public class RunnableCallFlowDescriptor { + + /** + * Bean name of the flow to instantiate + */ + private String beanName; + + /** + * Path of the flow to instantiate + */ + private String path; + + /** + * List of RunnableCall + */ + private List runnableCalls = new ArrayList(); + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public List getRunnableCalls() { + return runnableCalls; + } + + public void setRunnableCalls(List runnableCalls) { + this.runnableCalls = runnableCalls; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableDataNode.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableDataNode.java new file mode 100644 index 000000000..51843dcd0 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableDataNode.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import java.util.List; +import java.util.Map; + +/** + * Stores information relative to a Runnable. + * Allows to structure the information as a tree, each node + * storing data as a Map. + */ +public interface RunnableDataNode { + + /** + * @return a Map containing the data associated with this node. + * Data associated with parent nodes are expected + * to be contained in the returned Map + */ + public Map getData(); + + /** + * @return the name of the bean to create. + * Can be null if no bean shall be created for the + * RunnableDataNode (e.g. is is a sub-node) + */ + public String getBeanName(); + + /** + * @return the path of the flow bean to create. + * Can be null if the bean to created is not an + * ExecutionFlow or if no bean shall be created for the + * RunnableDataNode (e.g. is is a sub-node) + */ + public String getPath(); + + /** + * @return whether the RunnableDataNode has + * children or not. + * Expected to be equivalent to getChildren().empty() + */ + public boolean isLeaf(); + + /** + * @return the list of RunnableDataNode children. + * Can be empty. Shall not be null. + */ + public List getChildren(); + + /** + * @return the RunnableDataNode parent. + * Can be null if no parent is defined (top node). + */ + public RunnableDataNode getParent(); + + /** + * Sets the RunnableDataNode parent + * @param parent + */ + public void setParent(RunnableDataNode parent); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableFactory.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableFactory.java new file mode 100644 index 000000000..2b3702889 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/generator/RunnableFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.generator; + +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +/** + * Interprets a RunnableDataNode by creating corresponding + * beans and registering them in a BeanDefinitionRegistry + * + */ +public interface RunnableFactory { + + public void createAndRegisterRunnable(RunnableDataNode node, + BeanDefinitionRegistry beanDefinitionRegistry); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/runtime.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/runtime.xml new file mode 100644 index 000000000..990d85cb2 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/runtime.xml @@ -0,0 +1,68 @@ + + + + + + + Bare minimal runtime configuration. In general you will + want to use simple.xml instead. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/simple.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/simple.xml new file mode 100644 index 000000000..b25f3d130 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/simple.xml @@ -0,0 +1,58 @@ + + + + + + + Default Capabilities + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/specs.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/specs.xml new file mode 100644 index 000000000..7cc960475 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/specs.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/spring.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/spring.xml new file mode 100644 index 000000000..de1c06b1e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/spring.xml @@ -0,0 +1,51 @@ + + + + + + + + Simple runtime enriched with defaults and templates used + to simplify XML files. These templates have been deprecated by the + custom XML namespace and will be removed in SLC 2.x. Use the XML + namespace instead. + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/CloseTestResult.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/CloseTestResult.java new file mode 100644 index 000000000..43b296106 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/CloseTestResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import org.argeo.slc.test.TestResult; + +public class CloseTestResult implements Runnable { + private TestResult testResult; + + public void run() { + testResult.close(); + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/Echo.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/Echo.java new file mode 100644 index 000000000..d47149b86 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/Echo.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.core.io.Resource; + +public class Echo implements Runnable { + private final static Log defaultLog = LogFactory.getLog(Echo.class); + private Resource writeTo = null; + + private Log log; + private Object message; + + public void run() { + log().info(message); + + if (writeTo != null) { + try { + File file = writeTo.getFile(); + if (log().isDebugEnabled()) + log().debug("Write to " + file); + if (message != null) + FileUtils.writeStringToFile(file, message.toString()); + } catch (IOException e) { + throw new SlcException("Could not write to " + writeTo, e); + } + } + } + + private Log log() { + return log != null ? log : defaultLog; + } + + public void setMessage(Object message) { + this.message = message; + } + + public void setWriteTo(Resource writeTo) { + this.writeTo = writeTo; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/If.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/If.java new file mode 100644 index 000000000..0d22e437d --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/If.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import org.argeo.slc.SlcException; + +/** Conditional execution */ +public class If implements Runnable { + private Boolean is; + private Boolean not; + private Runnable then; + private Runnable els; + + public void run() { + if (is == null && not == null) + throw new SlcException("No condition set"); + if (is != null && not != null) + throw new SlcException("Both is and not cannot be set"); + + boolean bool = (is != null ? is : !not); + if (bool) { + if (then != null) + then.run(); + } else { + if (els != null) + els.run(); + } + + } + + public void setIs(Boolean bool) { + this.is = bool; + } + + public void setThen(Runnable then) { + this.then = then; + } + + public void setEls(Runnable els) { + this.els = els; + } + + public Boolean getNot() { + return not; + } + + public void setNot(Boolean not) { + this.not = not; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/JvmProcess.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/JvmProcess.java new file mode 100644 index 000000000..01f11012f --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/JvmProcess.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.io.Resource; + +/** A Java Virtual Machine process. */ +public class JvmProcess extends SystemCall implements InitializingBean { + private Properties systemProperties = new Properties(); + private List classpath = new ArrayList(); + private List pBootClasspath = new ArrayList(); + private Resource jvm = null; + private String mainClass; + private String mainJar; + private List jvmArgs = new ArrayList(); + private List args = new ArrayList(); + + private String systemPropertiesFileProperty = null; + private String systemPropertiesFileDir = null; + private String systemPropertiesFileName = null; + + public void afterPropertiesSet() throws Exception { + List command = new ArrayList(); + if (jvm != null) + command.add(asFile(jvm).getPath()); + else + command.add("java"); + + if (pBootClasspath.size() > 0) { + StringBuffer buf = new StringBuffer("-Xbootclasspath/p:"); + Boolean first = true; + for (Resource res : pBootClasspath) { + if (first) + first = false; + else + buf.append(File.pathSeparatorChar); + + buf.append(asFile(res)); + } + command.add(buf.toString()); + } + + for (String jvmArg : jvmArgs) { + command.add(jvmArg); + } + + if (classpath.size() > 0) { + command.add("-cp"); + StringBuffer buf = new StringBuffer(""); + for (Resource res : classpath) { + if (buf.length() != 0) + buf.append(File.pathSeparatorChar); + buf.append(asFile(res)); + } + command.add(buf.toString()); + } + + if (systemPropertiesFileProperty == null) { + // pass system properties as argument + for (Map.Entry entry : systemProperties.entrySet()) { + command.add("-D" + entry.getKey() + "=" + entry.getValue()); + } + } else { + // write system properties in a file to work around OS limitations + // with command line (e.g. Win XP) + String dir = systemPropertiesFileDir; + if (dir == null) + dir = getExecDirToUse(); + String fileName = systemPropertiesFileName; + if (fileName == null) + fileName = systemPropertiesFileProperty + ".properties"; + + // Write file + FileOutputStream fos = null; + File file = new File(dir + File.separator + fileName); + try { + + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + fos = new FileOutputStream(file); + systemProperties.store(fos, "Automatically generated by " + + getClass()); + command.add("-D" + systemPropertiesFileProperty + "=" + + file.getCanonicalPath()); + } catch (IOException e) { + throw new SlcException("Cannot write to system properties to " + + file, e); + } finally { + IOUtils.closeQuietly(fos); + } + } + + // Program + if (mainClass != null) { + command.add(mainClass); + } else if (mainJar != null) { + command.add("-jar"); + command.add(mainJar); + } else { + throw new SlcException("No main class or jar defined"); + } + + for (String arg : args) { + command.add(arg); + } + + setCommand(command); + } + + protected File asFile(Resource res) { + try { + return res.getFile(); + } catch (FileNotFoundException e) { + return copyToTempFile(res); + } catch (IOException e) { + throw new SlcException("Cannot convert resource to file", e); + } + + } + + protected File copyToTempFile(Resource res) { + File tempFile; + FileOutputStream fos; + try { + tempFile = File.createTempFile("slcJvmProcess-", res.getFilename()); + tempFile.deleteOnExit(); + fos = new FileOutputStream(tempFile); + IOUtils.copy(res.getInputStream(), fos); + } catch (IOException e) { + throw new SlcException("Cannot copy " + res + " to temp file.", e); + } + IOUtils.closeQuietly(fos); + return tempFile; + } + + /** Append the argument (for chaining) */ + @Override + public SystemCall arg(String arg) { + args.add(arg); + return this; + } + + /** Append the argument (for chaining) */ + @Override + public SystemCall arg(String arg, String value) { + args.add(arg); + args.add(value); + return this; + } + + public Properties getSystemProperties() { + return systemProperties; + } + + public void setSystemProperties(Properties systemProperties) { + this.systemProperties = systemProperties; + } + + public List getClasspath() { + return classpath; + } + + public void setClasspath(List classpath) { + this.classpath = classpath; + } + + public List getPBootClasspath() { + return pBootClasspath; + } + + public void setPBootClasspath(List bootClasspath) { + pBootClasspath = bootClasspath; + } + + public Resource getJvm() { + return jvm; + } + + public void setJvm(Resource jvm) { + this.jvm = jvm; + } + + public String getMainClass() { + return mainClass; + } + + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + public String getMainJar() { + return mainJar; + } + + public void setMainJar(String mainJar) { + this.mainJar = mainJar; + } + + public List getJvmArgs() { + return jvmArgs; + } + + public void setJvmArgs(List jvmArgs) { + this.jvmArgs = jvmArgs; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public void setSystemPropertiesFileProperty( + String systemPropertiesFilePropertyName) { + this.systemPropertiesFileProperty = systemPropertiesFilePropertyName; + } + + public void setSystemPropertiesFileDir(String systemPropertiesFileDir) { + this.systemPropertiesFileDir = systemPropertiesFileDir; + } + + public void setSystemPropertiesFileName(String systemPropertiesFileName) { + this.systemPropertiesFileName = systemPropertiesFileName; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MergedLists.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MergedLists.java new file mode 100644 index 000000000..ab6f59efc --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MergedLists.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.FactoryBean; + +/** Merge the provided lists in one single list, in the order provided. */ +public class MergedLists implements FactoryBean { + private List> lists = new ArrayList>(); + + public void setLists(List> lists) { + this.lists = lists; + } + + public Object getObject() throws Exception { + List merged = new ArrayList(); + for (List lst : lists) { + merged.addAll(lst); + } + return merged; + } + + public Class getObjectType() { + return List.class; + } + + public boolean isSingleton() { + return false; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MethodCall.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MethodCall.java new file mode 100644 index 000000000..e4fa77222 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/MethodCall.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class MethodCall implements Runnable { + private Object target; + private String method; + private List args = new ArrayList(); + + public void run() { + Assert.notNull(target, "target"); + Assert.notNull(method, "method"); + Method methodRef = ReflectionUtils + .findMethod(target.getClass(), method); + if (args.size() == 0) + ReflectionUtils.invokeMethod(methodRef, target); + else + ReflectionUtils.invokeMethod(methodRef, methodRef, args.toArray()); + } + + public void setTarget(Object target) { + this.target = target; + } + + public void setMethod(String method) { + this.method = method; + } + + public void setArgs(List args) { + this.args = args; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/OverrideContextAware.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/OverrideContextAware.java new file mode 100644 index 000000000..9afa8468c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/OverrideContextAware.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import org.argeo.slc.SlcException; +import org.argeo.slc.core.test.context.SimpleContextAware; +import org.argeo.slc.test.context.ContextAware; + +/** + * Overrides Values and Expected values of a target + * SimpleContextAware with the corresponding + * values and expected values of a source ContextAware + * + */ +public class OverrideContextAware implements Runnable { + + private ContextAware source; + + private SimpleContextAware target; + + /** + * Whether an exception shall be thrown if a value + * or expected value of the source is not defined + * in the target + */ + private Boolean failIfUndefinedInSource = true; + + public void run() { + // override values + if(source.getValues() != null) + for(String key : source.getValues().keySet()) { + if(failIfUndefinedInSource && !target.getValues().containsKey(key)) { + throw new SlcException("No entry in target values for key '" + key + "'"); + } + target.getValues().put(key, source.getValues().get(key)); + } + + // override expected values + if(source.getExpectedValues() != null) + for(String key : source.getExpectedValues().keySet()) { + if(failIfUndefinedInSource && !target.getExpectedValues().containsKey(key)) { + throw new SlcException("No entry in target expected values for key '" + key + "'"); + } + target.getExpectedValues().put(key, source.getExpectedValues().get(key)); + } + } + + public void setSource(ContextAware source) { + this.source = source; + } + + public void setTarget(SimpleContextAware target) { + this.target = target; + } + + public void setFailIfUndefinedInSource(Boolean failIfUndefinedInSource) { + this.failIfUndefinedInSource = failIfUndefinedInSource; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCall.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCall.java new file mode 100644 index 000000000..8f031847e --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -0,0 +1,782 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.callback.CallbackHandler; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteResultHandler; +import org.apache.commons.exec.ExecuteStreamHandler; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.LogOutputStream; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.ShutdownHookProcessDestroyer; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.core.execution.ExecutionResources; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestStatus; +import org.springframework.core.io.Resource; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; + +/** Execute an OS specific system call. */ +public class SystemCall implements Runnable { + public final static String LOG_STDOUT = "System.out"; + + private final Log log = LogFactory.getLog(getClass()); + + private String execDir; + + private String cmd = null; + private List command = null; + + private Executor executor = new DefaultExecutor(); + private Boolean synchronous = true; + + private String stdErrLogLevel = "ERROR"; + private String stdOutLogLevel = "INFO"; + + private Resource stdOutFile = null; + private Resource stdErrFile = null; + + private Resource stdInFile = null; + /** + * If no {@link #stdInFile} provided, writing to this stream will write to + * the stdin of the process. + */ + private OutputStream stdInSink = null; + + private Boolean redirectStdOut = false; + + private List outputListeners = Collections + .synchronizedList(new ArrayList()); + + private Map> osCommands = new HashMap>(); + private Map osCmds = new HashMap(); + private Map environmentVariables = new HashMap(); + + private Boolean logCommand = false; + private Boolean redirectStreams = true; + private Boolean exceptionOnFailed = true; + private Boolean mergeEnvironmentVariables = true; + + private Authentication authentication; + + private String osConsole = null; + private String generateScript = null; + + /** 24 hours */ + private Long watchdogTimeout = 24 * 60 * 60 * 1000l; + + private TestResult testResult; + + private ExecutionResources executionResources; + + /** Sudo the command, as root if empty or as user if not. */ + private String sudo = null; + // TODO make it more secure and robust, test only once + private final String sudoPrompt = UUID.randomUUID().toString(); + private String askPassProgram = "/usr/libexec/openssh/ssh-askpass"; + private boolean firstLine = true; + private CallbackHandler callbackHandler; + /** Chroot to the this path (must not be empty) */ + private String chroot = null; + + // Current + /** Current watchdog, null if process is completed */ + ExecuteWatchdog currentWatchdog = null; + + /** Empty constructor */ + public SystemCall() { + + } + + /** + * Constructor based on the provided command list. + * + * @param command + * the command list + */ + public SystemCall(List command) { + this.command = command; + } + + /** + * Constructor based on the provided command. + * + * @param cmd + * the command. If the provided string contains no space a + * command list is initialized with the argument as first + * component (useful for chained construction) + */ + public SystemCall(String cmd) { + if (cmd.indexOf(' ') < 0) { + command = new ArrayList(); + command.add(cmd); + } else { + this.cmd = cmd; + } + } + + /** Executes the system call. */ + public void run() { + authentication = SecurityContextHolder.getContext().getAuthentication(); + + // Manage streams + Writer stdOutWriter = null; + OutputStream stdOutputStream = null; + Writer stdErrWriter = null; + InputStream stdInStream = null; + if (stdOutFile != null) + if (redirectStdOut) + stdOutputStream = createOutputStream(stdOutFile); + else + stdOutWriter = createWriter(stdOutFile, true); + + if (stdErrFile != null) { + stdErrWriter = createWriter(stdErrFile, true); + } else { + if (stdOutFile != null && !redirectStdOut) + stdErrWriter = createWriter(stdOutFile, true); + } + + try { + if (stdInFile != null) + stdInStream = stdInFile.getInputStream(); + else { + stdInStream = new PipedInputStream(); + stdInSink = new PipedOutputStream( + (PipedInputStream) stdInStream); + } + } catch (IOException e2) { + throw new SlcException("Cannot open a stream for " + stdInFile, e2); + } + + if (log.isTraceEnabled()) { + log.debug("os.name=" + System.getProperty("os.name")); + log.debug("os.arch=" + System.getProperty("os.arch")); + log.debug("os.version=" + System.getProperty("os.version")); + } + + // Execution directory + File dir = new File(getExecDirToUse()); + // if (!dir.exists()) + // dir.mkdirs(); + + // Watchdog to check for lost processes + Executor executorToUse; + if (executor != null) + executorToUse = executor; + else + executorToUse = new DefaultExecutor(); + executorToUse.setWatchdog(createWatchdog()); + + if (redirectStreams) { + // Redirect standard streams + executorToUse.setStreamHandler(createExecuteStreamHandler( + stdOutWriter, stdOutputStream, stdErrWriter, stdInStream)); + } else { + // Dummy stream handler (otherwise pump is used) + executorToUse.setStreamHandler(new DummyexecuteStreamHandler()); + } + + executorToUse.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + executorToUse.setWorkingDirectory(dir); + + // Command line to use + final CommandLine commandLine = createCommandLine(); + if (logCommand) + log.info("Execute command:\n" + commandLine + + "\n in working directory: \n" + dir + "\n"); + + // Env variables + Map environmentVariablesToUse = null; + environmentVariablesToUse = new HashMap(); + if (mergeEnvironmentVariables) + environmentVariablesToUse.putAll(System.getenv()); + if (environmentVariables.size() > 0) + environmentVariablesToUse.putAll(environmentVariables); + + // Execute + ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); + + // + // THE EXECUTION PROPER + // + try { + if (synchronous) + try { + int exitValue = executorToUse.execute(commandLine, + environmentVariablesToUse); + executeResultHandler.onProcessComplete(exitValue); + } catch (ExecuteException e1) { + if (e1.getExitValue() == Executor.INVALID_EXITVALUE) { + Thread.currentThread().interrupt(); + return; + } + // Sleep 1s in order to make sure error logs are flushed + Thread.sleep(1000); + executeResultHandler.onProcessFailed(e1); + } + else + executorToUse.execute(commandLine, environmentVariablesToUse, + executeResultHandler); + } catch (SlcException e) { + throw e; + } catch (Exception e) { + throw new SlcException("Could not execute command " + commandLine, + e); + } finally { + IOUtils.closeQuietly(stdOutWriter); + IOUtils.closeQuietly(stdErrWriter); + IOUtils.closeQuietly(stdInStream); + IOUtils.closeQuietly(stdInSink); + } + + } + + public synchronized String function() { + final StringBuffer buf = new StringBuffer(""); + SystemCallOutputListener tempOutputListener = new SystemCallOutputListener() { + private Long lineCount = 0l; + + public void newLine(SystemCall systemCall, String line, + Boolean isError) { + if (!isError) { + if (lineCount != 0l) + buf.append('\n'); + buf.append(line); + lineCount++; + } + } + }; + addOutputListener(tempOutputListener); + run(); + removeOutputListener(tempOutputListener); + return buf.toString(); + } + + public String asCommand() { + return createCommandLine().toString(); + } + + @Override + public String toString() { + return asCommand(); + } + + /** + * Build a command line based on the properties. Can be overridden by + * specific command wrappers. + */ + protected CommandLine createCommandLine() { + // Check if an OS specific command overrides + String osName = System.getProperty("os.name"); + List commandToUse = null; + if (osCommands.containsKey(osName)) + commandToUse = osCommands.get(osName); + else + commandToUse = command; + String cmdToUse = null; + if (osCmds.containsKey(osName)) + cmdToUse = osCmds.get(osName); + else + cmdToUse = cmd; + + CommandLine commandLine = null; + + // Which command definition to use + if (commandToUse == null && cmdToUse == null) + throw new SlcException("Please specify a command."); + else if (commandToUse != null && cmdToUse != null) + throw new SlcException( + "Specify the command either as a line or as a list."); + else if (cmdToUse != null) { + if (chroot != null && !chroot.trim().equals("")) + cmdToUse = "chroot \"" + chroot + "\" " + cmdToUse; + if (sudo != null) { + environmentVariables.put("SUDO_ASKPASS", askPassProgram); + if (!sudo.trim().equals("")) + cmdToUse = "sudo -p " + sudoPrompt + " -u " + sudo + " " + + cmdToUse; + else + cmdToUse = "sudo -p " + sudoPrompt + " " + cmdToUse; + } + + // GENERATE COMMAND LINE + commandLine = CommandLine.parse(cmdToUse); + } else if (commandToUse != null) { + if (commandToUse.size() == 0) + throw new SlcException("Command line is empty."); + + if (chroot != null && sudo != null) { + commandToUse.add(0, "chroot"); + commandToUse.add(1, chroot); + } + + if (sudo != null) { + environmentVariables.put("SUDO_ASKPASS", askPassProgram); + commandToUse.add(0, "sudo"); + commandToUse.add(1, "-p"); + commandToUse.add(2, sudoPrompt); + if (!sudo.trim().equals("")) { + commandToUse.add(3, "-u"); + commandToUse.add(4, sudo); + } + } + + // GENERATE COMMAND LINE + commandLine = new CommandLine(commandToUse.get(0).toString()); + + for (int i = 1; i < commandToUse.size(); i++) { + if (log.isTraceEnabled()) + log.debug(commandToUse.get(i)); + commandLine.addArgument(commandToUse.get(i).toString()); + } + } else { + // all cases covered previously + throw new UnsupportedException(); + } + + if (generateScript != null) { + File scriptFile = new File(getExecDirToUse() + File.separator + + generateScript); + try { + FileUtils.writeStringToFile(scriptFile, + (osConsole != null ? osConsole + " " : "") + + commandLine.toString()); + } catch (IOException e) { + throw new SlcException("Could not generate script " + + scriptFile, e); + } + commandLine = new CommandLine(scriptFile); + } else { + if (osConsole != null) + commandLine = CommandLine.parse(osConsole + " " + + commandLine.toString()); + } + + return commandLine; + } + + /** + * Creates a {@link PumpStreamHandler} which redirects streams to the custom + * logging mechanism. + */ + protected ExecuteStreamHandler createExecuteStreamHandler( + final Writer stdOutWriter, final OutputStream stdOutputStream, + final Writer stdErrWriter, final InputStream stdInStream) { + + // Log writers + OutputStream stdout = stdOutputStream != null ? stdOutputStream + : new LogOutputStream() { + protected void processLine(String line, int level) { + // if (firstLine) { + // if (sudo != null && callbackHandler != null + // && line.startsWith(sudoPrompt)) { + // try { + // PasswordCallback pc = new PasswordCallback( + // "sudo password", false); + // Callback[] cbs = { pc }; + // callbackHandler.handle(cbs); + // char[] pwd = pc.getPassword(); + // char[] arr = Arrays.copyOf(pwd, + // pwd.length + 1); + // arr[arr.length - 1] = '\n'; + // IOUtils.write(arr, stdInSink); + // stdInSink.flush(); + // } catch (Exception e) { + // throw new SlcException( + // "Cannot retrieve sudo password", e); + // } + // } + // firstLine = false; + // } + + if (line != null && !line.trim().equals("")) + logStdOut(line); + + if (stdOutWriter != null) + appendLineToFile(stdOutWriter, line); + } + }; + + OutputStream stderr = new LogOutputStream() { + protected void processLine(String line, int level) { + if (line != null && !line.trim().equals("")) + logStdErr(line); + if (stdErrWriter != null) + appendLineToFile(stdErrWriter, line); + } + }; + + PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, + stderr, stdInStream) { + + @Override + public void stop() throws IOException { + // prevents the method to block when joining stdin + if (stdInSink != null) + IOUtils.closeQuietly(stdInSink); + + super.stop(); + } + }; + return pumpStreamHandler; + } + + /** Creates the default {@link ExecuteResultHandler}. */ + protected ExecuteResultHandler createExecuteResultHandler( + final CommandLine commandLine) { + return new ExecuteResultHandler() { + + public void onProcessComplete(int exitValue) { + String msg = "System call '" + commandLine + + "' properly completed."; + if (log.isTraceEnabled()) + log.trace(msg); + if (testResult != null) { + forwardPath(testResult); + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, msg)); + } + releaseWatchdog(); + } + + public void onProcessFailed(ExecuteException e) { + + String msg = "System call '" + commandLine + "' failed."; + if (testResult != null) { + forwardPath(testResult); + testResult.addResultPart(new SimpleResultPart( + TestStatus.ERROR, msg, e)); + } else { + if (exceptionOnFailed) + throw new SlcException(msg, e); + else + log.error(msg, e); + } + releaseWatchdog(); + } + }; + } + + @Deprecated + protected void forwardPath(TestResult testResult) { + // TODO: allocate a TreeSPath + } + + /** + * Shortcut method getting the execDir to use + */ + protected String getExecDirToUse() { + try { + if (execDir != null) { + return execDir; + } + return System.getProperty("user.dir"); + } catch (Exception e) { + throw new SlcException("Cannot find exec dir", e); + } + } + + protected void logStdOut(String line) { + for (SystemCallOutputListener outputListener : outputListeners) + outputListener.newLine(this, line, false); + log(stdOutLogLevel, line); + } + + protected void logStdErr(String line) { + for (SystemCallOutputListener outputListener : outputListeners) + outputListener.newLine(this, line, true); + log(stdErrLogLevel, line); + } + + /** Log from the underlying streams. */ + protected void log(String logLevel, String line) { + // TODO optimize + if (SecurityContextHolder.getContext().getAuthentication() == null) { + SecurityContextHolder.getContext() + .setAuthentication(authentication); + } + + if ("ERROR".equals(logLevel)) + log.error(line); + else if ("WARN".equals(logLevel)) + log.warn(line); + else if ("INFO".equals(logLevel)) + log.info(line); + else if ("DEBUG".equals(logLevel)) + log.debug(line); + else if ("TRACE".equals(logLevel)) + log.trace(line); + else if (LOG_STDOUT.equals(logLevel)) + System.out.println(line); + else if ("System.err".equals(logLevel)) + System.err.println(line); + else + throw new SlcException("Unknown log level " + logLevel); + } + + /** Append line to a log file. */ + protected void appendLineToFile(Writer writer, String line) { + try { + writer.append(line).append('\n'); + } catch (IOException e) { + log.error("Cannot write to log file", e); + } + } + + /** Creates the writer for the output/err files. */ + protected Writer createWriter(Resource target, Boolean append) { + FileWriter writer = null; + try { + + final File file; + if (executionResources != null) + file = new File(executionResources.getAsOsPath(target, true)); + else + file = target.getFile(); + writer = new FileWriter(file, append); + } catch (IOException e) { + log.error("Cannot get file for " + target, e); + IOUtils.closeQuietly(writer); + } + return writer; + } + + /** Creates an outputstream for the output/err files. */ + protected OutputStream createOutputStream(Resource target) { + FileOutputStream out = null; + try { + + final File file; + if (executionResources != null) + file = new File(executionResources.getAsOsPath(target, true)); + else + file = target.getFile(); + out = new FileOutputStream(file, false); + } catch (IOException e) { + log.error("Cannot get file for " + target, e); + IOUtils.closeQuietly(out); + } + return out; + } + + /** Append the argument (for chaining) */ + public SystemCall arg(String arg) { + if (command == null) + command = new ArrayList(); + command.add(arg); + return this; + } + + /** Append the argument (for chaining) */ + public SystemCall arg(String arg, String value) { + if (command == null) + command = new ArrayList(); + command.add(arg); + command.add(value); + return this; + } + + // CONTROL + public synchronized Boolean isRunning() { + return currentWatchdog != null; + } + + private synchronized ExecuteWatchdog createWatchdog() { +// if (currentWatchdog != null) +// throw new SlcException("A process is already being monitored"); + currentWatchdog = new ExecuteWatchdog(watchdogTimeout); + return currentWatchdog; + } + + private synchronized void releaseWatchdog() { + currentWatchdog = null; + } + + public synchronized void kill() { + if (currentWatchdog != null) + currentWatchdog.destroyProcess(); + } + + /** */ + public void setCmd(String command) { + this.cmd = command; + } + + public void setCommand(List command) { + this.command = command; + } + + public void setExecDir(String execdir) { + this.execDir = execdir; + } + + public void setStdErrLogLevel(String stdErrLogLevel) { + this.stdErrLogLevel = stdErrLogLevel; + } + + public void setStdOutLogLevel(String stdOutLogLevel) { + this.stdOutLogLevel = stdOutLogLevel; + } + + public void setSynchronous(Boolean synchronous) { + this.synchronous = synchronous; + } + + public void setOsCommands(Map> osCommands) { + this.osCommands = osCommands; + } + + public void setOsCmds(Map osCmds) { + this.osCmds = osCmds; + } + + public void setEnvironmentVariables(Map environmentVariables) { + this.environmentVariables = environmentVariables; + } + + public Map getEnvironmentVariables() { + return environmentVariables; + } + + public void setWatchdogTimeout(Long watchdogTimeout) { + this.watchdogTimeout = watchdogTimeout; + } + + public void setStdOutFile(Resource stdOutFile) { + this.stdOutFile = stdOutFile; + } + + public void setStdErrFile(Resource stdErrFile) { + this.stdErrFile = stdErrFile; + } + + public void setStdInFile(Resource stdInFile) { + this.stdInFile = stdInFile; + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + + public void setLogCommand(Boolean logCommand) { + this.logCommand = logCommand; + } + + public void setRedirectStreams(Boolean redirectStreams) { + this.redirectStreams = redirectStreams; + } + + public void setExceptionOnFailed(Boolean exceptionOnFailed) { + this.exceptionOnFailed = exceptionOnFailed; + } + + public void setMergeEnvironmentVariables(Boolean mergeEnvironmentVariables) { + this.mergeEnvironmentVariables = mergeEnvironmentVariables; + } + + public void setOsConsole(String osConsole) { + this.osConsole = osConsole; + } + + public void setGenerateScript(String generateScript) { + this.generateScript = generateScript; + } + + public void setExecutionResources(ExecutionResources executionResources) { + this.executionResources = executionResources; + } + + public void setRedirectStdOut(Boolean redirectStdOut) { + this.redirectStdOut = redirectStdOut; + } + + public void addOutputListener(SystemCallOutputListener outputListener) { + outputListeners.add(outputListener); + } + + public void removeOutputListener(SystemCallOutputListener outputListener) { + outputListeners.remove(outputListener); + } + + public void setOutputListeners( + List outputListeners) { + this.outputListeners = outputListeners; + } + + public void setExecutor(Executor executor) { + this.executor = executor; + } + + public void setSudo(String sudo) { + this.sudo = sudo; + } + + public void setCallbackHandler(CallbackHandler callbackHandler) { + this.callbackHandler = callbackHandler; + } + + public void setChroot(String chroot) { + this.chroot = chroot; + } + + private class DummyexecuteStreamHandler implements ExecuteStreamHandler { + + public void setProcessErrorStream(InputStream is) throws IOException { + } + + public void setProcessInputStream(OutputStream os) throws IOException { + } + + public void setProcessOutputStream(InputStream is) throws IOException { + } + + public void start() throws IOException { + } + + public void stop() { + } + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java new file mode 100644 index 000000000..b28f1ade2 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +public interface SystemCallOutputListener { + public void newLine(SystemCall systemCall, String line, Boolean isError); +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/UploadAttachments.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/UploadAttachments.java new file mode 100644 index 000000000..13cc51918 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/UploadAttachments.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.tasks; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.argeo.slc.SlcException; +import org.argeo.slc.core.attachment.Attachment; +import org.argeo.slc.core.attachment.AttachmentUploader; +import org.argeo.slc.core.attachment.AttachmentsEnabled; +import org.springframework.core.io.Resource; + +public class UploadAttachments implements Runnable { + private AttachmentUploader attachmentUploader; + private Attachment attachment = null; + private Resource resource = null; + private Map attachments = new HashMap(); + private List attachTo = new ArrayList(); + private Boolean newUuidPerExecution = true; + + public void run() { + if (attachment != null) { + if (resource == null) + throw new SlcException("A resource must be specified."); + uploadAndAdd(attachment, resource); + } + + for (Attachment attachmentT : attachments.keySet()) { + Resource resourceT = attachments.get(attachmentT); + uploadAndAdd(attachmentT, resourceT); + } + + } + + protected void uploadAndAdd(Attachment attachment, Resource resource) { + if (newUuidPerExecution) + attachment.setUuid(UUID.randomUUID().toString()); + attachmentUploader.upload(attachment, resource); + for (AttachmentsEnabled attachmentsEnabled : attachTo) { + attachmentsEnabled.addAttachment(attachment); + } + } + + public void setAttachmentUploader(AttachmentUploader attachmentUploader) { + this.attachmentUploader = attachmentUploader; + } + + public void setAttachments(Map attachments) { + this.attachments = attachments; + } + + public void setAttachTo(List attachTo) { + this.attachTo = attachTo; + } + + public void setAttachment(Attachment attachment) { + this.attachment = attachment; + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + public void setNewUuidPerExecution(Boolean newUuidPerExecution) { + this.newUuidPerExecution = newUuidPerExecution; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/core.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/core.xml new file mode 100644 index 000000000..df35944ee --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/tasks/core.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/templates.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/templates.xml new file mode 100644 index 000000000..28b742af7 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/templates.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/utils.xml b/org.argeo.slc.core/src/org/argeo/slc/core/execution/utils.xml new file mode 100644 index 000000000..527e701f6 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/utils.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/AsFlowDecorator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/AsFlowDecorator.java new file mode 100644 index 000000000..ecdf5b56a --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/AsFlowDecorator.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.DefaultExecutionFlow; +import org.argeo.slc.execution.ExecutionFlow; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.xml.BeanDefinitionDecorator; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Attr; +import org.w3c.dom.Node; + +/** Publishes a {@link Runnable} as an {@link ExecutionFlow} */ +public class AsFlowDecorator implements BeanDefinitionDecorator { + private Log log = LogFactory.getLog(AsFlowDecorator.class); + + @SuppressWarnings("unchecked") + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder bean, + ParserContext ctx) { + String attrValue = ((Attr) node).getValue(); + if (attrValue.charAt(attrValue.length() - 1) == '/') + throw new SlcException(attrValue + " cannot end with a path"); + final String flowBeanName = attrValue; + + if (log.isTraceEnabled()) + log.trace("flowBeanName=" + flowBeanName); + + if (ctx.getRegistry().containsBeanDefinition(flowBeanName)) + throw new SlcException("A bean named " + flowBeanName + + " is already defined."); + BeanDefinitionBuilder flow = BeanDefinitionBuilder + .rootBeanDefinition(DefaultExecutionFlow.class); + ManagedList executables = new ManagedList(1); + + String beanName = bean.getBeanName(); + if (beanName == null) + executables.add(bean.getBeanDefinition()); + else + executables.add(new RuntimeBeanReference(beanName)); + + // if (path != null) + // flow.addPropertyValue("path", path); + flow.addPropertyValue("executables", executables); + + if (beanName != null) + ctx.getRegistry().registerBeanDefinition(flowBeanName, + flow.getBeanDefinition()); + return bean; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java new file mode 100644 index 000000000..dfca9d512 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionDecorator; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Inspired by org.springframework.aop.config.ScopedProxyBeanDefinitionDecorator + */ +public class ExecutionScopeDecorator implements BeanDefinitionDecorator { + private static final String PROXY_TARGET_CLASS = "proxy-target-class"; + + public BeanDefinitionHolder decorate(Node node, + BeanDefinitionHolder definition, ParserContext parserContext) { + + definition.getBeanDefinition().setScope("execution"); + + // Default: CGLib not used + boolean proxyTargetClass = false; + if (node instanceof Element) { + Element ele = (Element) node; + if (ele.hasAttribute(PROXY_TARGET_CLASS)) { + proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)).booleanValue(); + } + } + + // Register the original bean definition as it will be referenced by the scoped proxy and is relevant for tooling (validation, navigation). + String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName()); + parserContext.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName)); + + return ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java new file mode 100644 index 000000000..ca64d12f5 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.core.execution.DefaultExecutionFlow; +import org.argeo.slc.execution.ExecutionFlow; +import org.springframework.beans.factory.BeanDefinitionStoreException; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.ManagedMap; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** Interprets the tag */ +public class FlowBeanDefinitionParser extends + AbstractSingleBeanDefinitionParser { + private Log log = LogFactory.getLog(FlowBeanDefinitionParser.class); + + /** Whether the user has already be warned on path attribute usage. */ + private Boolean warnedAboutPathAttribute = false; + + @SuppressWarnings("unchecked") + @Override + protected void doParse(Element element, ParserContext parserContext, + BeanDefinitionBuilder builder) { + String path = element.getAttribute("path"); + if (StringUtils.hasText(path)) { + builder.addPropertyValue("path", path); + + // warns user only once + if (!warnedAboutPathAttribute) + log.warn("The path=\"\" attribute is deprecated" + + " and will be removed in a later release." + + " Use ."); + warnedAboutPathAttribute = true; + } + + String spec = element.getAttribute("spec"); + if (StringUtils.hasText(spec)) + builder.getBeanDefinition().getConstructorArgumentValues() + .addGenericArgumentValue(new RuntimeBeanReference(spec)); + + String abstrac = element.getAttribute("abstract"); + if (StringUtils.hasText(abstrac)) + builder.setAbstract(Boolean.parseBoolean(abstrac)); + + String parent = element.getAttribute("parent"); + if (StringUtils.hasText(parent)) + builder.setParentName(parent); + + builder.getBeanDefinition().setDescription( + DomUtils.getChildElementValueByTagName(element, "description")); + + List argsElems = new ArrayList(); + List execElems = new ArrayList(); + List specElems = new ArrayList(); + NodeList nodeList = element.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node instanceof Element) { + if (DomUtils.nodeNameEquals(node, "arg")) + argsElems.add((Element) node); + else if (DomUtils.nodeNameEquals(node, "spec")) + specElems.add((Element) node); + else if (!DomUtils.nodeNameEquals(node, "description")) + execElems.add((Element) node); + } + } + + // Arguments + if (argsElems.size() != 0) { + ManagedMap args = new ManagedMap(argsElems.size()); + for (Element argElem : argsElems) { + Object value = NamespaceUtils.parseValue(argElem, + parserContext, builder.getBeanDefinition(), null); + if (value != null) + args.put(argElem.getAttribute("name"), value); + else + throw new SlcException("No value defined."); + } + builder.getBeanDefinition().getConstructorArgumentValues() + .addGenericArgumentValue(args); + } + + // Execution specs + if (StringUtils.hasText(spec) && specElems.size() != 0) + throw new SlcException("A flow cannot have multiple specs"); + if (specElems.size() == 1) { + Object specObj = NamespaceUtils.parseBeanOrReference( + specElems.get(0), parserContext, + builder.getBeanDefinition()); + builder.getBeanDefinition().getConstructorArgumentValues() + .addGenericArgumentValue(specObj); + } else if (specElems.size() > 1) + throw new SlcException("A flow cannot have multiple specs"); + + // Executables + if (execElems.size() != 0) { + ManagedList executables = new ManagedList(execElems.size()); + for (Element child : execElems) { + // child validity check is performed in xsd + executables.add(NamespaceUtils.parseBeanOrReference(child, + parserContext, builder.getBeanDefinition())); + } + if (executables.size() > 0) + builder.addPropertyValue("executables", executables); + } + } + + @SuppressWarnings("unchecked") + @Override + protected Class getBeanClass(Element element) { + String clss = element.getAttribute("class"); + if (StringUtils.hasText(clss)) + // TODO: check that it actually works + try { + return (Class) getClass() + .getClassLoader().loadClass(clss); + } catch (ClassNotFoundException e) { + try { + return (Class) Thread + .currentThread().getContextClassLoader() + .loadClass(clss); + } catch (ClassNotFoundException e1) { + throw new SlcException("Cannot load class " + clss, e); + } + } + else + return DefaultExecutionFlow.class; + } + + // parse nested bean definition + // private Object parseBeanReference(Element element, + // ParserContext parserContext, BeanDefinitionBuilder builder) { + // return parserContext.getDelegate().parsePropertySubElement(element, + // builder.getBeanDefinition()); + // } + + @Override + protected String resolveId(Element element, + AbstractBeanDefinition definition, ParserContext parserContext) + throws BeanDefinitionStoreException { + String name = element.getAttribute("name"); + if (StringUtils.hasText(name)) { + return name; + } else { + return super.resolveId(element, definition, parserContext); + } + } + + protected boolean shouldGenerateIdAsFallback() { + return true; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java new file mode 100644 index 000000000..2deba8bb2 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +public class FlowNamespaceHandler extends NamespaceHandlerSupport { + + public void init() { + registerBeanDefinitionParser("flow", new FlowBeanDefinitionParser()); + registerBeanDefinitionParser("spec", new SpecBeanDefinitionParser()); + registerBeanDefinitionDecoratorForAttribute("as-flow", + new AsFlowDecorator()); + registerBeanDefinitionParser("param", new ParamDecorator()); + + // The objective was to replace + // - attribute scope="execution" + // - and element "aop:scoped-proxy" + // by a single attribute, using an attribute decorator + // this does not work correctly with other attribute decorators (e.g. + // p namespace) since this decorator needs to be called after all + // properties have been set on target bean. + // It works properly with element decorators (called after all attribute + // decorators + registerBeanDefinitionDecorator("variable", new ExecutionScopeDecorator()); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/NamespaceUtils.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/NamespaceUtils.java new file mode 100644 index 000000000..ccf94f131 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/NamespaceUtils.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.argeo.slc.SlcException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Utilities to simplify common tasks when interpreting a custom namespace and + * converting it into bean definitions. + */ +public class NamespaceUtils { + // private final static Log log = LogFactory.getLog(NamespaceUtils.class); + + /** + * Returns the value defined either: directly by the the 'value' attribute, + * as reference by the 'ref' attribute or as a nested bean. + */ + public static Object parseValue(Element element, + ParserContext parserContext, + BeanDefinition containingBeanDefintion, String valueTagName) { + Object value = null; + if (element.hasAttribute("value")) { + value = element.getAttribute("value"); + } + + if (element.hasAttribute("ref")) { + if (value != null) + throw new SlcException("Multiple value definition for " + + element); + value = new RuntimeBeanReference(element.getAttribute("ref")); + } + + Element uniqueSubElem = null; + if (valueTagName != null) { + Element valueElem = DomUtils.getChildElementByTagName(element, + valueTagName); + if (valueElem != null) { + uniqueSubElem = findUniqueSubElement(valueElem); + if (uniqueSubElem == null) + throw new SlcException("No subelement found under " + + valueElem); + } + } else {// no intermediary tag + uniqueSubElem = findUniqueSubElement(element); + } + + if (uniqueSubElem != null) { + if (value != null) + throw new SlcException("Multiple value definition for " + + element); + value = parseBeanOrReference(uniqueSubElem, parserContext, + containingBeanDefintion); + } + return value; + } + + public static Element findUniqueSubElement(Element element) { + NodeList childNodes = element.getChildNodes(); + + Element uniqueSubElem = null; + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if (node != null && node instanceof Element) { + if (uniqueSubElem == null) + uniqueSubElem = (Element) node; + else + throw new SlcException( + "There are more than one sub element under " + + element); + } + } + return uniqueSubElem; + } + + public static Object parseBeanOrReference(Element element, + ParserContext parserContext, BeanDefinition beanDefinition) { + // return parserContext.getDelegate().parsePropertySubElement(element, + // beanDefinition); + + BeanDefinitionParserDelegate deleg = parserContext.getDelegate(); + // if ("bean".equals(element.getNodeName())) + // return deleg.parseBeanDefinitionElement(element, beanDefinition); + // else + return deleg.parsePropertySubElement(element, beanDefinition); + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ParamDecorator.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ParamDecorator.java new file mode 100644 index 000000000..16839c042 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/ParamDecorator.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import org.argeo.slc.core.execution.ParameterRef; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +public class ParamDecorator extends AbstractSingleBeanDefinitionParser { + + // public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder + // bean, + // ParserContext ctx) { + // String paramName = ((Element) node).getAttribute("name"); + // String propertyName = ((Element) node.getParentNode()) + // .getAttribute("name"); + // BeanDefinitionBuilder parameterRef = BeanDefinitionBuilder + // .genericBeanDefinition(ParameterRef.class); + // parameterRef.addPropertyReference("instantiationManager", + // "instantiationManager"); + // parameterRef.addConstructorArgValue(paramName); + // bean.getBeanDefinition().getPropertyValues().addPropertyValue( + // propertyName, parameterRef.getBeanDefinition()); + // return bean; + // } + + @Override + protected void doParse(Element element, ParserContext parserContext, + BeanDefinitionBuilder builder) { + String paramName = element.getAttribute("name"); + + String instantationManagerRef = element + .getAttribute("instantiationManager"); + if (!StringUtils.hasText(instantationManagerRef)) + instantationManagerRef = "instantiationManager"; + builder.addPropertyReference("instantiationManager", + instantationManagerRef); + builder.addConstructorArgValue(paramName); + } + + @Override + protected Class getBeanClass(Element element) { + return ParameterRef.class; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java new file mode 100644 index 000000000..4ef3f9788 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.execution.xml; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.execution.DefaultExecutionSpec; +import org.argeo.slc.core.execution.PrimitiveSpecAttribute; +import org.argeo.slc.core.execution.RefSpecAttribute; +import org.argeo.slc.core.execution.RefValueChoice; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.support.ManagedMap; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; + +/** Interprets the tag */ +public class SpecBeanDefinitionParser extends + AbstractSingleBeanDefinitionParser { + private Log log = LogFactory.getLog(SpecBeanDefinitionParser.class); + + @SuppressWarnings("unchecked") + @Override + protected void doParse(Element element, ParserContext parserContext, + BeanDefinitionBuilder builder) { + builder.getBeanDefinition().setDescription( + DomUtils.getChildElementValueByTagName(element, "description")); + + ManagedMap attributes = new ManagedMap(); + + // Primitives + for (Element child : (List) DomUtils + .getChildElementsByTagName(element, "primitive")) { + BeanDefinitionBuilder childBuilder = BeanDefinitionBuilder + .genericBeanDefinition(PrimitiveSpecAttribute.class); + addCommonProperties(child, parserContext, childBuilder); + + String type = child.getAttribute("type"); + if (StringUtils.hasText(type)) + childBuilder.addPropertyValue("type", type); + + putInAttributes(attributes, child, + childBuilder.getBeanDefinition(), "primitive"); + } + + // Refs + for (Element refAttrElem : (List) DomUtils + .getChildElementsByTagName(element, "ref")) { + BeanDefinitionBuilder refAttrBuilder = BeanDefinitionBuilder + .genericBeanDefinition(RefSpecAttribute.class); + addCommonProperties(refAttrElem, parserContext, refAttrBuilder); + + String targetClassName = refAttrElem.getAttribute("targetClass"); + if (StringUtils.hasText(targetClassName)) + refAttrBuilder.addPropertyValue("targetClass", targetClassName); + + // Choices + Element choicesElem = DomUtils.getChildElementByTagName( + refAttrElem, "choices"); + if (choicesElem != null) { + List choices = DomUtils.getChildElementsByTagName( + choicesElem, "choice"); + ManagedList choiceBeans = new ManagedList(choices.size()); + for (Element choiceElem : choices) { + BeanDefinitionBuilder choiceBuilder = BeanDefinitionBuilder + .genericBeanDefinition(RefValueChoice.class); + choiceBuilder.addPropertyValue("name", + choiceElem.getAttribute("name")); + String desc = choiceElem.getAttribute("description"); + if (StringUtils.hasText(desc)) + choiceBuilder.addPropertyValue("description", desc); + + choiceBeans.add(choiceBuilder.getBeanDefinition()); + } + refAttrBuilder.addPropertyValue("choices", choiceBeans); + } + + putInAttributes(attributes, refAttrElem, + refAttrBuilder.getBeanDefinition(), "ref"); + } + + builder.addPropertyValue("attributes", attributes); + } + + protected void addCommonProperties(Element element, + ParserContext parserContext, BeanDefinitionBuilder specAttr) { + addBooleanProperty("isImmutable", specAttr, element); + addBooleanProperty("isConstant", specAttr, element); + addBooleanProperty("isHidden", specAttr, element); + addBooleanProperty("isParameter", specAttr, element); + addBooleanProperty("isFrozen", specAttr, element); + + Object value = NamespaceUtils.parseValue(element, parserContext, + specAttr.getBeanDefinition(), "value"); + if (value != null) + specAttr.addPropertyValue("value", value); + + } + + @SuppressWarnings("unchecked") + protected void putInAttributes(ManagedMap attributes, Element child, + BeanDefinition beanDefinition, String nature) { + String name = child.getAttribute("name"); + attributes.put(name, beanDefinition); + if (log.isTraceEnabled()) + log.debug("Added " + nature + " attribute " + name); + + } + + private void addBooleanProperty(String name, + BeanDefinitionBuilder specAttr, Element element) { + String bool = element.getAttribute(name); + if (StringUtils.hasText(bool)) + specAttr.addPropertyValue(name, Boolean.parseBoolean(bool)); + + } + + @Override + protected Class getBeanClass(Element element) { + return DefaultExecutionSpec.class; + } + + protected boolean shouldGenerateIdAsFallback() { + return false; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd new file mode 100644 index 000000000..8b31a60bf --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd new file mode 100644 index 000000000..a70798f2d --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd @@ -0,0 +1,402 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestData.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestData.java new file mode 100644 index 000000000..39a97f290 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestData.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import org.argeo.slc.test.TestData; + +public class BasicTestData implements TestData { + private Object expected; + private Object reached; + + public Object getExpected() { + return expected; + } + + public void setExpected(Object expected) { + this.expected = expected; + } + + public Object getReached() { + return reached; + } + + public void setReached(Object reached) { + this.reached = reached; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestDefinition.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestDefinition.java new file mode 100644 index 000000000..6b92135e8 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/BasicTestDefinition.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import org.argeo.slc.SlcException; +import org.argeo.slc.core.test.context.ContextUtils; +import org.argeo.slc.test.IncompatibleTestDataException; +import org.argeo.slc.test.TestData; +import org.argeo.slc.test.TestDefinition; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestRun; +import org.argeo.slc.test.TestStatus; +import org.argeo.slc.test.context.ContextAware; + +/** Understands basic test data and context aware test data. */ +public class BasicTestDefinition implements TestDefinition { + + public void execute(TestRun testRun) { + if (testRun. getTestData() instanceof BasicTestData) { + BasicTestData testData = testRun.getTestData(); + TestResult result = testRun.getTestResult(); + + if (result == null) + throw new SlcException("No test result defined."); + + try { + if (testData.getExpected().equals(testData.getReached())) { + result.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Reached and expected equals")); + } else { + result.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "Expected " + + testData.getExpected() + " but reached " + + testData.getReached())); + } + } catch (Exception e) { + result.addResultPart(new SimpleResultPart(TestStatus.ERROR, + "Could not compare", e)); + } + } else if (testRun. getTestData() instanceof ContextAware) { + TestData testData = testRun.getTestData(); + ContextUtils.compareReachedExpected((ContextAware) testData, + testRun.getTestResult()); + } else { + throw new IncompatibleTestDataException(testRun); + } + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleResultPart.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleResultPart.java new file mode 100644 index 000000000..8ad81af1c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleResultPart.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import java.io.Serializable; + +import org.argeo.slc.test.TestResultPart; +import org.argeo.slc.test.TestRun; +import org.argeo.slc.test.TestRunAware; +import org.argeo.slc.test.TestStatus; + +/** + *

+ * Basic implementation of a result part, implementing the standard three status + * approach for test results. + *

+ * + * @see TestStatus + */ +public class SimpleResultPart implements TestResultPart, TestStatus, + TestRunAware, Serializable { + private static final long serialVersionUID = 6669675957685071901L; + + private Long tid; + + private String testRunUuid; + + /** The status. Default to ERROR since it should always be explicitely set. */ + private Integer status = ERROR; + private String message; + private String exceptionMessage; + + public SimpleResultPart() { + } + + public SimpleResultPart(Integer status, String message) { + this(status, message, null); + } + + public SimpleResultPart(Integer status, String message, Exception exception) { + this.status = status; + this.message = message; + setException(exception); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getStatus() { + return status; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public void setException(Exception exception) { + if (exception == null) + return; + + StringBuffer buf = new StringBuffer(""); + buf.append(exception.toString()); + buf.append('\n'); + for (StackTraceElement elem : exception.getStackTrace()) { + buf.append('\t').append(elem.toString()).append('\n'); + } + + if (exception.getCause() != null) + addRootCause(buf, exception.getCause()); + + this.exceptionMessage = buf.toString(); + } + + protected void addRootCause(StringBuffer buf, Throwable cause) { + if (cause == null) + return; + + buf.append("Caused by: " + cause.getMessage()); + for (StackTraceElement elem : cause.getStackTrace()) { + buf.append('\t').append(elem.toString()).append('\n'); + } + + if (cause.getCause() != null) { + addRootCause(buf, cause.getCause()); + } + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(""); + buf.append(SlcTestUtils.statusToString(status)); + if (status == PASSED || status == FAILED) { + buf.append(' '); + } else if (status == ERROR) { + buf.append(" "); + } + buf.append(message); + return buf.toString(); + } + + /** @deprecated */ + Long getTid() { + return tid; + } + + /** @deprecated */ + void setTid(Long tid) { + this.tid = tid; + } + + public String getTestRunUuid() { + return testRunUuid; + } + + /** For ORM */ + public void setTestRunUuid(String testRunUuid) { + this.testRunUuid = testRunUuid; + } + + public void notifyTestRun(TestRun testRun) { + testRunUuid = testRun.getUuid(); + } + + public void setExceptionMessage(String exceptionMessage) { + this.exceptionMessage = exceptionMessage; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestResult.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestResult.java new file mode 100644 index 000000000..5fca5a9d7 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestResult.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.UUID; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.argeo.slc.SlcException; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestResultPart; +import org.argeo.slc.test.TestRun; + +/** + * Basic implementation of a test result containing only a list of result parts. + */ +public class SimpleTestResult implements TestResult { + private static Log log = LogFactory.getLog(SimpleTestResult.class); + + private String uuid; + private String currentTestRunUuid; + + private Boolean throwError = true; + + private Date closeDate; + private List parts = new Vector(); + + private Map attributes = new TreeMap(); + + public void addResultPart(TestResultPart part) { + if (throwError && part.getStatus() == ERROR) { + throw new SlcException( + "There was an error in the underlying test: " + + part.getExceptionMessage()); + } + parts.add(part); + if (log.isDebugEnabled()) + log.debug(part); + } + + public void close() { + parts.clear(); + closeDate = new Date(); + } + + public List getParts() { + return parts; + } + + public Date getCloseDate() { + return closeDate; + } + + public void setThrowError(Boolean throwError) { + this.throwError = throwError; + } + + public void notifyTestRun(TestRun testRun) { + currentTestRunUuid = testRun.getUuid(); + } + + public String getUuid() { + if (uuid == null) { + uuid = UUID.randomUUID().toString(); + } + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getCurrentTestRunUuid() { + return currentTestRunUuid; + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestRun.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestRun.java new file mode 100644 index 000000000..4f6a12f81 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/SimpleTestRun.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import java.util.UUID; + +import org.argeo.slc.deploy.DeployedSystem; +import org.argeo.slc.test.ExecutableTestRun; +import org.argeo.slc.test.TestData; +import org.argeo.slc.test.TestDefinition; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.WritableTestRun; + +/** + * A basic bean implementation of a WritableTestRun, holding + * references to the various parts of a test run. + */ +public class SimpleTestRun implements WritableTestRun, ExecutableTestRun { + private String uuid; + + // private String slcExecutionUuid; + // private String slcExecutionStepUuid; + + private DeployedSystem deployedSystem; + private TestData testData; + private TestDefinition testDefinition; + private TestResult testResult; + + /** Executes the underlying test definition. */ + public void run() { + uuid = UUID.randomUUID().toString(); + if (testResult != null) + testResult.notifyTestRun(this); + + testDefinition.execute(this); + } + + @SuppressWarnings("unchecked") + public T getDeployedSystem() { + return (T) deployedSystem; + } + + public void setDeployedSystem(DeployedSystem deployedSystem) { + this.deployedSystem = deployedSystem; + } + + @SuppressWarnings("unchecked") + public T getTestData() { + return (T) testData; + } + + public void setTestData(TestData testData) { + this.testData = testData; + } + + @SuppressWarnings("unchecked") + public T getTestDefinition() { + return (T) testDefinition; + } + + public void setTestDefinition(TestDefinition testDefinition) { + this.testDefinition = testDefinition; + } + + @SuppressWarnings("unchecked") + public T getTestResult() { + return (T) testResult; + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + // public String getSlcExecutionUuid() { + // return slcExecutionUuid; + // } + // + // public void setSlcExecutionUuid(String slcExecutionUuid) { + // this.slcExecutionUuid = slcExecutionUuid; + // } + // + // public String getSlcExecutionStepUuid() { + // return slcExecutionStepUuid; + // } + // + // public void setSlcExecutionStepUuid(String slcExecutionStepUuid) { + // this.slcExecutionStepUuid = slcExecutionStepUuid; + // } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/SlcTestUtils.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/SlcTestUtils.java new file mode 100644 index 000000000..c926a691d --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/SlcTestUtils.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import org.argeo.slc.SlcException; +import org.argeo.slc.test.TestStatus; + +public abstract class SlcTestUtils { + public static String statusToString(Integer status) { + if (status.equals(TestStatus.PASSED)) { + return TestStatus.STATUSSTR_PASSED; + } else if (status.equals(TestStatus.FAILED)) { + return TestStatus.STATUSSTR_FAILED; + } else if (status.equals(TestStatus.ERROR)) { + return TestStatus.STATUSSTR_ERROR; + } else { + throw new SlcException("Unrecognized status " + status); + } + } + + public static Integer stringToStatus(String statusStr) { + if (statusStr.equals(TestStatus.STATUSSTR_PASSED)) { + return TestStatus.PASSED; + } else if (statusStr.equals(TestStatus.STATUSSTR_FAILED)) { + return TestStatus.FAILED; + } else if (statusStr.equals(TestStatus.STATUSSTR_ERROR)) { + return TestStatus.ERROR; + } else { + throw new SlcException("Unrecognized status string " + statusStr); + } + } + + private SlcTestUtils() { + + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/TestDataUtils.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/TestDataUtils.java new file mode 100644 index 000000000..b32da3801 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/TestDataUtils.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test; + +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.test.TestData; +import org.argeo.slc.test.TestDataProvider; + +/** Utilities for dealing with test datas. */ +public class TestDataUtils { + /** Extracts the test data from the given provider. */ + public static T getFromProvider(Object obj, + Class clss, String key) { + if (obj instanceof TestDataProvider) { + TestDataProvider testDataProvider = (TestDataProvider) obj; + return testDataProvider.getTestData(clss, key); + } else { + throw new UnsupportedException("test data provider", obj); + } + } + + /** + * Extracts the test data from the given provider using null + * as key. + */ + public static T getFromProvider(Object obj, + Class clss) { + return getFromProvider(obj, clss, null); + } + + /** + * Returns it self after making the proper checks. Used for test data being + * their own data providers. + */ + @SuppressWarnings("unchecked") + public static T getItSelf(Class clss, + TestData testDataObject) { + if (clss.isAssignableFrom(testDataObject.getClass())) { + return (T) testDataObject; + } else { + throw new UnsupportedException("test data", testDataObject); + } + + } + + /** Makes sure this is an utility class. */ + private TestDataUtils() { + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/context/ContextUtils.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/ContextUtils.java new file mode 100644 index 000000000..f62fb5ca3 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/ContextUtils.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestStatus; +import org.argeo.slc.test.context.ContextAware; +import org.argeo.slc.test.context.ParentContextAware; + +/** Utilities for comparing and synchronising contexts. */ +public class ContextUtils { + private final static Log log = LogFactory.getLog(ContextUtils.class); + + public static void compareReachedExpected(ContextAware contextAware, + TestResult testResult) { + for (String key : contextAware.getExpectedValues().keySet()) { + + // Compare expected values with reached ones + Object expectedValue = contextAware.getExpectedValues().get(key); + + if (expectedValue.toString().equals( + contextAware.getContextSkipFlag())) { + if (log.isDebugEnabled()) + log.debug("Skipped check for key '" + key + "'"); + continue; + } + + if (contextAware.getValues().containsKey(key)) { + Object reachedValue = contextAware.getValues().get(key); + + if (expectedValue.equals(contextAware.getContextAnyFlag())) { + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Expected any value for key '" + + key + "'")); + } else if (expectedValue.equals(reachedValue)) { + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Values matched for key '" + key + + "'")); + } else { + testResult.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "Mismatch for key '" + key + + "': expected '" + expectedValue + + "' but reached '" + reachedValue + "'")); + } + } else { + testResult.addResultPart(new SimpleResultPart( + TestStatus.FAILED, "No value reached for key '" + key + + "'")); + } + } + } + + /** + * Makes sure that all children and sub-children of parent share the same + * maps for values and expected values. + */ + public static void synchronize(ParentContextAware parent) { + Map expectedValuesCommon = new TreeMap( + parent.getExpectedValues()); + synchronize(parent, expectedValuesCommon); + if (log.isDebugEnabled()) + log.debug("Synchronized context " + parent); + + } + + private static void synchronize(ParentContextAware parent, + Map expectedValuesCommon) { + for (ContextAware child : parent.getChildContexts()) { + // Values + putNotContained(parent.getValues(), child.getValues()); + child.setValues(parent.getValues()); + + // Expected Values + // Expected values reference is not overridden: each child has its + // own expected values map. + overrideContained(expectedValuesCommon, child.getExpectedValues()); + + // Creates a new Map in order not to disturb other context using the + // same keys + Map expectedValuesCommonChild = new TreeMap( + expectedValuesCommon); + putNotContained(expectedValuesCommonChild, + child.getExpectedValues()); + + if (child instanceof ParentContextAware) { + // Recursive sync + synchronize((ParentContextAware) child, + expectedValuesCommonChild); + } + } + + } + + /** + * Put into common map the values from child map which are not already + * defined in common map. + */ + public static void putNotContained(Map commonMap, + Map childMap) { + for (String key : childMap.keySet()) { + if (!commonMap.containsKey(key)) { + commonMap.put(key, childMap.get(key)); + } + } + } + + /** Overrides child map values with the values already set in common map */ + public static void overrideContained(Map commonMap, + Map childMap) { + for (String key : childMap.keySet()) { + if (commonMap.containsKey(key)) { + childMap.put(key, commonMap.get(key)); + } + } + } + + /** Makes sure this cannot be instantiated. */ + private ContextUtils() { + + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/context/DefaultContextTestData.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/DefaultContextTestData.java new file mode 100644 index 000000000..ca0bf5ffb --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/DefaultContextTestData.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import org.argeo.slc.core.test.TestDataUtils; +import org.argeo.slc.test.TestData; +import org.argeo.slc.test.TestDataProvider; + +public class DefaultContextTestData extends SimpleContextAware implements + TestData, TestDataProvider { + + public T getTestData(Class clss, String key) { + return TestDataUtils.getItSelf(clss, this); + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleContextAware.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleContextAware.java new file mode 100644 index 000000000..8ed38720c --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleContextAware.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import java.util.Map; +import java.util.TreeMap; + +import org.springframework.beans.factory.InitializingBean; + +import org.argeo.slc.SlcException; +import org.argeo.slc.test.context.ContextAware; +import org.argeo.slc.test.context.ParentContextAware; + +public class SimpleContextAware implements ContextAware, InitializingBean { + private ParentContextAware parentContext; + + private Map values = new TreeMap(); + private Map expectedValues = new TreeMap(); + + private String contextSkipFlag = DEFAULT_SKIP_FLAG; + private String contextAnyFlag = DEFAULT_ANY_FLAG; + + public Map getValues() { + return values; + } + + public void setValues(Map values) { + this.values = values; + } + + public Map getExpectedValues() { + return expectedValues; + } + + public void setExpectedValues(Map expectedValues) { + this.expectedValues = expectedValues; + } + + /** Used to add this context as a child by setting a property. */ + public void setParentContext(ParentContextAware parentContextAware) { + if (parentContext != null) + throw new SlcException("Parent context already set"); + this.parentContext = parentContextAware; + this.parentContext.addChildContext(this); + } + + protected ParentContextAware getParentContext() { + return parentContext; + } + + public void afterPropertiesSet() throws Exception { + if (parentContext != null) { + ContextUtils.synchronize(parentContext); + } + } + + public String getContextSkipFlag() { + return contextSkipFlag; + } + + public void setContextSkipFlag(String contextSkipFlag) { + this.contextSkipFlag = contextSkipFlag; + } + + public String getContextAnyFlag() { + return contextAnyFlag; + } + + public void setContextAnyFlag(String contextAnyFlag) { + this.contextAnyFlag = contextAnyFlag; + } + +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java new file mode 100644 index 000000000..b8abf7fde --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.core.test.context; + +import java.util.Collection; +import java.util.List; +import java.util.Vector; + +import org.argeo.slc.test.context.ContextAware; +import org.argeo.slc.test.context.ParentContextAware; +import org.springframework.beans.factory.InitializingBean; + +public class SimpleParentContextAware extends SimpleContextAware implements + ParentContextAware, InitializingBean { + private List children = new Vector(); + + public Collection getChildContexts() { + return children; + } + + public void addChildContext(ContextAware contextAware) { + children.add(contextAware); + } + + @Override + public void afterPropertiesSet() throws Exception { + if (getParentContext() != null) { + // If has a parent, sync it. + super.afterPropertiesSet(); + } else { + if (children.size() > 0) { + // No need to synchronize if no children + ContextUtils.synchronize(this); + } + } + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/context/package.html b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/package.html new file mode 100644 index 000000000..cd08d63f3 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/context/package.html @@ -0,0 +1,6 @@ + + + +Context variables to be passed between parts of tests. + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/package.html b/org.argeo.slc.core/src/org/argeo/slc/core/test/package.html new file mode 100644 index 000000000..c70d2d151 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/package.html @@ -0,0 +1,6 @@ + + + +SLC Test: test of software systems. + + \ No newline at end of file diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/test/spring.xml b/org.argeo.slc.core/src/org/argeo/slc/core/test/spring.xml new file mode 100644 index 000000000..31cf67167 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/core/test/spring.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4063097e1..e474716d1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ org.argeo.slc.api + org.argeo.slc.core diff --git a/runtime/org.argeo.slc.core/META-INF/spring.handlers b/runtime/org.argeo.slc.core/META-INF/spring.handlers deleted file mode 100644 index 417a952e8..000000000 --- a/runtime/org.argeo.slc.core/META-INF/spring.handlers +++ /dev/null @@ -1 +0,0 @@ -http\://www.argeo.org/schema/slc-flow=org.argeo.slc.core.execution.xml.FlowNamespaceHandler \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/META-INF/spring.schemas b/runtime/org.argeo.slc.core/META-INF/spring.schemas deleted file mode 100644 index 229d4c5f6..000000000 --- a/runtime/org.argeo.slc.core/META-INF/spring.schemas +++ /dev/null @@ -1,3 +0,0 @@ -http\://www.argeo.org/schema/slc-flow.xsd=org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd -http\://www.argeo.org/schema/slc-flow-1.2.xsd=org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd -http\://www.argeo.org/schema/slc-flow-0.12.xsd=org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/Attachment.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/Attachment.java deleted file mode 100644 index ecde0b936..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/Attachment.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -public interface Attachment { - public String getUuid(); - - public void setUuid(String uuid); - - public String getName(); - - public String getContentType(); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentUploader.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentUploader.java deleted file mode 100644 index eb484c92c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentUploader.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -import org.springframework.core.io.Resource; - -public interface AttachmentUploader { - public void upload(Attachment attachment, Resource resource); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsEnabled.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsEnabled.java deleted file mode 100644 index 780a6a483..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsEnabled.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -public interface AttachmentsEnabled { - public void addAttachment(Attachment attachment); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java deleted file mode 100644 index 2214afabf..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/AttachmentsStorage.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -import java.io.InputStream; -import java.io.OutputStream; - -public interface AttachmentsStorage { - public void retrieveAttachment(Attachment attachment, - OutputStream outputStream); - - /** Does NOT close the provided input stream. */ - public void storeAttachment(Attachment attachment, InputStream inputStream); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java deleted file mode 100644 index 3b7e62dac..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/FileAttachmentsStorage.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; - -public class FileAttachmentsStorage implements AttachmentsStorage, - AttachmentUploader, InitializingBean { - private final static Log log = LogFactory - .getLog(FileAttachmentsStorage.class); - - private File attachmentsDirectory; - - private String attachmentsTocFileName = "attachmentsToc.csv"; - - private DateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd"); - private DateFormat dateFormatTime = new SimpleDateFormat("HH:mm:ss"); - - public void afterPropertiesSet() { - if (attachmentsDirectory == null) { - - String osgiInstanceArea = System.getProperty("osgi.instance.area"); - if (osgiInstanceArea != null) { - if (osgiInstanceArea.startsWith("file:")) - osgiInstanceArea = osgiInstanceArea.substring("file:" - .length()); - attachmentsDirectory = new File(osgiInstanceArea - + File.separator + "slcAttachments"); - } - - if (attachmentsDirectory == null) { - String tempDir = System.getProperty("java.io.tmpdir"); - attachmentsDirectory = new File(tempDir + File.separator - + "slcAttachments"); - } - } - if (!attachmentsDirectory.exists()) - attachmentsDirectory.mkdirs(); - if (log.isDebugEnabled()) - log.debug("File attachment storage initialized in directory " - + attachmentsDirectory); - } - - public void retrieveAttachment(Attachment attachment, - OutputStream outputStream) { - File file = getFile(attachment); - InputStream in = null; - try { - byte[] buffer = new byte[1024 * 1024]; - in = new FileInputStream(file); - int read = -1; - while ((read = in.read(buffer)) >= 0) { - outputStream.write(buffer, 0, read); - } - if (log.isTraceEnabled()) - log.trace("Read " + attachment + " from " + file); - } catch (IOException e) { - throw new SlcException("Cannot write attachment " + attachment - + " to " + file, e); - } finally { - IOUtils.closeQuietly(in); - } - } - - public void storeAttachment(Attachment attachment, InputStream inputStream) { - File file = getFile(attachment); - FileOutputStream out = null; - try { - byte[] buffer = new byte[1024 * 1024]; - out = new FileOutputStream(file); - int read = -1; - while ((read = inputStream.read(buffer)) >= 0) { - out.write(buffer, 0, read); - } - if (log.isTraceEnabled()) - log.trace("Wrote " + attachment + " to " + file); - updateAttachmentToc(attachment, file); - } catch (IOException e) { - throw new SlcException("Cannot write attachment " + attachment - + " to " + file, e); - } finally { - IOUtils.closeQuietly(out); - } - - } - - public void upload(Attachment attachment, Resource resource) { - try { - storeAttachment(attachment, resource.getInputStream()); - } catch (IOException e) { - throw new SlcException("Cannot upload attachment " + attachment, e); - } - } - - /** For monitoring purposes only */ - protected void updateAttachmentToc(Attachment attachment, File file) { - Date date = new Date(file.lastModified()); - FileWriter writer = null; - try { - writer = new FileWriter(attachmentsDirectory + File.separator - + attachmentsTocFileName, true); - writer.append(dateFormatDay.format(date)); - writer.append(','); - writer.append(dateFormatTime.format(date)); - writer.append(','); - writer.append(attachment.getUuid()); - writer.append(','); - writer.append(attachment.getName()); - writer.append(','); - writer.append(attachment.getContentType()); - writer.append(','); - writer.append(Long.toString(file.length())); - writer.append(','); - writer.append(file.getCanonicalPath()); - writer.append('\n'); - } catch (IOException e) { - log.warn("Could not update attachments TOC for " + attachment - + " and file " + file, e); - } finally { - IOUtils.closeQuietly(writer); - } - - } - - protected File getFile(Attachment attachment) { - File file = new File(attachmentsDirectory + File.separator - + attachment.getUuid()); - return file; - } - - public void setAttachmentsDirectory(File attachmentsDirectory) { - this.attachmentsDirectory = attachmentsDirectory; - } - - public void setAttachmentsTocFileName(String attachmentsTocFileName) { - this.attachmentsTocFileName = attachmentsTocFileName; - } - - public void setDateFormatDay(DateFormat dateFormatDay) { - this.dateFormatDay = dateFormatDay; - } - - public void setDateFormatTime(DateFormat dateFormatTime) { - this.dateFormatTime = dateFormatTime; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java deleted file mode 100644 index 6248dd71e..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/attachment/SimpleAttachment.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.attachment; - -import java.io.Serializable; -import java.util.UUID; - -public class SimpleAttachment implements Attachment, Serializable { - private static final long serialVersionUID = 6615155908800610606L; - private String uuid = UUID.randomUUID().toString(); - private String name; - private String contentType = ""; - - public SimpleAttachment() { - } - - public SimpleAttachment(String uuid, String name, String contentType) { - super(); - this.uuid = uuid; - this.name = name; - this.contentType = contentType; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getContentType() { - return contentType; - } - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - public String toString() { - return "Attachment #" + uuid + "(" + name + ", " + contentType + ")"; - } - - public boolean equals(Object obj) { - if (obj instanceof Attachment) { - Attachment attachment = (Attachment) obj; - if (uuid != null && attachment.getUuid() != null) - return uuid.equals(attachment.getUuid()); - - if (name != null && attachment.getName() != null) - return name.equals(attachment.getName()); - - return hashCode() == attachment.hashCode(); - } - return false; - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java deleted file mode 100644 index 4ebbe92a4..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.build; - -import java.io.IOException; -import java.io.InputStream; - -import org.argeo.slc.SlcException; -import org.argeo.slc.StreamReadable; -import org.argeo.slc.build.Distribution; -import org.springframework.core.io.Resource; - -/** A software distribution archive accessible via a {@link Resource}. */ -public class ResourceDistribution implements Distribution, StreamReadable { - private Resource resource; - - public ResourceDistribution() { - } - - public ResourceDistribution(Resource location) { - this.resource = location; - } - - public String getDistributionId() { - return resource.toString(); - } - - public Resource getResource() { - return resource; - } - - public void setResource(Resource resource) { - this.resource = resource; - } - - public InputStream getInputStream() { - try { - return resource.getInputStream(); - } catch (IOException e) { - throw new SlcException("Cannot get input stream", e); - } - } - - @Override - public String toString() { - return resource.toString(); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java deleted file mode 100644 index c11dc00ea..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionDistributionId.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.build; - -import java.util.StringTokenizer; - -/** - *

- * An implementation of the distribution id using the standard - * Major.Minor.Release notation. And additional arbitrary string can also be - * added. - *

- * - *

- * Examples:
- * 0.2.6
- * 2.4.12.RC1 - *

- */ -public class VersionDistributionId { - - private Integer major; - private Integer minor; - private Integer release; - private String additional; - - /** Parse the provided string in order to set the various components. */ - public void setVersionString(String str) { - StringTokenizer st = new StringTokenizer(str, "."); - if (st.hasMoreTokens()) - major = Integer.parseInt(st.nextToken()); - if (st.hasMoreTokens()) - minor = Integer.parseInt(st.nextToken()); - if (st.hasMoreTokens()) - release = Integer.parseInt(st.nextToken()); - if (st.hasMoreTokens()) - additional = st.nextToken(); - } - - public Integer getMajor() { - return major; - } - - public void setMajor(Integer major) { - this.major = major; - } - - public Integer getMinor() { - return minor; - } - - public void setMinor(Integer minor) { - this.minor = minor; - } - - public Integer getRelease() { - return release; - } - - public void setRelease(Integer release) { - this.release = release; - } - - public String getAdditional() { - return additional; - } - - public void setAdditional(String additional) { - this.additional = additional; - } - - @Override - public boolean equals(Object obj) { - // TODO Auto-generated method stub - return super.equals(obj); - } - - @Override - public String toString() { - return major + "." + minor + "." + release - + (additional != null ? "." + additional : ""); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java deleted file mode 100644 index 52307ec67..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.build; - -import org.argeo.slc.NameVersion; -import org.springframework.core.io.Resource; - -/** - * The distribution of a software package (jar, zip, RPM, etc.) which is - * versioned. The archive itself is accessible via a {@link Resource}. - */ -public class VersionedResourceDistribution extends ResourceDistribution - implements NameVersion { - private String name; - private String version; - - public VersionedResourceDistribution() { - super(); - } - - public VersionedResourceDistribution(NameVersion nameVersion, - Resource resource) { - this(nameVersion.getName(), nameVersion.getVersion(), resource); - } - - public VersionedResourceDistribution(String name, String version, - Resource resource) { - super(resource); - this.name = name; - this.version = version; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/package.html b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/package.html deleted file mode 100644 index 5da205278..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -SLC Build: building of software systems. - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DefaultResourceSet.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DefaultResourceSet.java deleted file mode 100644 index abdcfeec3..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DefaultResourceSet.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; - -public class DefaultResourceSet implements ResourceLoaderAware, - InitializingBean, ResourceSet { - private final static Log log = LogFactory.getLog(DefaultResourceSet.class); - public final static String DEFAULT_EXCLUDES = "**/.svn/**"; - - private String base; - private String include; - private List includes = new ArrayList(); - private String exclude; - private List excludes = new ArrayList(); - private Boolean useDefaultExcludes = true; - private ResourcePatternResolver resourcePatternResolver; - private PathMatcher excludePathMatcher = new AntPathMatcher(); - - private ResourceLoader resourceLoader; - - /** List the resources, identified by their relative path. */ - public Map listResources() { - try { - Map res = new TreeMap(); - if (base == null) - return res; - String baseResUrl = getResourceLoaderToUse().getResource(base) - .getURL().toString(); - for (String includePattern : includes) - processInclude(res, includePattern, baseResUrl); - return res; - } catch (IOException e) { - throw new SlcException("Cannot list resource from " + base, e); - } - } - - protected void processInclude(Map res, String include, - String baseResUrl) throws IOException { - String pattern = base + "/" + include; - if (log.isTraceEnabled()) - log.trace("Look for resources with pattern '" + pattern - + "' in base url " + baseResUrl); - Resource[] resources = resourcePatternResolver.getResources(pattern); - resources: for (Resource resource : resources) { - String url = resource.getURL().toString(); - String relPath = url.substring(baseResUrl.length()); - - // skip dir - if (relPath.charAt(relPath.length() - 1) == '/') { - if (log.isTraceEnabled()) - log.trace("Skip directory " + relPath + "=" + resource); - continue resources; - } - - // make sure there is not starting '/' - if (relPath.charAt(0) == '/') - relPath = relPath.substring(1); - - // skip excludes - for (String exclude : excludes) - if (excludePathMatcher.match(exclude, relPath)) { - if (log.isTraceEnabled()) - log.trace("Exclude " + relPath + "=" + resource); - continue resources; - } - - // check if already exists - if (res.containsKey(relPath)) - log.warn(relPath + " already matched by " + res.get(relPath) - + ", " + resource + " will override it."); - - // store the marched resource - res.put(relPath, resource); - if (log.isTraceEnabled()) - log.trace(relPath + "=" + resource); - } - - } - - public void afterPropertiesSet() throws Exception { - if (resourcePatternResolver == null) - resourcePatternResolver = new PathMatchingResourcePatternResolver( - getResourceLoaderToUse()); - if (include != null) - addCommaSeparatedToList(include, includes); - if (exclude != null) - addCommaSeparatedToList(exclude, excludes); - - if (includes.size() == 0) - includes.add("**"); - - if (useDefaultExcludes) - addCommaSeparatedToList(DEFAULT_EXCLUDES, excludes); - } - - private void addCommaSeparatedToList(String str, List lst) { - StringTokenizer st = new StringTokenizer(str, ","); - while (st.hasMoreTokens()) { - String token = st.nextToken(); - if (!lst.contains(token)) - lst.add(token); - } - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - /** - * Can be overridden in order to provide the proper resource loader used to - * resolve resources. - */ - public ResourceLoader getResourceLoaderToUse() { - return resourceLoader; - } - - public void setBase(String base) { - this.base = base; - } - - public void setInclude(String include) { - this.include = include; - } - - public void setIncludes(List includes) { - this.includes = includes; - } - - public void setExclude(String exclude) { - this.exclude = exclude; - } - - public void setExcludes(List excludes) { - this.excludes = excludes; - } - - public void setUseDefaultExcludes(Boolean useDefaultExcludes) { - this.useDefaultExcludes = useDefaultExcludes; - } - - public void setExcludePathMatcher(PathMatcher excludePathMatcher) { - this.excludePathMatcher = excludePathMatcher; - } - - public void setResourcePatternResolver( - ResourcePatternResolver resourcePatternResolver) { - this.resourcePatternResolver = resourcePatternResolver; - } - - public ResourcePatternResolver getResourcePatternResolver() { - return resourcePatternResolver; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DigestCheck.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DigestCheck.java deleted file mode 100644 index 5df54232c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/DigestCheck.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.io.File; -import java.io.IOException; - -import org.argeo.slc.SlcException; -import org.argeo.util.security.DigestUtils; -import org.springframework.core.io.Resource; - -/** Add Spring capabilities to {@link DigestUtils} */ -public class DigestCheck extends DigestUtils { - public static String digest(String algorithm, Resource resource) { - try { - File file = resource.getFile(); - return digest(algorithm, file); - } catch (IOException e) { - try { - return digest(algorithm, resource.getInputStream()); - } catch (IOException e1) { - throw new SlcException("Cannot digest " + resource - + " with algorithm " + algorithm, e); - } - } - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/LocalFilesDeployment.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/LocalFilesDeployment.java deleted file mode 100644 index 79ad83597..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/LocalFilesDeployment.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.argeo.slc.SlcException; -import org.springframework.core.io.Resource; - -public class LocalFilesDeployment implements Runnable { - private String targetBase = ""; - private ResourceSet resourceSet; - - public LocalFilesDeployment() { - } - - public LocalFilesDeployment(ResourceSet resourceSet) { - this.resourceSet = resourceSet; - } - - public void run() { - Map resources = resourceSet.listResources(); - for (String relPath : resources.keySet()) { - File targetFile = new File(targetBase + File.separator + relPath); - File parentDir = targetFile.getParentFile(); - if (!parentDir.exists()) - parentDir.mkdirs(); - - Resource resource = resources.get(relPath); - - InputStream in = null; - OutputStream out = null; - try { - in = resource.getInputStream(); - out = FileUtils.openOutputStream(targetFile); - IOUtils.copy(in, out); - } catch (IOException e) { - throw new SlcException("Cannot extract " + resource + " to " - + targetFile, e); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - } - - public void setTargetBase(String targetBase) { - this.targetBase = targetBase; - } - - public void setResourceSet(ResourceSet resourceSet) { - this.resourceSet = resourceSet; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/MultiResourceSet.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/MultiResourceSet.java deleted file mode 100644 index 8da17ba42..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/MultiResourceSet.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.core.io.Resource; - -public class MultiResourceSet implements ResourceSet { - private List resourceSets = new ArrayList(); - - public Map listResources() { - Map res = new HashMap(); - for (ResourceSet resourceSet : resourceSets) { - res.putAll(resourceSet.listResources()); - } - return res; - } - - /** Last listed override previous for the same relative paths. */ - public void setResourceSets(List resourceSets) { - this.resourceSets = resourceSets; - } - - public List getResourceSets() { - return resourceSets; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/ResourceSet.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/ResourceSet.java deleted file mode 100644 index 01c01abae..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/ResourceSet.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.util.Map; - -import org.springframework.core.io.Resource; - -public interface ResourceSet { - /** - * List the resources, identified by their relative path. Relative paths - * must NOT start with a '/'. - */ - public Map listResources(); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java deleted file mode 100644 index 5a5b8259f..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/SimpleExecutables.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.io.File; -import java.util.Map; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.build.Distribution; -import org.argeo.slc.deploy.DeploymentData; -import org.argeo.slc.deploy.InstalledExecutables; -import org.argeo.slc.deploy.TargetData; - -public class SimpleExecutables implements InstalledExecutables { - private final static Log log = LogFactory.getLog(SimpleExecutables.class); - - private String baseDir; - private Map paths = new TreeMap(); - - private Distribution distribution; - - public String getExecutablePath(String key) { - String path = paths.get(key); - if (path == null) { - if (log.isDebugEnabled()) - log.debug("No executable path found for key " + key - + ", using the key as executable name."); - path = key; - } - - if (baseDir != null) - path = baseDir + File.separator + path; - return path; - } - - public String getDeployedSystemId() { - // TODO Auto-generated method stub - return null; - } - - public DeploymentData getDeploymentData() { - // TODO Auto-generated method stub - return null; - } - - public Distribution getDistribution() { - return distribution; - } - - public TargetData getTargetData() { - // TODO Auto-generated method stub - return null; - } - - public String getBaseDir() { - return baseDir; - } - - public void setBaseDir(String baseDir) { - this.baseDir = baseDir; - } - - public Map getPaths() { - return paths; - } - - public void setPaths(Map paths) { - this.paths = paths; - } - - public void setDistribution(Distribution distribution) { - this.distribution = distribution; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/VersionedDirSync.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/VersionedDirSync.java deleted file mode 100644 index 13d254366..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/VersionedDirSync.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.io.File; -import java.io.IOException; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.deploy.VersioningDriver; - -/** - * Synchronizes an URL to a local directory, taking into account versioning - * information if possible. - */ -public class VersionedDirSync implements Runnable { - private final static Log log = LogFactory.getLog(VersionedDirSync.class); - - private VersioningDriver versioningDriver; - private File dir; - private String url; - private Boolean clean = false; - - private Boolean changed = null; - - public void run() { - changed = null; - if (clean) { - try { - log.info("Clean " + dir); - FileUtils.deleteDirectory(dir); - } catch (IOException e) { - throw new SlcException("Cannot delete checkout directory " - + dir, e); - } - dir.mkdirs(); - } - log.info("Checkout " + url + " to " + dir); - changed = versioningDriver.checkout(url, dir, true); - if (log.isDebugEnabled()) - log.debug("Synchronized " + url + " to " + dir); - } - - public void setVersioningDriver(VersioningDriver versioningDriver) { - this.versioningDriver = versioningDriver; - } - - public void setDir(File dir) { - this.dir = dir; - } - - public void setUrl(String url) { - this.url = url; - } - - /** Delete before checkout */ - public void setClean(Boolean clean) { - this.clean = clean; - } - - /** Whether last call has changed the directory */ - public Boolean getChanged() { - if (changed == null) - throw new SlcException("Sync has not run"); - return changed; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/package.html b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/package.html deleted file mode 100644 index f3a4c5bd6..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/deploy/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -SLC Deploy: deployment of software systems. - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java deleted file mode 100644 index dc55b40f9..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionFlowGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; -import org.springframework.core.Ordered; -import org.springframework.core.PriorityOrdered; - -public abstract class AbstractExecutionFlowGenerator implements - BeanFactoryPostProcessor, PriorityOrdered { - private final Log log = LogFactory.getLog(getClass()); - - protected abstract Map createExecutionFlowDefinitions( - ConfigurableListableBeanFactory beanFactory); - - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (!(beanFactory instanceof BeanDefinitionRegistry)) { - throw new SlcException("Can only work on " - + BeanDefinitionRegistry.class); - } - - Map definitions = createExecutionFlowDefinitions(beanFactory); - - for (String beanName : definitions.keySet()) { - if (log.isTraceEnabled()) - log.debug("Registering execution flow " + beanName); - ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition( - beanName, definitions.get(beanName)); - } - } - - protected GenericBeanDefinition createDefaultFlowDefinition( - List executables) { - GenericBeanDefinition bd = new GenericBeanDefinition(); - bd.setBeanClass(DefaultExecutionFlow.class); - - MutablePropertyValues mpv = new MutablePropertyValues(); - mpv.addPropertyValue("executables", executables); - - bd.setPropertyValues(mpv); - return bd; - } - - public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java deleted file mode 100644 index 1a07313f0..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionModulesManager.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; -import org.argeo.slc.execution.ExecutionModulesManager; -import org.argeo.slc.execution.RealizedFlow; - -/** Provides the base feature of an execution module manager. */ -public abstract class AbstractExecutionModulesManager implements - ExecutionModulesManager { - private final static Log log = LogFactory - .getLog(AbstractExecutionModulesManager.class); - -// private List filteredNotifiers = Collections -// .synchronizedList(new ArrayList()); - - protected abstract ExecutionFlow findExecutionFlow(String moduleName, - String moduleVersion, String flowName); - - protected abstract ExecutionContext findExecutionContext(String moduleName, - String moduleVersion); - - protected abstract ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter( - String moduleName, String moduleVersion); - - public void execute(RealizedFlow realizedFlow) { - if (log.isTraceEnabled()) - log.trace("Executing " + realizedFlow); - - String moduleName = realizedFlow.getModuleName(); - String moduleVersion = realizedFlow.getModuleVersion(); - - Map variablesToAdd = getExecutionFlowDescriptorConverter( - moduleName, moduleVersion).convertValues( - realizedFlow.getFlowDescriptor()); - ExecutionContext executionContext = findExecutionContext(moduleName, - moduleVersion); - for (String key : variablesToAdd.keySet()) - executionContext.setVariable(key, variablesToAdd.get(key)); - - ExecutionFlow flow = findExecutionFlow(moduleName, moduleVersion, - realizedFlow.getFlowDescriptor().getName()); - - // - // Actually runs the flow, IN THIS THREAD - // - flow.run(); - // - // - // - } - -// public void dispatchUpdateStatus(ExecutionProcess process, -// String oldStatus, String newStatus) { -// // filtered notifiers -// for (Iterator it = filteredNotifiers.iterator(); it -// .hasNext();) { -// FilteredNotifier filteredNotifier = it.next(); -// if (filteredNotifier.receiveFrom(process)) -// filteredNotifier.getNotifier().updateStatus(process, oldStatus, -// newStatus); -// } -// -// } - -// public void dispatchAddSteps(ExecutionProcess process, -// List steps) { -// process.addSteps(steps); -// for (Iterator it = filteredNotifiers.iterator(); it -// .hasNext();) { -// FilteredNotifier filteredNotifier = it.next(); -// if (filteredNotifier.receiveFrom(process)) -// filteredNotifier.getNotifier().addSteps(process, steps); -// } -// } - -// public void registerProcessNotifier(ExecutionProcessNotifier notifier, -// Map properties) { -// filteredNotifiers.add(new FilteredNotifier(notifier, properties)); -// } -// -// public void unregisterProcessNotifier(ExecutionProcessNotifier notifier, -// Map properties) { -// filteredNotifiers.remove(notifier); -// } - -// protected class FilteredNotifier { -// private final ExecutionProcessNotifier notifier; -// private final String processId; -// -// public FilteredNotifier(ExecutionProcessNotifier notifier, -// Map properties) { -// super(); -// this.notifier = notifier; -// if (properties == null) -// properties = new HashMap(); -// if (properties.containsKey(SLC_PROCESS_ID)) -// processId = properties.get(SLC_PROCESS_ID); -// else -// processId = null; -// } -// -// /** -// * Whether event from this process should be received by this listener. -// */ -// public Boolean receiveFrom(ExecutionProcess process) { -// if (processId != null) -// if (process.getUuid().equals(processId)) -// return true; -// else -// return false; -// return true; -// } -// -// @Override -// public int hashCode() { -// return notifier.hashCode(); -// } -// -// @Override -// public boolean equals(Object obj) { -// if (obj instanceof FilteredNotifier) { -// FilteredNotifier fn = (FilteredNotifier) obj; -// return notifier.equals(fn.notifier); -// } else if (obj instanceof ExecutionProcessNotifier) { -// ExecutionProcessNotifier epn = (ExecutionProcessNotifier) obj; -// return notifier.equals(epn); -// } else -// return false; -// } -// -// public ExecutionProcessNotifier getNotifier() { -// return notifier; -// } -// -// } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionValue.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionValue.java deleted file mode 100644 index 131ffec75..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionValue.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.Serializable; - -/** Value to be used by an execution */ -public abstract class AbstractExecutionValue implements Serializable { - private static final long serialVersionUID = 1558444746120706961L; -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpecAttribute.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpecAttribute.java deleted file mode 100644 index 109c0335e..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpecAttribute.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.Serializable; - -import org.argeo.slc.execution.ExecutionSpecAttribute; - -/** Canonical implementation of the execution spec attribute booleans. */ -public abstract class AbstractSpecAttribute implements ExecutionSpecAttribute, - Serializable { - private static final long serialVersionUID = 6494963738891709440L; - private Boolean isImmutable = false; - private Boolean isConstant = false; - private Boolean isHidden = false; - - private String description; - - /** Has to be set at instantiation */ - public Boolean getIsImmutable() { - return isImmutable; - } - - public void setIsImmutable(Boolean isImmutable) { - this.isImmutable = isImmutable; - } - - /** Cannot be overridden at runtime */ - public Boolean getIsConstant() { - return isConstant; - } - - public void setIsConstant(Boolean isConstant) { - this.isConstant = isConstant; - } - - /** Should not be shown to the end user */ - public Boolean getIsHidden() { - return isHidden; - } - - public void setIsHidden(Boolean isHidden) { - this.isHidden = isHidden; - } - - /* - * DEPRECATED - */ - /** @deprecated use {@link #getIsImmutable()} instead */ - public Boolean getIsParameter() { - return isImmutable; - } - - /** @deprecated use {@link #getIsConstant()} instead */ - public Boolean getIsFrozen() { - return isConstant; - } - - /** @deprecated use {@link #setIsImmutable(Boolean)} instead */ - public void setIsParameter(Boolean isParameter) { - this.isImmutable = isParameter; - } - - /** @deprecated use {@link #setIsConstant(Boolean)} instead */ - public void setIsFrozen(Boolean isFrozen) { - this.isConstant = isFrozen; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getDescription() { - return description; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java deleted file mode 100644 index b2252f6a2..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.argeo.slc.execution.ExecutionModule; - -@Deprecated -public abstract class AbstractSpringExecutionModule implements ExecutionModule - { -/* - protected ApplicationContext applicationContext; - - protected ExecutionContext executionContext; - - protected ExecutionFlowDescriptorConverter descriptorConverter = new DefaultDescriptorConverter(); - - public ExecutionModuleDescriptor getDescriptor() { - ExecutionModuleDescriptor md = new ExecutionModuleDescriptor(); - md.setName(getName()); - md.setVersion(getVersion()); - - Map executionFlows = listFlows(); - for (String name : executionFlows.keySet()) { - ExecutionFlow executionFlow = executionFlows.get(name); - - Assert.notNull(executionFlow.getName()); - Assert.state(name.equals(executionFlow.getName())); - - ExecutionSpec executionSpec = executionFlow.getExecutionSpec(); - Assert.notNull(executionSpec); - Assert.notNull(executionSpec.getName()); - - Map values = new TreeMap(); - for (String key : executionSpec.getAttributes().keySet()) { - ExecutionSpecAttribute attribute = executionSpec - .getAttributes().get(key); - - if (executionFlow.isSetAsParameter(key)) { - Object value = executionFlow.getParameter(key); - if (attribute instanceof PrimitiveSpecAttribute) { - PrimitiveValue primitiveValue = new PrimitiveValue(); - primitiveValue - .setType(((PrimitiveSpecAttribute) attribute) - .getType()); - primitiveValue.setValue(value); - values.put(key, primitiveValue); - } else if (attribute instanceof RefSpecAttribute) { - RefValue refValue = new RefValue(); - if (value instanceof ScopedObject) { - refValue.setLabel("RUNTIME " - + value.getClass().getName()); - } else { - refValue.setLabel("STATIC " - + value.getClass().getName()); - } - values.put(key, refValue); - } else if (attribute instanceof ResourceSpecAttribute) { - PrimitiveValue primitiveValue = new PrimitiveValue(); - primitiveValue - .setType(((ResourceSpecAttribute) attribute) - .getType()); - primitiveValue.setValue(value); - values.put(key, primitiveValue); - } else { - throw new SlcException("Unkown spec attribute type " - + attribute.getClass()); - } - } - - } - - ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name, - values, executionSpec); - if (executionFlow.getPath() != null) - efd.setPath(executionFlow.getPath()); - - // Add execution spec if necessary - if (!md.getExecutionSpecs().contains(executionSpec)) - md.getExecutionSpecs().add(executionSpec); - - // Add execution flow - md.getExecutionFlows().add(efd); - } - - return md; - } - - protected Map listFlows() { - GenericBeanFactoryAccessor accessor = new GenericBeanFactoryAccessor( - applicationContext); - Map executionFlows = accessor - .getBeansOfType(ExecutionFlow.class); - return executionFlows; - } - - public void execute(ExecutionFlowDescriptor executionFlowDescriptor) { - if (descriptorConverter != null) - executionContext.addVariables(descriptorConverter - .convertValues(executionFlowDescriptor)); - ExecutionFlow flow = (ExecutionFlow) applicationContext.getBean( - executionFlowDescriptor.getName(), ExecutionFlow.class); - flow.run(); - } - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - public void setDescriptorConverter( - ExecutionFlowDescriptorConverter descriptorConverter) { - this.descriptorConverter = descriptorConverter; - }*/ - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgent.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgent.java deleted file mode 100644 index aaa687fd7..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgent.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.argeo.slc.BasicNameVersion; -import org.argeo.slc.NameVersion; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionModuleDescriptor; -import org.argeo.slc.execution.ExecutionModulesManager; -import org.argeo.slc.execution.ExecutionProcess; -import org.argeo.slc.execution.SlcAgent; - -/** Implements the base methods of an SLC agent. */ -public class DefaultAgent implements SlcAgent { - // private final static Log log = LogFactory.getLog(DefaultAgent.class); - /** UTF-8 charset for encoding. */ - private final static String UTF8 = "UTF-8"; - - private String agentUuid = null; - private ExecutionModulesManager modulesManager; - - private ThreadGroup processesThreadGroup; - private Map runningProcesses = Collections - .synchronizedMap(new HashMap()); - - private String defaultModulePrefix = null; - - /* - * LIFECYCLE - */ - /** Initialization */ - public void init() { - agentUuid = initAgentUuid(); - processesThreadGroup = new ThreadGroup("SLC Processes of Agent #" - + agentUuid); - } - - /** Clean up (needs to be called by overriding method) */ - public void destroy() { - } - - /** - * Called during initialization in order to determines the agent UUID. To be - * overridden. By default creates a new one per instance. - */ - protected String initAgentUuid() { - return UUID.randomUUID().toString(); - } - - /* - * SLC AGENT - */ - public void process(ExecutionProcess process) { - ProcessThread processThread = createProcessThread(processesThreadGroup, - modulesManager, process); - processThread.start(); - runningProcesses.put(process.getUuid(), processThread); - - // clean up old processes - Iterator it = runningProcesses.values().iterator(); - while (it.hasNext()) { - ProcessThread pThread = it.next(); - if (!pThread.isAlive()) - it.remove(); - } - } - - public String process(List uris) { - DefaultProcess process = new DefaultProcess(); - for (URI uri : uris) { - String[] path = uri.getPath().split("/"); - if (path.length < 3) - throw new SlcException("Badly formatted URI: " + uri); - NameVersion nameVersion = new BasicNameVersion(path[1]); - StringBuilder flow = new StringBuilder(); - for (int i = 2; i < path.length; i++) - flow.append('/').append(path[i]); - - Map values = getQueryMap(uri.getQuery()); - // Get execution module descriptor - ExecutionModuleDescriptor emd = getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - process.getRealizedFlows().add( - emd.asRealizedFlow(flow.toString(), values)); - } - process(process); - return process.getUuid(); - } - - public void kill(String processUuid) { - if (runningProcesses.containsKey(processUuid)) { - runningProcesses.get(processUuid).interrupt(); - } else { - // assume is finished - } - } - - public void waitFor(String processUuid, Long millis) { - if (runningProcesses.containsKey(processUuid)) { - try { - if (millis != null) - runningProcesses.get(processUuid).join(millis); - else - runningProcesses.get(processUuid).join(); - } catch (InterruptedException e) { - // silent - } - } else { - // assume is finished - } - } - - /** Creates the thread which will coordinate the execution for this agent. */ - protected ProcessThread createProcessThread( - ThreadGroup processesThreadGroup, - ExecutionModulesManager modulesManager, ExecutionProcess process) { - ProcessThread processThread = new ProcessThread(processesThreadGroup, - modulesManager, process); - return processThread; - } - - public ExecutionModuleDescriptor getExecutionModuleDescriptor( - String moduleName, String moduleVersion) { - // Get execution module descriptor - ExecutionModuleDescriptor emd; - try { - modulesManager - .start(new BasicNameVersion(moduleName, moduleVersion)); - emd = modulesManager.getExecutionModuleDescriptor(moduleName, - moduleVersion); - } catch (SlcException e) { - if (defaultModulePrefix != null) { - moduleName = defaultModulePrefix + "." + moduleName; - modulesManager.start(new BasicNameVersion(moduleName, - moduleVersion)); - emd = modulesManager.getExecutionModuleDescriptor(moduleName, - moduleVersion); - } else - throw e; - } - return emd; - } - - public List listExecutionModuleDescriptors() { - return modulesManager.listExecutionModules(); - } - - public boolean ping() { - return true; - } - - /* - * UTILITIES - */ - /** - * @param query - * can be null - */ - static Map getQueryMap(String query) { - Map map = new LinkedHashMap(); - if (query == null) - return map; - String[] params = query.split("&"); - for (String param : params) { - String[] arr = param.split("="); - String name = arr[0]; - Object value = arr.length > 1 ? param.split("=")[1] : Boolean.TRUE; - try { - map.put(URLDecoder.decode(name, UTF8), - URLDecoder.decode(value.toString(), UTF8)); - } catch (UnsupportedEncodingException e) { - throw new SlcException("Cannot decode '" + param + "'", e); - } - } - return map; - } - - /* - * BEAN - */ - public void setModulesManager(ExecutionModulesManager modulesManager) { - this.modulesManager = modulesManager; - } - - public void setDefaultModulePrefix(String defaultModulePrefix) { - this.defaultModulePrefix = defaultModulePrefix; - } - - public String getAgentUuid() { - return agentUuid; - } - - @Override - public String toString() { - return "Agent #" + getAgentUuid(); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgentCli.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgentCli.java deleted file mode 100644 index b09aee755..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultAgentCli.java +++ /dev/null @@ -1,242 +0,0 @@ -package org.argeo.slc.core.execution; - -import java.net.URI; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.security.OsAuthenticationToken; -import org.argeo.slc.BasicNameVersion; -import org.argeo.slc.NameVersion; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlowDescriptor; -import org.argeo.slc.execution.ExecutionModuleDescriptor; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.argeo.slc.execution.SlcAgent; -import org.argeo.slc.execution.SlcAgentCli; -import org.springframework.security.Authentication; -import org.springframework.security.AuthenticationManager; -import org.springframework.security.context.SecurityContextHolder; - -/** - * Authenticates thread and executes synchronously a command line execution. - * Reference implementation of args to URIs algorithm. - */ -public class DefaultAgentCli implements SlcAgentCli { - private final static Log log = LogFactory.getLog(DefaultAgentCli.class); - - private final static String UTF8 = "UTF-8"; - private SlcAgent agent; - private AuthenticationManager authenticationManager; - - private Long timeout = 24 * 60 * 60 * 1000l; - - public String process(String[] args) { - if (SecurityContextHolder.getContext().getAuthentication() == null) { - OsAuthenticationToken oat = new OsAuthenticationToken(); - Authentication authentication = authenticationManager - .authenticate(oat); - SecurityContextHolder.getContext() - .setAuthentication(authentication); - } - - if (args.length > 0 && args[0].equals("help")) { - StringBuilder buf = new StringBuilder(); - help(args, buf); - log.info("\n" + buf); - return buf.toString(); - } else { - List uris = asURIs(args); - String processUuid = agent.process(uris); - agent.waitFor(processUuid, timeout); - return processUuid; - } - } - - protected void help(String[] rawArgs, StringBuilder buf) { - String[] args = Arrays.copyOfRange(rawArgs, 1, rawArgs.length); - if (args.length == 0) {// modules - for (ExecutionModuleDescriptor emd : agent - .listExecutionModuleDescriptors()) { - appendModule(emd, buf); - } - } else if (args.length == 1 && !args[0].contains("/")) {// single module - NameVersion nameVersion = new BasicNameVersion(args[0]); - ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - appendModule(emd, buf); - - // flows - for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { - buf.append(" ").append(efd.getName()); - if (efd.getDescription() != null - && !efd.getDescription().trim().equals("")) - buf.append(" : ").append(" ").append(efd.getDescription()); - buf.append('\n'); - } - return; - } else { - List uris = asURIs(args); - for (URI uri : uris) { - appendUriHelp(uri, buf); - } - } - } - - protected void appendUriHelp(URI uri, StringBuilder buf) { - String[] path = uri.getPath().split("/"); - NameVersion nameVersion = new BasicNameVersion(path[1]); - ExecutionModuleDescriptor emd = agent.getExecutionModuleDescriptor( - nameVersion.getName(), nameVersion.getVersion()); - - StringBuilder flow = new StringBuilder(); - for (int i = 2; i < path.length; i++) - flow.append('/').append(path[i]); - String flowPath = flow.toString(); - ExecutionFlowDescriptor efd = findExecutionFlowDescriptor(emd, flowPath); - if (efd == null) - throw new SlcException("Flow " + uri + " not found"); - - appendModule(emd, buf); - - buf.append(" ").append(efd.getName()); - if (efd.getDescription() != null - && !efd.getDescription().trim().equals("")) - buf.append(" : ").append(" ").append(efd.getDescription()); - buf.append('\n'); - Map values = DefaultAgent.getQueryMap(uri.getQuery()); - ExecutionSpec spec = efd.getExecutionSpec(); - for (String attrKey : spec.getAttributes().keySet()) { - ExecutionSpecAttribute esa = spec.getAttributes().get(attrKey); - buf.append(" --").append(attrKey); - if (values.containsKey(attrKey)) - buf.append(" ").append(values.get(attrKey)); - if (esa.getValue() != null) - buf.append(" (").append(esa.getValue()).append(')'); - buf.append('\n'); - } - } - - private void appendModule(ExecutionModuleDescriptor emd, StringBuilder buf) { - buf.append("# ").append(emd.getName()); - if (emd.getDescription() != null - && !emd.getDescription().trim().equals("")) - buf.append(" : ").append(emd.getDescription()); - if (emd.getVersion() != null) - buf.append(" (v").append(emd.getVersion()).append(")"); - buf.append('\n'); - } - - public static List asURIs(String[] args) { - try { - List uris = new ArrayList(); - List leftOvers = new ArrayList(); - - Boolean hasArgs = false; - String currKey = null; - StringBuilder currUri = null; - Iterator argIt = Arrays.asList(args).iterator(); - while (argIt.hasNext()) { - String arg = argIt.next(); - if (!arg.startsWith("-")) { - if (currKey != null) {// value - currUri.append(URLEncoder.encode(arg, UTF8)); - currKey = null; - } else { // module - if (currUri != null) { - uris.add(new URI(currUri.toString())); - } - currUri = new StringBuilder("flow:"); - - String currModule = arg; - currUri.append('/').append(currModule); - if (!arg.contains("/")) { - // flow path not in arg go to next arg - if (!argIt.hasNext()) - throw new SlcException("No flow found"); - String currFlow = argIt.next(); - if (!currFlow.startsWith("/")) - currFlow = "/" + currFlow; - currUri.append(currFlow); - } - } - } else { - if (currUri == null) {// first args - leftOvers.add(arg); - } else { - String key; - if (arg.startsWith("--")) - key = arg.substring(2); - else if (arg.startsWith("-")) - key = arg.substring(1); - else { - throw new SlcException("Cannot intepret key: " - + arg); - } - - if (!hasArgs) { - currUri.append('?'); - hasArgs = true; - } else { - currUri.append('&'); - } - - // deal with boolean keys - if (currKey != null) {// value - currUri.append(URLEncoder.encode("true", UTF8)); - currKey = null; - } - - currKey = key; - currUri.append(URLEncoder.encode(key, UTF8)) - .append('='); - } - } - } - if (currUri != null) - uris.add(new URI(currUri.toString())); - return uris; - } catch (Exception e) { - throw new SlcException("Cannot convert " + Arrays.toString(args) - + " to flow URI", e); - } - } - - private ExecutionFlowDescriptor findExecutionFlowDescriptor( - ExecutionModuleDescriptor emd, String flowPath) { - ExecutionFlowDescriptor flowDescriptor = null; - for (ExecutionFlowDescriptor efd : emd.getExecutionFlows()) { - String name = efd.getName(); - // normalize name as flow path - if (!name.startsWith("/")) - name = "/" + name; - if (name.endsWith("/")) - name = name.substring(0, name.length() - 1); - if (name.equals(flowPath)) { - flowDescriptor = efd; - break; - } - } - return flowDescriptor; - } - - public void setAgent(SlcAgent agent) { - this.agent = agent; - } - - public void setAuthenticationManager( - AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - public void setTimeout(Long timeout) { - this.timeout = timeout; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlow.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlow.java deleted file mode 100644 index 535c42dad..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlow.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.validation.MapBindingResult; - -/** Default implementation of an execution flow. */ -public class DefaultExecutionFlow implements ExecutionFlow, InitializingBean, - BeanNameAware { - private final static Log log = LogFactory - .getLog(DefaultExecutionFlow.class); - - private final ExecutionSpec executionSpec; - private String name = null; - private Map parameters = new HashMap(); - private List executables = new ArrayList(); - - private String path; - - private Boolean failOnError = true; - - public DefaultExecutionFlow() { - this.executionSpec = new DefaultExecutionSpec(); - } - - public DefaultExecutionFlow(ExecutionSpec executionSpec) { - this.executionSpec = executionSpec; - } - - public DefaultExecutionFlow(ExecutionSpec executionSpec, - Map parameters) { - // be sure to have an execution spec - this.executionSpec = (executionSpec == null) ? new DefaultExecutionSpec() - : executionSpec; - - // only parameters contained in the executionSpec can be set - for (String parameter : parameters.keySet()) { - if (!executionSpec.getAttributes().containsKey(parameter)) { - throw new SlcException("Parameter " + parameter - + " is not defined in the ExecutionSpec"); - } - } - - // set the parameters - this.parameters.putAll(parameters); - - // check that all the required parameters are defined - MapBindingResult errors = new MapBindingResult(parameters, "execution#" - + getName()); - for (String key : executionSpec.getAttributes().keySet()) { - ExecutionSpecAttribute attr = executionSpec.getAttributes() - .get(key); - - if (attr.getIsImmutable() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Immutable but not set"); - break; - } - - if (attr.getIsConstant() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Constant but not set as parameter"); - break; - } - - if (attr.getIsHidden() && !isSetAsParameter(key)) { - errors.rejectValue(key, "Hidden but not set as parameter"); - break; - } - } - - if (errors.hasErrors()) - throw new SlcException("Could not prepare execution flow: " - + errors.toString()); - - } - - public void run() { - try { - for (Runnable executable : executables) { - if (Thread.interrupted()) { - log.error("Flow '" + getName() + "' killed before '" - + executable + "'"); - Thread.currentThread().interrupt(); - return; - // throw new ThreadDeath(); - } - this.doExecuteRunnable(executable); - } - } catch (RuntimeException e) { - if (Thread.interrupted()) { - log.error("Flow '" + getName() - + "' killed while receiving an unrelated exception", e); - Thread.currentThread().interrupt(); - return; - // throw new ThreadDeath(); - } - if (failOnError) - throw e; - else { - log.error("Execution flow failed," - + " but process did not fail" - + " because failOnError property" - + " is set to false: " + e); - if (log.isTraceEnabled()) - e.printStackTrace(); - } - } - } - - /** - * List sub-runnables that would be executed if run() method would be - * called. - */ - public Iterator runnables() { - return executables.iterator(); - } - - /** - * If there is one and only one runnable wrapped return it, throw an - * exeception otherwise. - */ - public Runnable getRunnable() { - if (executables.size() == 1) - return executables.get(0); - else - throw new SlcException("There are " + executables.size() - + " runnables in flow " + getName()); - } - - public void doExecuteRunnable(Runnable runnable) { - runnable.run(); - } - - public void afterPropertiesSet() throws Exception { - if (path == null) { - if (name.charAt(0) == '/') { - path = name.substring(0, name.lastIndexOf('/')); - } - } - - if (path != null) { - for (Runnable executable : executables) { - if (executable instanceof DefaultExecutionFlow) { - // so we don't need to have DefaultExecutionFlow - // implementing StructureAware - // FIXME: probably has side effects - DefaultExecutionFlow flow = (DefaultExecutionFlow) executable; - String newPath = path + '/' + flow.getName(); - flow.setPath(newPath); - log.warn(newPath + " was forcibly set on " + flow); - } - } - } - } - - public void setBeanName(String name) { - this.name = name; - } - - public void setExecutables(List executables) { - this.executables = executables; - } - - public void setParameters(Map attributes) { - this.parameters = attributes; - } - - public String getName() { - return name; - } - - public ExecutionSpec getExecutionSpec() { - return executionSpec; - } - - public Object getParameter(String parameterName) { - // Verify that there is a spec attribute - ExecutionSpecAttribute specAttr = null; - if (executionSpec.getAttributes().containsKey(parameterName)) { - specAttr = executionSpec.getAttributes().get(parameterName); - } else { - throw new SlcException("Key " + parameterName - + " is not defined in the specifications of " + toString()); - } - - if (parameters.containsKey(parameterName)) { - Object paramValue = parameters.get(parameterName); - return paramValue; - } else { - if (specAttr.getValue() != null) { - return specAttr.getValue(); - } - } - throw new SlcException("Key " + parameterName - + " is not set as parameter in " + toString()); - } - - public Boolean isSetAsParameter(String key) { - return parameters.containsKey(key) - || (executionSpec.getAttributes().containsKey(key) && executionSpec - .getAttributes().get(key).getValue() != null); - } - - @Override - public String toString() { - return new StringBuffer("Execution flow ").append(name).toString(); - } - - @Override - public boolean equals(Object obj) { - return ((ExecutionFlow) obj).getName().equals(name); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public Boolean getFailOnError() { - return failOnError; - } - - public void setFailOnError(Boolean failOnError) { - this.failOnError = failOnError; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java deleted file mode 100644 index d7670789e..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.TreeSet; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionFlowDescriptor; -import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; -import org.argeo.slc.execution.ExecutionModuleDescriptor; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.springframework.aop.scope.ScopedObject; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.util.StringUtils; - -/** - * Performs conversion in both direction between data exchanged with the agent - * and the data in the application context. - */ -public class DefaultExecutionFlowDescriptorConverter implements - ExecutionFlowDescriptorConverter, ApplicationContextAware { - public final static String REF_VALUE_TYPE_BEAN_NAME = "beanName"; - - /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */ - private final static String REF_VALUE_INTERNAL = "[internal]"; - - private final static Log log = LogFactory - .getLog(DefaultExecutionFlowDescriptorConverter.class); - - private ApplicationContext applicationContext; - - @SuppressWarnings("unused") - public Map convertValues( - ExecutionFlowDescriptor executionFlowDescriptor) { - Map values = executionFlowDescriptor.getValues(); - Map convertedValues = new HashMap(); - ExecutionSpec executionSpec = executionFlowDescriptor - .getExecutionSpec(); - - if (executionSpec == null && log.isTraceEnabled()) - log.warn("Execution spec is null for " + executionFlowDescriptor); - - if (values != null && executionSpec != null) { - values: for (String key : values.keySet()) { - ExecutionSpecAttribute attribute = executionSpec - .getAttributes().get(key); - - if (attribute == null) - throw new FlowConfigurationException( - "No spec attribute defined for '" + key + "'"); - - if (attribute.getIsConstant()) - continue values; - - Object value = values.get(key); - if (value instanceof PrimitiveValue) { - PrimitiveValue primitiveValue = (PrimitiveValue) value; - // TODO: check class <=> type - convertedValues.put(key, primitiveValue.getValue()); - } else if (value instanceof RefValue) { - RefValue refValue = (RefValue) value; - String type = refValue.getType(); - if (REF_VALUE_TYPE_BEAN_NAME.equals(type)) { - // FIXME: UI should send all information about spec - // - targetClass - // - name - // String executionSpecName = executionSpec.getName(); - // ExecutionSpec localSpec = (ExecutionSpec) - // applicationContext - // .getBean(executionSpecName); - // RefSpecAttribute localAttr = (RefSpecAttribute) - // localSpec - // .getAttributes().get(key); - // Class targetClass = localAttr.getTargetClass(); - // - // String primitiveType = PrimitiveUtils - // .classAsType(targetClass); - String primitiveType = null; - if (primitiveType != null) { - // not active - String ref = refValue.getRef(); - Object obj = PrimitiveUtils.convert(primitiveType, - ref); - convertedValues.put(key, obj); - } else { - String ref = refValue.getRef(); - if (ref != null && !ref.equals(REF_VALUE_INTERNAL)) { - Object obj = null; - if (applicationContext.containsBean(ref)) { - obj = applicationContext.getBean(ref); - } else { - // FIXME: hack in order to pass primitive - obj = ref; - } - convertedValues.put(key, obj); - } else { - log.warn("Cannot interpret " + refValue); - } - } - } else if (PrimitiveUtils.typeAsClass(type) != null) { - String ref = refValue.getRef(); - Object obj = PrimitiveUtils.convert(type, ref); - convertedValues.put(key, obj); - } else { - throw new FlowConfigurationException( - "Ref value type not supported: " - + refValue.getType()); - } - } else { - // default is to take the value as is - convertedValues.put(key, value); - } - } - } - return convertedValues; - } - - public void addFlowsToDescriptor(ExecutionModuleDescriptor md, - Map executionFlows) { - SortedSet set = new TreeSet( - new ExecutionFlowDescriptorComparator()); - for (String name : executionFlows.keySet()) { - ExecutionFlow executionFlow = executionFlows.get(name); - - ExecutionFlowDescriptor efd = getExecutionFlowDescriptor(executionFlow); - ExecutionSpec executionSpec = efd.getExecutionSpec(); - - // Add execution spec if necessary - if (!md.getExecutionSpecs().contains(executionSpec)) - md.getExecutionSpecs().add(executionSpec); - - // Add execution flow - set.add(efd); - // md.getExecutionFlows().add(efd); - } - md.getExecutionFlows().addAll(set); - } - - @SuppressWarnings("deprecation") - public ExecutionFlowDescriptor getExecutionFlowDescriptor( - ExecutionFlow executionFlow) { - if (executionFlow.getName() == null) - throw new FlowConfigurationException("Flow name is null: " - + executionFlow); - String name = executionFlow.getName(); - - ExecutionSpec executionSpec = executionFlow.getExecutionSpec(); - if (executionSpec == null) - throw new FlowConfigurationException("Execution spec is null: " - + executionFlow); - if (executionSpec.getName() == null) - throw new FlowConfigurationException( - "Execution spec name is null: " + executionSpec); - - Map values = new TreeMap(); - for (String key : executionSpec.getAttributes().keySet()) { - ExecutionSpecAttribute attribute = executionSpec.getAttributes() - .get(key); - - if (attribute instanceof PrimitiveSpecAttribute) { - if (executionFlow.isSetAsParameter(key)) { - Object value = executionFlow.getParameter(key); - PrimitiveValue primitiveValue = new PrimitiveValue(); - primitiveValue.setType(((PrimitiveSpecAttribute) attribute) - .getType()); - primitiveValue.setValue(value); - values.put(key, primitiveValue); - } else { - // no need to add a primitive value if it is not set, - // all necessary information is in the spec - } - } else if (attribute instanceof RefSpecAttribute) { - if (attribute.getIsConstant()) { - values.put(key, new RefValue(REF_VALUE_INTERNAL)); - } else - values.put( - key, - buildRefValue((RefSpecAttribute) attribute, - executionFlow, key)); - } else { - throw new FlowConfigurationException( - "Unkown spec attribute type " + attribute.getClass()); - } - - } - - ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(name, null, - values, executionSpec); - if (executionFlow.getPath() != null) - efd.setPath(executionFlow.getPath()); - else - efd.setPath(""); - - // Takes description from spring - BeanFactory bf = getBeanFactory(); - if (bf != null) { - BeanDefinition bd = getBeanFactory().getBeanDefinition(name); - efd.setDescription(bd.getDescription()); - } - return efd; - } - - @SuppressWarnings(value = { "unchecked" }) - protected RefValue buildRefValue(RefSpecAttribute rsa, - ExecutionFlow executionFlow, String key) { - RefValue refValue = new RefValue(); - // FIXME: UI should be able to deal with other types - refValue.setType(REF_VALUE_TYPE_BEAN_NAME); - Class targetClass = rsa.getTargetClass(); - String primitiveType = PrimitiveUtils.classAsType(targetClass); - if (primitiveType != null) { - if (executionFlow.isSetAsParameter(key)) { - Object value = executionFlow.getParameter(key); - refValue.setRef(value.toString()); - } - refValue.setType(primitiveType); - return refValue; - } else { - - if (executionFlow.isSetAsParameter(key)) { - String ref = null; - Object value = executionFlow.getParameter(key); - if (applicationContext == null) { - log.warn("No application context declared, cannot scan ref value."); - ref = value.toString(); - } else { - - // look for a ref to the value - Map beans = getBeanFactory() - .getBeansOfType(targetClass, false, false); - // TODO: also check scoped beans - beans: for (String beanName : beans.keySet()) { - Object obj = beans.get(beanName); - if (value instanceof ScopedObject) { - // don't call methods of the target of the scope - if (obj instanceof ScopedObject) - if (value == obj) { - ref = beanName; - break beans; - } - } else { - if (obj.equals(value)) { - ref = beanName; - break beans; - } - } - } - } - if (ref == null) { - if (log.isTraceEnabled()) - log.trace("Cannot define reference for ref spec attribute " - + key - + " in " - + executionFlow - + " (" - + rsa - + ")." - + " If it is an inner bean consider put it frozen."); - ref = REF_VALUE_INTERNAL; - } else { - if (log.isTraceEnabled()) - log.trace(ref - + " is the reference for ref spec attribute " - + key + " in " + executionFlow + " (" + rsa - + ")"); - } - refValue.setRef(ref); - } - return refValue; - } - } - - /** @return can be null */ - private ConfigurableListableBeanFactory getBeanFactory() { - if (applicationContext == null) - return null; - return ((ConfigurableApplicationContext) applicationContext) - .getBeanFactory(); - } - - /** Must be use within the execution application context */ - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - - private static class ExecutionFlowDescriptorComparator implements - Comparator { - @SuppressWarnings("deprecation") - public int compare(ExecutionFlowDescriptor o1, - ExecutionFlowDescriptor o2) { - // TODO: write unit tests for this - - String name1 = o1.getName(); - String name2 = o2.getName(); - - String path1 = o1.getPath(); - String path2 = o2.getPath(); - - // Check whether name include path - int lastIndex1 = name1.lastIndexOf('/'); - // log.debug(name1+", "+lastIndex1); - if (!StringUtils.hasText(path1) && lastIndex1 >= 0) { - path1 = name1.substring(0, lastIndex1); - name1 = name1.substring(lastIndex1 + 1); - } - - int lastIndex2 = name2.lastIndexOf('/'); - if (!StringUtils.hasText(path2) && lastIndex2 >= 0) { - path2 = name2.substring(0, lastIndex2); - name2 = name2.substring(lastIndex2 + 1); - } - - // Perform the actual comparison - if (StringUtils.hasText(path1) && StringUtils.hasText(path2)) { - if (path1.equals(path2)) - return name1.compareTo(name2); - else if (path1.startsWith(path2)) - return -1; - else if (path2.startsWith(path1)) - return 1; - else - return path1.compareTo(path2); - } else if (!StringUtils.hasText(path1) - && StringUtils.hasText(path2)) { - return 1; - } else if (StringUtils.hasText(path1) - && !StringUtils.hasText(path2)) { - return -1; - } else if (!StringUtils.hasText(path1) - && !StringUtils.hasText(path2)) { - return name1.compareTo(name2); - } else { - return 0; - } - } - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionSpec.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionSpec.java deleted file mode 100644 index 002d691ae..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionSpec.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; - -/** Spring based implementation of execution specifications. */ -public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware, - ApplicationContextAware, InitializingBean, Serializable { - private static final long serialVersionUID = 5159882223926926539L; - private final static Log log = LogFactory - .getLog(DefaultExecutionSpec.class); - private transient ApplicationContext applicationContext; - - private String description; - private Map attributes = new HashMap(); - - private String name = INTERNAL_NAME; - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - - public void setBeanName(String name) { - this.name = name; - } - - /** - * The Spring bean name (only relevant for specs declared has high-level - * beans) - */ - public String getName() { - return name; - } - - public boolean equals(Object obj) { - return ((ExecutionSpec) obj).getName().equals(name); - } - - /** - * The Spring bean description (only relevant for specs declared has - * high-level beans) - */ - public String getDescription() { - return description; - } - - private ConfigurableListableBeanFactory getBeanFactory() { - return ((ConfigurableApplicationContext) applicationContext) - .getBeanFactory(); - } - - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - public void afterPropertiesSet() throws Exception { - if (description == null) { - try { - description = getBeanFactory().getBeanDefinition(name) - .getDescription(); - } catch (NoSuchBeanDefinitionException e) { - // silent - } - } - - for (String key : attributes.keySet()) { - ExecutionSpecAttribute attr = attributes.get(key); - if (attr instanceof RefSpecAttribute) { - RefSpecAttribute rsa = (RefSpecAttribute) attr; - if (rsa.getChoices() == null) { - List choices = buildRefValueChoices(rsa); - rsa.setChoices(choices); - } - if (log.isTraceEnabled()) - log.debug("Spec attr " + key + " has " - + rsa.getChoices().size() + " choices"); - } - } - } - - /** - * Generates a list of ref value choices based on the bean available in the - * application ocntext. - */ - protected List buildRefValueChoices(RefSpecAttribute rsa) { - List choices = new ArrayList(); - if (applicationContext == null) { - log.warn("No application context declared," - + " cannot scan ref value choices."); - return choices; - } - - for (String beanName : getBeanFactory().getBeanNamesForType( - rsa.getTargetClass(), true, false)) { - - // Since Spring 3, systemProperties is implicitly defined but has no - // bean definition - // if (beanName.equals("systemProperties")) - // continue beanNames; - - BeanDefinition bd = getBeanFactory().getBeanDefinition(beanName); - RefValueChoice choice = new RefValueChoice(); - choice.setName(beanName); - choice.setDescription(bd.getDescription()); - if (log.isTraceEnabled()) - log.debug("Found choice " + beanName + " for " + rsa); - - choices.add(choice); - - } - return choices; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionStack.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionStack.java deleted file mode 100644 index d1d06c698..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionStack.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; -import java.util.UUID; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionSpecAttribute; -import org.argeo.slc.execution.ExecutionStack; - -/** Canonical implementation of an execution stack. */ -public class DefaultExecutionStack implements ExecutionStack { - - private final static Log log = LogFactory - .getLog(DefaultExecutionStack.class); - - private final Stack stack = new Stack(); - - public synchronized void enterFlow(ExecutionFlow executionFlow) { - ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow); - stack.push(runtime); - - Map specAttrs = executionFlow - .getExecutionSpec().getAttributes(); - for (String key : specAttrs.keySet()) { - if (executionFlow.isSetAsParameter(key)) { - runtime.getLocalVariables().put(key, - executionFlow.getParameter(key)); - } - } - } - - public synchronized String getCurrentStackLevelUuid() { - return stack.peek().getUuid(); - } - - public synchronized Integer getStackSize() { - return stack.size(); - } - - /** - * Looks for a set variable in the stack, starting at the upper flows - * - * @return the variable or null if not found - */ - public synchronized Object findLocalVariable(String key) { - Object obj = null; - for (int i = 0; i < stack.size(); i++) { - if (stack.get(i).getLocalVariables().containsKey(key)) { - obj = stack.get(i).getLocalVariables().get(key); - break; - } - } - return obj; - } - - public synchronized void leaveFlow(ExecutionFlow executionFlow) { - ExecutionFlowRuntime leftEf = stack.pop(); - - if (!leftEf.getExecutionFlow().getName() - .equals(executionFlow.getName())) - throw new SlcException("Asked to leave " + executionFlow - + " but last is " + leftEf); - - leftEf.getScopedObjects().clear(); - leftEf.getLocalVariables().clear(); - } - - public synchronized void addScopedObject(String name, Object obj) { - ExecutionFlowRuntime runtime = stack.peek(); - // TODO: check that the object is not set yet ? - if (log.isDebugEnabled()) { - Object existing = findScopedObject(name); - if (existing != null) - log.warn("Scoped object " + name + " of type " + obj.getClass() - + " already registered in " + runtime); - } - runtime.getScopedObjects().put(name, obj); - } - - /** @return null if not found */ - public synchronized Object findScopedObject(String name) { - Object obj = null; - for (int i = stack.size() - 1; i >= 0; i--) { - if (stack.get(i).getScopedObjects().containsKey(name)) { - obj = stack.get(i).getScopedObjects().get(name); - break; - } - } - return obj; - } - - protected static class ExecutionFlowRuntime { - private final ExecutionFlow executionFlow; - private final Map scopedObjects = new HashMap(); - private final Map localVariables = new HashMap(); - private final String uuid = UUID.randomUUID().toString(); - - public ExecutionFlowRuntime(ExecutionFlow executionFlow) { - this.executionFlow = executionFlow; - } - - public ExecutionFlow getExecutionFlow() { - return executionFlow; - } - - public Map getScopedObjects() { - return scopedObjects; - } - - public String getUuid() { - return uuid; - } - - public Map getLocalVariables() { - return localVariables; - } - - @Override - public String toString() { - return "Stack Level #" + uuid; - } - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultProcess.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultProcess.java deleted file mode 100644 index 30211800f..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultProcess.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.argeo.slc.core.execution; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.argeo.slc.execution.ExecutionProcess; -import org.argeo.slc.execution.ExecutionStep; -import org.argeo.slc.execution.RealizedFlow; - -/** Canonical implementation of an {@link ExecutionProcess} as a bean. */ -public class DefaultProcess implements ExecutionProcess { - private String uuid = UUID.randomUUID().toString(); - private String status = ExecutionProcess.NEW; - - private List steps = new ArrayList(); - private List realizedFlows = new ArrayList(); - - public String getUuid() { - return uuid; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public void addSteps(List steps) { - steps.addAll(steps); - } - - public List getRealizedFlows() { - return realizedFlows; - } - - public List getSteps() { - return steps; - } - - public void setSteps(List steps) { - this.steps = steps; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public void setRealizedFlows(List realizedFlows) { - this.realizedFlows = realizedFlows; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionAspect.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionAspect.java deleted file mode 100644 index b50b78f51..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionAspect.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionStack; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; - -@Aspect -/** Aspect intercepting calls on execution flows and contexts. */ -public class ExecutionAspect { - private final static Log log = LogFactory.getLog(ExecutionAspect.class); - - private ExecutionStack executionStack; - private ExecutionContext executionContext; - - @Around("flowExecution()") - public void aroundFlow(ProceedingJoinPoint pjp) throws Throwable { - // IMPORTANT: Make sure that the execution context is called before the - // execution stack - executionContext.getUuid(); - - ExecutionFlow executionFlow = (ExecutionFlow) pjp.getTarget(); - executionStack.enterFlow(executionFlow); - executionContext.setVariable(ExecutionContext.VAR_FLOW_ID, - executionStack.getCurrentStackLevelUuid()); - executionContext.setVariable(ExecutionContext.VAR_FLOW_NAME, - executionFlow.getName()); - - logStackEvent("=> ", executionFlow); - try { - // Actually execute the flow - pjp.proceed(); - } finally { - logStackEvent("<= ", executionFlow); - executionStack.leaveFlow(executionFlow); - } - } - - @Around("getVariable()") - public Object aroundGetVariable(ProceedingJoinPoint pjp) throws Throwable { - Object obj = pjp.proceed(); - // if the variable was not found, look in the stack starting at the - // upper flows - if (obj == null) { - String key = pjp.getArgs()[0].toString(); - obj = executionStack.findLocalVariable(key); - } - return obj; - } - - @Pointcut("execution(void org.argeo.slc.execution.ExecutionFlow.run())") - public void flowExecution() { - } - - @Pointcut("execution(* org.argeo.slc.execution.ExecutionContext.getVariable(..))") - public void getVariable() { - } - - public void setExecutionStack(ExecutionStack executionStack) { - this.executionStack = executionStack; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - protected void logStackEvent(String symbol, ExecutionFlow executionFlow) { - Integer stackSize = executionStack.getStackSize(); - if (log.isTraceEnabled()) - log.debug(depthSpaces(stackSize) + symbol + executionFlow + " #" - + executionStack.getCurrentStackLevelUuid() + ", depth=" - + stackSize); - if (log.isDebugEnabled()) - log.debug(depthSpaces(stackSize) + symbol + executionFlow); - } - - protected void logRunnableExecution(ExecutionFlow executionFlow, - Runnable runnable) { - Integer stackSize = executionStack.getStackSize(); - if (log.isDebugEnabled()) - log.debug(depthSpaces(stackSize + 1) - + runnable.getClass().getSimpleName() + " in " - + executionFlow); - } - - private String depthSpaces(int depth) { - StringBuffer buf = new StringBuffer(depth * 2); - for (int i = 0; i < depth; i++) - buf.append(" "); - return buf.toString(); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java deleted file mode 100644 index 1365e6bc6..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.beans.PropertyDescriptor; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.BeanDefinitionStoreException; -import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; -import org.springframework.beans.factory.config.TypedStringValue; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.support.ManagedMap; -import org.springframework.beans.factory.support.ManagedSet; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -/** - * Spring post processor which ensures that execution parameters are properly - * set. It is used at two levels: first during instantiation for instantiation - * parameters which allow to implement templates, then at runtime in order to - * interpret @{} placeholders when object of scope execution are instantiated. - */ -public class ExecutionParameterPostProcessor extends - InstantiationAwareBeanPostProcessorAdapter { - - private final static Log log = LogFactory - .getLog(ExecutionParameterPostProcessor.class); - - private ExecutionContext executionContext; - private InstantiationManager instantiationManager; - - private String placeholderPrefix = "@{"; - private String placeholderSuffix = "}"; - private String nullValue; - - @Override - public PropertyValues postProcessPropertyValues(PropertyValues pvs, - PropertyDescriptor[] pds, Object bean, String beanName) - throws BeansException { - - // TODO: resolve at execution only if scope is execution - // TODO: deal with placeholders in RuntimeBeanReference and - // RuntimeBeanNameReference - - MutablePropertyValues newPvs = new MutablePropertyValues(); - - boolean changesOccured = false; - - for (PropertyValue pv : pvs.getPropertyValues()) { - Object convertedValue = resolveValue(beanName, bean, pv.getValue()); - newPvs.addPropertyValue(new PropertyValue(pv, convertedValue)); - if (convertedValue != pv.getValue()) { - changesOccured = true; - } - } - - return changesOccured ? newPvs : pvs; - } - - @Override - public boolean postProcessAfterInstantiation(Object bean, String beanName) - throws BeansException { - if (bean instanceof ExecutionFlow) - instantiationManager.flowInitializationStarted( - (ExecutionFlow) bean, beanName); - return true; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - if (bean instanceof ExecutionFlow) - instantiationManager.flowInitializationFinished( - (ExecutionFlow) bean, beanName); - return bean; - } - - protected String resolvePlaceholder(Object bean, String placeholder) { - if (instantiationManager.isInFlowInitialization()) - return instantiationManager.getInitializingFlowParameter( - placeholder).toString(); - - else {// execution - // next call fail if no execution context available - Object obj = executionContext.getVariable(placeholder); - if (obj != null) { - return obj.toString(); - } - } - - return null; - } - - @SuppressWarnings(value = { "unchecked" }) - public Object resolveValue(String beanName, Object bean, Object value) { - if (value instanceof TypedStringValue) { - TypedStringValue tsv = (TypedStringValue) value; - String originalValue = tsv.getValue(); - - String convertedValue = resolveString(beanName, bean, originalValue); - if (convertedValue == null) - return null; - return convertedValue.equals(originalValue) ? value - : new TypedStringValue(convertedValue); - } else if (value instanceof String) { - String originalValue = value.toString(); - String convertedValue = resolveString(beanName, bean, originalValue); - if (convertedValue == null) - return null; - return convertedValue.equals(originalValue) ? value - : convertedValue; - } else if (value instanceof ManagedMap) { - Map mapVal = (Map) value; - - Map newContent = new ManagedMap(); - boolean entriesModified = false; - for (Iterator it = mapVal.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - int keyHash = (key != null ? key.hashCode() : 0); - Object newKey = resolveValue(beanName, bean, key); - int newKeyHash = (newKey != null ? newKey.hashCode() : 0); - Object val = entry.getValue(); - Object newVal = resolveValue(beanName, bean, val); - newContent.put(newKey, newVal); - entriesModified = entriesModified - || (newVal != val || newKey != key || newKeyHash != keyHash); - } - - return entriesModified ? newContent : value; - } else if (value instanceof ManagedList) { - List listVal = (List) value; - List newContent = new ManagedList(); - boolean valueModified = false; - - for (int i = 0; i < listVal.size(); i++) { - Object elem = listVal.get(i); - Object newVal = resolveValue(beanName, bean, elem); - newContent.add(newVal); - if (!ObjectUtils.nullSafeEquals(newVal, elem)) { - valueModified = true; - } - } - return valueModified ? newContent : value; - } else if (value instanceof ManagedSet) { - Set setVal = (Set) value; - Set newContent = new ManagedSet(); - boolean entriesModified = false; - for (Iterator it = setVal.iterator(); it.hasNext();) { - Object elem = it.next(); - int elemHash = (elem != null ? elem.hashCode() : 0); - Object newVal = resolveValue(beanName, bean, elem); - int newValHash = (newVal != null ? newVal.hashCode() : 0); - newContent.add(newVal); - entriesModified = entriesModified - || (newVal != elem || newValHash != elemHash); - } - return entriesModified ? newContent : value; - } else { - // log.debug(beanName + ": " + value.getClass() + " : " + value); - return value; - } - - } - - private String resolveString(String beanName, Object bean, String strVal) { - // in case is passed - if (strVal == null) - return null; - - String value = parseStringValue(bean, strVal, new HashSet()); - - if (value == null) - throw new SlcException("Could not resolve placeholder '" + strVal - + "' in bean '" + beanName + "'"); - - return (value.equals(nullValue) ? null : value); - } - - public void setPlaceholderPrefix(String placeholderPrefix) { - this.placeholderPrefix = placeholderPrefix; - } - - public void setPlaceholderSuffix(String placeholderSuffix) { - this.placeholderSuffix = placeholderSuffix; - } - - public void setNullValue(String nullValue) { - this.nullValue = nullValue; - } - - public void setInstantiationManager( - InstantiationManager instantiationManager) { - this.instantiationManager = instantiationManager; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - // - // Following methods hacked from the internals of - // PropertyPlaceholderConfigurer - // - - protected String parseStringValue(Object bean, String strVal, - Set visitedPlaceholders) - throws BeanDefinitionStoreException { - - // in case is passed - if (strVal == null) - return null; - - StringBuffer buf = new StringBuffer(strVal); - - int startIndex = strVal.indexOf(placeholderPrefix); - while (startIndex != -1) { - int endIndex = findPlaceholderEndIndex(buf, startIndex); - if (endIndex != -1) { - String placeholder = buf.substring(startIndex - + placeholderPrefix.length(), endIndex); - if (!visitedPlaceholders.add(placeholder)) { - throw new BeanDefinitionStoreException( - "Circular placeholder reference '" + placeholder - + "' in property definitions"); - } - // Recursive invocation, parsing placeholders contained in - // the placeholder key. - placeholder = parseStringValue(bean, placeholder, - visitedPlaceholders); - // Now obtain the value for the fully resolved key... - String propVal = resolvePlaceholder(bean, placeholder); - if (propVal != null) { - // Recursive invocation, parsing placeholders contained - // in the - // previously resolved placeholder value. - propVal = parseStringValue(bean, propVal, - visitedPlaceholders); - buf.replace(startIndex, - endIndex + placeholderSuffix.length(), propVal); - if (log.isTraceEnabled()) { - log.trace("Resolved placeholder '" + placeholder + "'"); - } - startIndex = buf.indexOf(placeholderPrefix, startIndex - + propVal.length()); - } else { - throw new BeanDefinitionStoreException( - "Could not resolve placeholder '" + placeholder - + "'"); - } - visitedPlaceholders.remove(placeholder); - } else { - startIndex = -1; - } - } - - return buf.toString(); - } - - private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + placeholderPrefix.length(); - int withinNestedPlaceholder = 0; - while (index < buf.length()) { - if (StringUtils.substringMatch(buf, index, placeholderSuffix)) { - if (withinNestedPlaceholder > 0) { - withinNestedPlaceholder--; - index = index + placeholderSuffix.length(); - } else { - return index; - } - } else if (StringUtils - .substringMatch(buf, index, placeholderPrefix)) { - withinNestedPlaceholder++; - index = index + placeholderPrefix.length(); - } else { - index++; - } - } - return -1; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResources.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResources.java deleted file mode 100644 index 759a12542..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResources.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; - -import org.springframework.core.io.Resource; - -/** Provides write access to resources during execution */ -public interface ExecutionResources { - /** The base directory where this execution can write */ - public File getWritableBaseDir(); - - /** Allocates a local file in the writable area and return it as a resource. */ - public Resource getWritableResource(String relativePath); - - /** - * Allocates a local file in the writable area and return it as a fully - * qualified OS path. - */ - public String getWritableOsPath(String relativePath); - - /** - * Allocates a local file in the writable area and return it as a - * {@link File}. - */ - public File getWritableOsFile(String relativePath); - - /** - * Returns the resource as a file path. If the resource is not writable it - * is copied as a file in the writable area and the path to this local file - * is returned. - */ - public String getAsOsPath(Resource resource, Boolean overwrite); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java deleted file mode 100644 index bf5ffef12..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionResourcesFactoryBean.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** Workaround when execution placedholders needs to be passed.*/ -public class ExecutionResourcesFactoryBean implements FactoryBean { - private ExecutionResources executionResources; - private String relativePath; - - public Object getObject() throws Exception { - Assert.notNull(executionResources, "executionResources is null"); - Assert.notNull(relativePath, "relativePath is null"); - return executionResources.getWritableResource(relativePath); - } - - public Class getObjectType() { - return Resource.class; - } - - public boolean isSingleton() { - return true; - } - - public void setExecutionResources(ExecutionResources executionResources) { - this.executionResources = executionResources; - } - - public void setRelativePath(String relativePath) { - this.relativePath = relativePath; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java deleted file mode 100644 index a2a5a9b0c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.UnsupportedException; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionSpec; -import org.argeo.slc.execution.ExecutionStack; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.beans.factory.config.Scope; - -/** - * When Spring beans are instantiated with this scope, the same instance is - * reused across an execution. - */ -public class ExecutionScope implements Scope { - private final static Log log = LogFactory.getLog(ExecutionScope.class); - - private final ThreadLocal executionStack = new ThreadLocal(); - public final ThreadLocal executionStackBeanName = new ThreadLocal(); - - private final ThreadLocal executionContext = new ThreadLocal(); - private final ThreadLocal executionContextBeanName = new ThreadLocal(); - - public Object get(String name, ObjectFactory objectFactory) { - if (log.isTraceEnabled()) - log.debug("Get execution scoped bean " + name); - - // shortcuts - if (executionStackBeanName.get() != null - && name.equals(executionStackBeanName.get())) { - return executionStack.get(); - } - - if (executionContextBeanName.get() != null - && name.equals(executionContextBeanName.get())) { - return executionContext.get(); - } - - // execution context must be defined first - if (executionContext.get() == null) { - Object obj = objectFactory.getObject(); - if (obj instanceof ExecutionContext) { - return dealWithSpecialScopedObject(name, executionContext, - executionContextBeanName, (ExecutionContext) obj); - } else { - // TODO: use execution context wrapper - throw new SlcException("No execution context has been defined."); - } - } - - // for other scoped objects, an executions stack must be available - if (executionStack.get() == null) { - Object obj = objectFactory.getObject(); - if (obj instanceof ExecutionStack) { - return dealWithSpecialScopedObject(name, executionStack, - executionStackBeanName, (ExecutionStack) obj); - } else { - throw new SlcException("No execution stack has been defined."); - } - } - - // see if the execution stack already knows the object - Object obj = executionStack.get().findScopedObject(name); - if (obj == null) { - obj = objectFactory.getObject(); - if (obj instanceof ExecutionContext) - throw new SlcException( - "Only one execution context can be defined per thread"); - if (obj instanceof ExecutionStack) - throw new SlcException( - "Only one execution stack can be defined per thread"); - - checkForbiddenClasses(obj); - - executionStack.get().addScopedObject(name, obj); - } - return obj; - - } - - protected T dealWithSpecialScopedObject(String name, - ThreadLocal threadLocal, - ThreadLocal threadLocalBeanName, T newObj) { - - T obj = threadLocal.get(); - if (obj == null) { - obj = newObj; - threadLocal.set(obj); - threadLocalBeanName.set(name); - if (log.isTraceEnabled()) { - log.debug(obj.getClass() + " instantiated. (beanName=" + name - + ")"); - } - return obj; - } else { - throw new SlcException("Only one scoped " + obj.getClass() - + " can be defined per thread"); - } - - } - - protected void checkForbiddenClasses(Object obj) { - Class clss = obj.getClass(); - if (ExecutionFlow.class.isAssignableFrom(clss) - || ExecutionSpec.class.isAssignableFrom(clss)) { - throw new UnsupportedException("Execution scoped object", clss); - } - } - - public String getConversationId() { - // TODO: is it the most relevant? - return executionContext.get().getUuid(); - } - - public void registerDestructionCallback(String name, Runnable callback) { - if (Thread.currentThread() instanceof ExecutionThread) { - ExecutionThread executionThread = (ExecutionThread) Thread - .currentThread(); - executionThread.registerDestructionCallback(name, callback); - } - } - - public Object remove(String name) { - if (log.isDebugEnabled()) - log.debug("Remove object " + name); - throw new UnsupportedOperationException(); - } - - public Object resolveContextualObject(String key) { - return executionContext.get().getVariable(key); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java deleted file mode 100644 index 9289c7f56..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionThread.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlowDescriptor; -import org.argeo.slc.execution.ExecutionModulesManager; -import org.argeo.slc.execution.ExecutionStep; -import org.argeo.slc.execution.RealizedFlow; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** Thread of a single execution */ -public class ExecutionThread extends Thread { - public final static String SYSPROP_EXECUTION_AUTO_UPGRADE = "slc.execution.autoupgrade"; - private final static Log log = LogFactory.getLog(ExecutionThread.class); - - private ExecutionModulesManager executionModulesManager; - private final RealizedFlow realizedFlow; - - private List destructionCallbacks = new ArrayList(); - - public ExecutionThread(ProcessThreadGroup processThreadGroup, - ExecutionModulesManager executionModulesManager, - RealizedFlow realizedFlow) { - super(processThreadGroup, "Flow " - + realizedFlow.getFlowDescriptor().getName()); - this.realizedFlow = realizedFlow; - this.executionModulesManager = executionModulesManager; - } - - public void run() { - // authenticate thread - Authentication authentication = getProcessThreadGroup() - .getAuthentication(); - if (authentication == null) - throw new SlcException("Can only execute authenticated threads"); - SecurityContextHolder.getContext().setAuthentication(authentication); - - // Retrieve execution flow descriptor - ExecutionFlowDescriptor executionFlowDescriptor = realizedFlow - .getFlowDescriptor(); - String flowName = executionFlowDescriptor.getName(); - - getProcessThreadGroup().dispatchAddStep( - new ExecutionStep(realizedFlow.getModuleName(), - ExecutionStep.PHASE_START, "Flow " + flowName)); - - try { - String autoUpgrade = System - .getProperty(SYSPROP_EXECUTION_AUTO_UPGRADE); - if (autoUpgrade != null && autoUpgrade.equals("true")) - executionModulesManager.upgrade(realizedFlow - .getModuleNameVersion()); - executionModulesManager.start(realizedFlow.getModuleNameVersion()); - // - // START FLOW - // - executionModulesManager.execute(realizedFlow); - // END FLOW - } catch (FlowConfigurationException e) { - String msg = "Configuration problem with flow " + flowName + ":\n" - + e.getMessage(); - log.error(msg); - getProcessThreadGroup().dispatchAddStep( - new ExecutionStep(realizedFlow.getModuleName(), - ExecutionStep.ERROR, msg + " " + e.getMessage())); - } catch (Exception e) { - // TODO: re-throw exception ? - String msg = "Execution of flow " + flowName + " failed."; - log.error(msg, e); - getProcessThreadGroup().dispatchAddStep( - new ExecutionStep(realizedFlow.getModuleName(), - ExecutionStep.ERROR, msg + " " + e.getMessage())); - } finally { - getProcessThreadGroup().dispatchAddStep( - new ExecutionStep(realizedFlow.getModuleName(), - ExecutionStep.PHASE_END, "Flow " + flowName)); - processDestructionCallbacks(); - } - } - - private synchronized void processDestructionCallbacks() { - for (int i = destructionCallbacks.size() - 1; i >= 0; i--) { - try { - destructionCallbacks.get(i).run(); - } catch (Exception e) { - log.warn("Could not process destruction callback " + i - + " in thread " + getName(), e); - } - } - } - - /** - * Gather object destruction callback to be called in reverse order at the - * end of the thread - */ - synchronized void registerDestructionCallback(String name, Runnable callback) { - destructionCallbacks.add(callback); - } - - protected ProcessThreadGroup getProcessThreadGroup() { - return (ProcessThreadGroup) getThreadGroup(); - } -} \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java deleted file mode 100644 index d225cd193..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionContext; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** Implements write access to resources based on standard Java {@link File} */ -public class FileExecutionResources implements ExecutionResources { - private final static Log log = LogFactory - .getLog(FileExecutionResources.class); - protected final static String DEFAULT_EXECUTION_RESOURCES_DIRNAME = "executionResources"; - public final static String DEFAULT_EXECUTION_RESOURCES_TMP_PATH = System - .getProperty("java.io.tmpdir") - + File.separator - + System.getProperty("user.name") - + File.separator - + "slc" - + File.separator + DEFAULT_EXECUTION_RESOURCES_DIRNAME; - - private File baseDir; - private ExecutionContext executionContext; - private String prefixDatePattern = "yyMMdd_HHmmss_SSS"; - private SimpleDateFormat sdf = null; - - private Boolean withExecutionSubdirectory = true; - - public FileExecutionResources() { - // Default base directory - String osgiInstanceArea = System.getProperty("osgi.instance.area"); - String osgiInstanceAreaDefault = System - .getProperty("osgi.instance.area.default"); - - if (osgiInstanceArea != null) { - // within OSGi with -data specified - osgiInstanceArea = removeFilePrefix(osgiInstanceArea); - baseDir = new File(osgiInstanceArea + File.separator - + DEFAULT_EXECUTION_RESOURCES_DIRNAME); - } else if (osgiInstanceAreaDefault != null) { - // within OSGi without -data specified - osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault); - baseDir = new File(osgiInstanceAreaDefault + File.separator - + DEFAULT_EXECUTION_RESOURCES_DIRNAME); - } else {// outside OSGi - baseDir = new File(DEFAULT_EXECUTION_RESOURCES_TMP_PATH); - } - } - - protected SimpleDateFormat sdf() { - // Lazy init in case prefix has been externally set - if (sdf == null) - sdf = new SimpleDateFormat(prefixDatePattern); - return sdf; - } - - public Resource getWritableResource(String relativePath) { - File file = getFile(relativePath); - File parentDir = file.getParentFile(); - - if (!parentDir.exists()) { - // Creates if necessary - if (log.isTraceEnabled()) - log.trace("Creating parent directory " + parentDir); - parentDir.mkdirs(); - } - Resource resource = new FileSystemResource(file); - - if (log.isTraceEnabled()) - log.trace("Returns writable resource " + resource); - return resource; - } - - public String getWritableOsPath(String relativePath) { - try { - return getFile(relativePath).getCanonicalPath(); - } catch (IOException e) { - throw new SlcException("Cannot find canonical path", e); - } - } - - public File getWritableOsFile(String relativePath) { - return getFile(relativePath); - } - - public String getAsOsPath(Resource resource, Boolean overwrite) { - File file = fileFromResource(resource); - if (file != null) - try { - if (log.isTraceEnabled()) - log.debug("Directly interpret " + resource + " as OS file " - + file); - return file.getCanonicalPath(); - } catch (IOException e1) { - // silent - } - - if (log.isTraceEnabled()) - log.trace("Resource " + resource - + " is not available on the file system. Retrieving it..."); - - InputStream in = null; - OutputStream out = null; - try { - String path = resource.getURL().getPath(); - file = getFile(path); - if (file.exists() && !overwrite) - return file.getCanonicalPath(); - - file.getParentFile().mkdirs(); - in = resource.getInputStream(); - out = new FileOutputStream(file); - IOUtils.copy(in, out); - if (log.isDebugEnabled()) - log.debug("Retrieved " + resource + " to OS file " + file); - return file.getCanonicalPath(); - } catch (IOException e) { - throw new SlcException("Could not make resource " + resource - + " an OS file.", e); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - - /** - * Extract the underlying file from the resource. - * - * @return the file or null if no files support this resource. - */ - protected File fileFromResource(Resource resource) { - try { - return resource.getFile(); - } catch (IOException e) { - return null; - } - - } - - protected File getFile(String relativePath) { - File writableBaseDir = getWritableBaseDir(); - return new File(writableBaseDir.getPath() + File.separator - + relativePath.replace('/', File.separatorChar)); - } - - public File getWritableBaseDir() { - if (withExecutionSubdirectory) { - Date executionContextCreationDate = (Date) executionContext - .getVariable(ExecutionContext.VAR_EXECUTION_CONTEXT_CREATION_DATE); - Assert.notNull(executionContext, "execution context is null"); - String path = baseDir.getPath() + File.separator - + sdf().format(executionContextCreationDate); - // TODO write execution id somewhere? like in a txt file - return new File(path); - } else { - return baseDir; - } - } - - protected String removeFilePrefix(String url) { - if (url.startsWith("file:")) - return url.substring("file:".length()); - else if (url.startsWith("reference:file:")) - return url.substring("reference:file:".length()); - else - return url; - } - - public void setBaseDir(File baseDir) { - this.baseDir = baseDir; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - public void setPrefixDatePattern(String prefixDatePattern) { - this.prefixDatePattern = prefixDatePattern; - } - - public File getBaseDir() { - return baseDir; - } - - public ExecutionContext getExecutionContext() { - return executionContext; - } - - public String getPrefixDatePattern() { - return prefixDatePattern; - } - - /** Default is true. */ - public void setWithExecutionSubdirectory(Boolean withExecutionSubdirectory) { - this.withExecutionSubdirectory = withExecutionSubdirectory; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FlowConfigurationException.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FlowConfigurationException.java deleted file mode 100644 index aeda5aca5..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/FlowConfigurationException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.argeo.slc.core.execution; - -import org.argeo.slc.SlcException; - -/** The stack trace of such exceptions does not need to be displayed */ -public class FlowConfigurationException extends SlcException { - private static final long serialVersionUID = 8456260596346797321L; - - public FlowConfigurationException(String message) { - super(message); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/InstantiationManager.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/InstantiationManager.java deleted file mode 100644 index 60e93ec15..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/InstantiationManager.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.Stack; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionSpecAttribute; - -/** Manage parameters that need to be set during the instantiation of a flow */ -public class InstantiationManager { - - private final static Log log = LogFactory - .getLog(InstantiationManager.class); - - private ThreadLocal> flowStack = new ThreadLocal>(); - - public Object createRef(String name) { - - if ((flowStack.get() == null) || flowStack.get().empty()) { - throw new SlcException("No flow is currently initializing." - + " Declare ParameterRef as inner beans or prototypes."); - } - - return getInitializingFlowParameter(name); - } - - public void flowInitializationStarted(ExecutionFlow flow, String flowName) { - // set the flow name if it is DefaultExecutionFlow - if (flow instanceof DefaultExecutionFlow) { - ((DefaultExecutionFlow) flow).setBeanName(flowName); - } - - if (log.isTraceEnabled()) - log.trace("Start initialization of " + flow.hashCode() + " (" - + flow + " - " + flow.getClass() + ")"); - - // log.info("# flowInitializationStarted " + flowName); - // create a stack for this thread if there is none - if (flowStack.get() == null) { - flowStack.set(new Stack()); - } - flowStack.get().push(flow); - } - - public void flowInitializationFinished(ExecutionFlow flow, String flowName) { - if (log.isTraceEnabled()) - log.trace("Finish initialization of " + flow.hashCode() + " (" - + flow + " - " + flow.getClass() + ")"); - - if (flowStack.get() != null) { - ExecutionFlow registeredFlow = flowStack.get().pop(); - if (registeredFlow != null) { - if (!flow.getName().equals(registeredFlow.getName())) - throw new SlcException("Current flow is " + flow); - // log.info("# flowInitializationFinished " + flowName); - // initializingFlow.set(null); - } - } else { - // happens for flows imported as services - log.warn("flowInitializationFinished - Flow Stack is null"); - } - } - - protected ExecutionFlow findInitializingFlowWithParameter(String key) { - if ((flowStack.get() == null) || flowStack.get().empty()) - throw new SlcException("No initializing flow available."); - - // first look in the outer flow (that may override parameters) - for (int i = 0; i < flowStack.get().size(); i++) { - if (flowStack.get().elementAt(i).isSetAsParameter(key)) { - return flowStack.get().elementAt(i); - } - } - throw new SlcException("Key " + key + " is not set as parameter in " - + flowStack.get().firstElement().toString() + " (stack size=" - + flowStack.get().size() + ")"); - - } - - public Object getInitializingFlowParameter(String key) { - return findInitializingFlowWithParameter(key).getParameter(key); - } - - public Class getInitializingFlowParameterClass(String key) { - ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key) - .getExecutionSpec().getAttributes().get(key); - if (attr instanceof RefSpecAttribute) - return ((RefSpecAttribute) attr).getTargetClass(); - else if (attr instanceof PrimitiveSpecAttribute) { - String type = ((PrimitiveSpecAttribute) attr).getType(); - Class clss = PrimitiveUtils.typeAsClass(type); - if (clss == null) - throw new SlcException("Cannot convert type " + type - + " to class."); - return clss; - } else - return null; - } - - public Boolean isInFlowInitialization() { - return (flowStack.get() != null) && !flowStack.get().empty(); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java deleted file mode 100644 index 0bbc3f0df..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionContext; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -public class MapExecutionContext implements ExecutionContext, - ApplicationContextAware { - private final Map variables = Collections - .synchronizedMap(new HashMap()); - - private final String uuid; - - private ApplicationContext applicationContext; - - public MapExecutionContext() { - uuid = UUID.randomUUID().toString(); - variables.put(VAR_EXECUTION_CONTEXT_ID, uuid); - variables.put(VAR_EXECUTION_CONTEXT_CREATION_DATE, new Date()); - } - - public void setVariable(String key, Object value) { - // check if we do not refer to a bean - int lastInd = key.lastIndexOf('.'); - if (applicationContext != null && lastInd > 0) { - String beanName = key.substring(0, lastInd); - String propertyName = key.substring(lastInd + 1); - if (applicationContext.containsBean(beanName)) { - BeanWrapper beanWrapper = new BeanWrapperImpl( - applicationContext.getBean(beanName)); - if (!beanWrapper.isWritableProperty(propertyName)) - throw new SlcException("No writable property " - + propertyName + " in bean " + beanName); - beanWrapper.setPropertyValue(propertyName, value); - } - } - - variables.put(key, value); - } - - public Object getVariable(String key) { - // check if we do not refer to a bean - int lastInd = key.lastIndexOf('.'); - if (applicationContext != null && lastInd > 0) { - String beanName = key.substring(0, lastInd); - String propertyName = key.substring(lastInd + 1); - if (applicationContext.containsBean(beanName)) { - BeanWrapper beanWrapper = new BeanWrapperImpl( - applicationContext.getBean(beanName)); - if (!beanWrapper.isReadableProperty(propertyName)) - throw new SlcException("No readable property " - + propertyName + " in bean " + beanName); - Object obj = beanWrapper.getPropertyValue(propertyName); - return obj; - } - } - - Object value = variables.get(key); - // try system property in last resort - if (value == null) - value = System.getProperty(key); - return value; - } - - public String getUuid() { - return uuid; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ExecutionContext) - return uuid.equals(((ExecutionContext) obj).getUuid()); - return false; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "#" + uuid; - } - - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = applicationContext; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/OsFileFactoryBean.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/OsFileFactoryBean.java deleted file mode 100644 index 52f91e1d5..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/OsFileFactoryBean.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** Retrieve an OS File from the given resource. */ -public class OsFileFactoryBean implements FactoryBean { - private ExecutionResources executionResources; - private Resource resource; - private Boolean overwrite = false; - - /** Return an existing file on the file system. */ - public Object getObject() throws Exception { - Assert.notNull(executionResources, "executionResources is null"); - Assert.notNull(resource, "resource is null"); - return executionResources.getAsOsPath(resource, overwrite); - } - - /** Return {@link Object} because CGLIB is unable to proxy {@link File}.*/ - public Class getObjectType() { - return CharSequence.class; - } - - public boolean isSingleton() { - return false; - } - - /** The execution resources object. */ - public void setExecutionResources(ExecutionResources executionResources) { - this.executionResources = executionResources; - } - - /** The resource to access. */ - public void setResource(Resource resource) { - this.resource = resource; - } - - /** - * Whether to overwrite the resource if it already exists. Default is - * false. - */ - public void setOverwrite(Boolean overwrite) { - this.overwrite = overwrite; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ParameterRef.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ParameterRef.java deleted file mode 100644 index 5a9d9adcf..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ParameterRef.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.FactoryBean; - -public class ParameterRef implements FactoryBean { - private final static Log log = LogFactory.getLog(ParameterRef.class); - - private InstantiationManager instantiationManager; - private String name; - - /** Cached object. */ - private Object object; - - public ParameterRef() { - } - - public ParameterRef(String name) { - this.name = name; - } - - public Object getObject() throws Exception { - if (log.isTraceEnabled()) - log.debug("Parameter ref called for " + name); - - if (object == null) - object = instantiationManager.getInitializingFlowParameter(name); - return object; - } - - public Class getObjectType() { - if (object == null) - return instantiationManager.getInitializingFlowParameterClass(name); - else - return object.getClass(); - } - - public boolean isSingleton() { - return true; - } - - public void setInstantiationManager( - InstantiationManager instantiationManager) { - this.instantiationManager = instantiationManager; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveAccessor.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveAccessor.java deleted file mode 100644 index 18d1b9894..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveAccessor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -/** Abstraction of access to primitive values */ -public interface PrimitiveAccessor { - public final static String TYPE_STRING = "string"; - /** - * As of Argeo 1, passwords are NOT stored encrypted, just hidden in the UI, - * but stored in plain text in JCR. Use keyring instead. - */ - public final static String TYPE_PASSWORD = "password"; - public final static String TYPE_INTEGER = "integer"; - public final static String TYPE_LONG = "long"; - public final static String TYPE_FLOAT = "float"; - public final static String TYPE_DOUBLE = "double"; - public final static String TYPE_BOOLEAN = "boolean"; - - public String getType(); - - public Object getValue(); - - public void setValue(Object value); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java deleted file mode 100644 index fe8412c81..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveSpecAttribute.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.argeo.slc.SlcException; - -/** - * A spec attribute wrapping a primitive value. - * - * @see PrimitiveAccessor - */ -public class PrimitiveSpecAttribute extends AbstractSpecAttribute implements - PrimitiveAccessor { - private static final long serialVersionUID = -566676381839825483L; - private String type = "string"; - private Object value = null; - - public PrimitiveSpecAttribute() { - } - - public PrimitiveSpecAttribute(String type, Object value) { - this.type = type; - this.value = value; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - public String getType() { - return type; - } - - public void setType(String type) { - // check whether type is recognized. - if (PrimitiveUtils.typeAsClass(type) == null) - throw new SlcException("Unrecognized type " + type); - this.type = type; - - } - - @Override - public String toString() { - return "Primitive spec attribute [" + type + "]" - + (value != null ? "=" + value : ""); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveUtils.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveUtils.java deleted file mode 100644 index 4268b8b03..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -/** Converts to and from primitive types. */ -public class PrimitiveUtils { - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_STRING} instead - */ - public final static String TYPE_STRING = PrimitiveAccessor.TYPE_STRING; - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_INTEGER} instead - */ - public final static String TYPE_INTEGER = PrimitiveAccessor.TYPE_INTEGER; - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_LONG} instead - */ - public final static String TYPE_LONG = PrimitiveAccessor.TYPE_LONG; - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_FLOAT} instead - */ - public final static String TYPE_FLOAT = PrimitiveAccessor.TYPE_FLOAT; - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_DOUBLE} instead - */ - public final static String TYPE_DOUBLE = PrimitiveAccessor.TYPE_DOUBLE; - /** - * @deprecated Use {@link PrimitiveAccessor#TYPE_BOOLEAN} instead - */ - public final static String TYPE_BOOLEAN = PrimitiveAccessor.TYPE_BOOLEAN; - - private PrimitiveUtils() { - - } - - /** @return the class or null if the provided type is not a primitive */ - public static Class typeAsClass(String type) { - if (PrimitiveAccessor.TYPE_STRING.equals(type)) - return String.class; - else if (PrimitiveAccessor.TYPE_PASSWORD.equals(type)) - return char[].class; - else if (PrimitiveAccessor.TYPE_INTEGER.equals(type)) - return Integer.class; - else if (PrimitiveAccessor.TYPE_LONG.equals(type)) - return Long.class; - else if (PrimitiveAccessor.TYPE_FLOAT.equals(type)) - return Float.class; - else if (PrimitiveAccessor.TYPE_DOUBLE.equals(type)) - return Double.class; - else if (PrimitiveAccessor.TYPE_BOOLEAN.equals(type)) - return Boolean.class; - else - return null; - } - - /** @return the type or null if the provided class is not a primitive */ - public static String classAsType(Class clss) { - if (String.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_STRING; - else if (char[].class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_PASSWORD; - else if (Integer.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_INTEGER; - else if (Long.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_LONG; - else if (Float.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_FLOAT; - else if (Double.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_DOUBLE; - else if (Boolean.class.isAssignableFrom(clss)) - return PrimitiveAccessor.TYPE_BOOLEAN; - else - return null; - } - - /** Parse string as an object. Passwords are returned as String.*/ - public static Object convert(String type, String str) { - if (PrimitiveAccessor.TYPE_STRING.equals(type)) { - return str; - } else if (PrimitiveAccessor.TYPE_PASSWORD.equals(type)) { - return str; - } else if (PrimitiveAccessor.TYPE_INTEGER.equals(type)) { - return (Integer.parseInt(str)); - } else if (PrimitiveAccessor.TYPE_LONG.equals(type)) { - return (Long.parseLong(str)); - } else if (PrimitiveAccessor.TYPE_FLOAT.equals(type)) { - return (Float.parseFloat(str)); - } else if (PrimitiveAccessor.TYPE_DOUBLE.equals(type)) { - return (Double.parseDouble(str)); - } else if (PrimitiveAccessor.TYPE_BOOLEAN.equals(type)) { - return (Boolean.parseBoolean(str)); - } else { - return str; - } - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveValue.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveValue.java deleted file mode 100644 index 3dedb9c22..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveValue.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -/** Primitive value to be used by an execution. */ -public class PrimitiveValue extends AbstractExecutionValue implements - PrimitiveAccessor { - private static final long serialVersionUID = 533414290998374166L; - - private String type; - - private Object value; - - public PrimitiveValue() { - } - - public PrimitiveValue(String type, Object value) { - super(); - this.type = type; - this.value = value; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java deleted file mode 100644 index b64639a8c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThread.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.execution.ExecutionModulesManager; -import org.argeo.slc.execution.ExecutionProcess; -import org.argeo.slc.execution.ExecutionStep; -import org.argeo.slc.execution.RealizedFlow; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** - * Main thread coordinating an {@link ExecutionProcess}, launching parallel or - * sequential {@link ExecutionThread}s. - */ -public class ProcessThread extends Thread { - private final static Log log = LogFactory.getLog(ProcessThread.class); - - private final ExecutionModulesManager executionModulesManager; - private final ExecutionProcess process; - private final ProcessThreadGroup processThreadGroup; - - private Set executionThreads = Collections - .synchronizedSet(new HashSet()); - - // private Boolean hadAnError = false; - private Boolean killed = false; - - public ProcessThread(ThreadGroup processesThreadGroup, - ExecutionModulesManager executionModulesManager, - ExecutionProcess process) { - super(processesThreadGroup, "SLC Process #" + process.getUuid()); - this.executionModulesManager = executionModulesManager; - this.process = process; - processThreadGroup = new ProcessThreadGroup(process); - } - - public final void run() { - // authenticate thread - Authentication authentication = getProcessThreadGroup() - .getAuthentication(); - if (authentication == null) - throw new SlcException("Can only execute authenticated threads"); - SecurityContextHolder.getContext().setAuthentication(authentication); - - log.info("\n##\n## SLC Process #" + process.getUuid() - + " STARTED\n##\n"); - - // Start logging - new LoggingThread().start(); - - process.setStatus(ExecutionProcess.RUNNING); - try { - process(); - } catch (InterruptedException e) { - die(); - return; - } catch (Exception e) { - String msg = "Process " + getProcess().getUuid() - + " failed unexpectedly."; - log.error(msg, e); - getProcessThreadGroup().dispatchAddStep( - new ExecutionStep("Process", ExecutionStep.ERROR, msg + " " - + e.getMessage())); - } - - // waits for all execution threads to complete (in case they were - // started asynchronously) - for (ExecutionThread executionThread : executionThreads) { - if (executionThread.isAlive()) { - try { - executionThread.join(); - } catch (InterruptedException e) { - die(); - return; - } - } - } - - computeFinalStatus(); - } - - /** Make sure this is called BEFORE all the threads are interrupted. */ - private void computeFinalStatus() { - // String oldStatus = process.getStatus(); - // TODO: error management at flow level? - if (killed) - process.setStatus(ExecutionProcess.KILLED); - else if (processThreadGroup.hadAnError()) - process.setStatus(ExecutionProcess.ERROR); - else - process.setStatus(ExecutionProcess.COMPLETED); - // executionModulesManager.dispatchUpdateStatus(process, oldStatus, - // process.getStatus()); - log.info("\n## SLC Process #" + process.getUuid() + " " - + process.getStatus() + "\n"); - } - - /** Called when being killed */ - private synchronized void die() { - killed = true; - computeFinalStatus(); - for (ExecutionThread executionThread : executionThreads) { - try { - executionThread.interrupt(); - } catch (Exception e) { - log.error("Cannot interrupt " + executionThread); - } - } - processThreadGroup.interrupt(); - } - - /** - * Implementation specific execution. To be overridden in order to deal with - * custom process types. Default expects an {@link SlcExecution}. - */ - protected void process() throws InterruptedException { - List flowsToProcess = new ArrayList(); - flowsToProcess.addAll(process.getRealizedFlows()); - while (flowsToProcess.size() > 0) { - RealizedFlow realizedFlow = flowsToProcess.remove(0); - execute(realizedFlow, true); - } - } - - /** @return the (distinct) thread used for this execution */ - protected final void execute(RealizedFlow realizedFlow, Boolean synchronous) - throws InterruptedException { - if (killed) - return; - - ExecutionThread thread = new ExecutionThread(processThreadGroup, - executionModulesManager, realizedFlow); - executionThreads.add(thread); - thread.start(); - - if (synchronous) - thread.join(); - - return; - } - - // public void notifyError() { - // hadAnError = true; - // } - // - // public synchronized void flowCompleted() { - // // notifyAll(); - // } - - public ExecutionProcess getProcess() { - return process; - } - - public ProcessThreadGroup getProcessThreadGroup() { - return processThreadGroup; - } - - public ExecutionModulesManager getExecutionModulesManager() { - return executionModulesManager; - } - - private class LoggingThread extends Thread { - - public LoggingThread() { - super("SLC Process Logger #" + process.getUuid()); - } - - public void run() { - boolean run = true; - while (run) { - List newSteps = new ArrayList(); - processThreadGroup.getSteps().drainTo(newSteps); - if (newSteps.size() > 0) { - // System.out.println(steps.size() + " steps"); - process.addSteps(newSteps); - } - - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - break; - } - - if (!ProcessThread.this.isAlive() - && processThreadGroup.getSteps().size() == 0) - run = false; - } - } - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java deleted file mode 100644 index 2f264bed4..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ProcessThreadGroup.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; - -import org.argeo.slc.execution.ExecutionProcess; -import org.argeo.slc.execution.ExecutionStep; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** The thread group attached to a given {@link SlcExecution}. */ -public class ProcessThreadGroup extends ThreadGroup { - // private final ExecutionModulesManager executionModulesManager; - // private final ProcessThread processThread; - private final Authentication authentication; - private final static Integer STEPS_BUFFER_CAPACITY = 5000; - - private BlockingQueue steps = new ArrayBlockingQueue( - STEPS_BUFFER_CAPACITY); - - private Boolean hadAnError = false; - - public ProcessThreadGroup(ExecutionProcess executionProcess) { - super("SLC Process #" + executionProcess.getUuid() + " thread group"); - // this.executionModulesManager = executionModulesManager; - // this.processThread = processThread; - this.authentication = SecurityContextHolder.getContext() - .getAuthentication(); - } - - public Authentication getAuthentication() { - return authentication; - } - - public void dispatchAddStep(ExecutionStep step) { - // ExecutionProcess slcProcess = processThread.getProcess(); - // List steps = new ArrayList(); - // steps.add(step); - // TODO clarify why we don't dispatch steps, must be a reason - // dispatchAddSteps(steps); - // slcProcess.addSteps(steps); - if (step.getType().equals(ExecutionStep.ERROR)) - hadAnError = true; - this.steps.add(step); - } - - // public void dispatchAddSteps(List steps) { - // ExecutionProcess slcProcess = processThread.getProcess(); - // executionModulesManager.dispatchAddSteps(slcProcess, steps); - // } - - public BlockingQueue getSteps() { - return steps; - } - - public Boolean hadAnError() { - return hadAnError; - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefSpecAttribute.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefSpecAttribute.java deleted file mode 100644 index 8e4f617c8..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefSpecAttribute.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.List; - -/** A spec attribute whose value is a reference to a full fledged object. */ -public class RefSpecAttribute extends AbstractSpecAttribute implements - Cloneable { - private static final long serialVersionUID = -3427797452955753574L; - private transient Class targetClass = String.class; - /** Read only. */ - private String targetClassName; - private transient Object value = null; - - /** List to be chosen from */ - private List choices = null; - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } - - /** Default is {@link String} */ - public Class getTargetClass() { - return targetClass; - } - - public void setTargetClass(Class targetClass) { - this.targetClass = targetClass; - this.targetClassName = targetClass.getName(); - } - - public String getTargetClassName() { - return targetClassName; - } - - /** @return can be null */ - public List getChoices() { - return choices; - } - - public void setChoices(List choices) { - this.choices = choices; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - RefSpecAttribute rsa = new RefSpecAttribute(); - rsa.setTargetClass(targetClass); - rsa.setChoices(choices); - return rsa; - } - - @Override - public String toString() { - return "Ref spec attribute [" + targetClass + "]" - + (value != null ? "=" + value : ""); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValue.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValue.java deleted file mode 100644 index 0a24bc4b4..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValue.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -/** Reference value to be used by an execution */ -public class RefValue extends AbstractExecutionValue { - private static final long serialVersionUID = -8951231456757181687L; - private String ref; - private String type; - - public RefValue() { - } - - public RefValue(String ref) { - super(); - this.ref = ref; - } - - public String getRef() { - return ref; - } - - public void setRef(String ref) { - this.ref = ref; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - @Override - public String toString() { - return "Ref Value [" + type + "=" + ref + "]"; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValueChoice.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValueChoice.java deleted file mode 100644 index 5e1f9c2ab..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValueChoice.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.Serializable; - -/** A choice of ref value to be shown to the end user. */ -public class RefValueChoice implements Serializable { - private static final long serialVersionUID = -1133645722307507774L; - private String name; - private String description; - - public RefValueChoice() { - } - - public RefValueChoice(String name, String description) { - this.name = name; - this.description = description; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/SedFilteredResource.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/SedFilteredResource.java deleted file mode 100644 index 676918e98..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/SedFilteredResource.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.FileChannel; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.io.IOUtils; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.core.io.Resource; - -/** Experimental and suboptimal */ -public class SedFilteredResource implements FactoryBean, InitializingBean { - private Resource source; - - private List filters = new ArrayList(); - private Map patterns = new HashMap(); - - private String charset = "UTF-8"; - private Charset cs; - private CharsetDecoder decoder; - - // private CharsetEncoder encoder; - - public Object getObject() throws Exception { - if (filters.size() == 0) - return source; - - // int capacity = 100 * 1024;// 100 KB - ByteBuffer bb; - if (source instanceof ByteArrayResource) { - bb = ByteBuffer.wrap(((ByteArrayResource) source).getByteArray()); - } else { - FileInputStream fis = null; - try { - File file = source.getFile(); - fis = new FileInputStream(file); - FileChannel fc = fis.getChannel(); - - // Get the file's size and then map it into memory - int sz = (int) fc.size(); - bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz); - } catch (IOException e) { - // ReadableByteChannel channel = Channels.newChannel(source - // .getInputStream()); - // bb = ByteBuffer.allocateDirect(capacity); - // int read = 0; - // do { - // read = channel.read(bb); - // } while (read > 0); - // FIXME : use nio to parse the stream as it goes - bb = ByteBuffer.wrap(IOUtils.toByteArray(source - .getInputStream())); - } finally { - IOUtils.closeQuietly(fis); - } - } - CharBuffer cb = decoder.decode(bb); - for (Pattern pattern : patterns.keySet()) { - Matcher matcher = pattern.matcher(cb); - String output = matcher.replaceAll(patterns.get(pattern)); - cb = CharBuffer.wrap(output); - } - // ByteBuffer bbout = encoder.encode(cb); - // ByteArrayOutputStream out = new ByteArrayOutputStream(capacity); - // WritableByteChannel wchannel = Channels.newChannel(out); - // wchannel.write(bbout); - ByteArrayResource res = new ByteArrayResource(cb.toString().getBytes()); - return res; - } - - public Class getObjectType() { - return Resource.class; - } - - public boolean isSingleton() { - return true; - } - - public void afterPropertiesSet() throws Exception { - cs = Charset.forName(charset); - decoder = cs.newDecoder(); - // encoder = cs.newEncoder(); - - for (String sedStr : filters) { - sedStr = sedStr.trim(); - if (sedStr.length() < 4) - throw new SlcException(sedStr + " not properly formatted."); - if (sedStr.charAt(0) != 's') - throw new SlcException(sedStr + " not properly formatted."); - Character sep = sedStr.charAt(1); - List tokens = new ArrayList(4); - StringTokenizer st = new StringTokenizer(sedStr, sep.toString()); - while (st.hasMoreTokens()) - tokens.add(st.nextToken()); - if (tokens.size() != 3 && tokens.size() != 4) - throw new SlcException(sedStr + " not properly formatted."); - patterns.put(Pattern.compile(tokens.get(1)), tokens.get(2)); - } - } - - public void setSource(Resource source) { - this.source = source; - } - - public void setFilters(List filters) { - this.filters = filters; - } - - public void setCharset(String charset) { - this.charset = charset; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java deleted file mode 100644 index 6504a3de3..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ConsoleContextDescriber.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.doc; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; - -public class ConsoleContextDescriber implements ContextDescriber { - public void describeContext(BeanDefinitionRegistry registry) { - String[] beanNames = registry.getBeanDefinitionNames(); - for (String beanName : beanNames) { - log("\n## BEAN: " + beanName); - describeBean(registry.getBeanDefinition(beanName)); - } - } - - public void describeBean(BeanDefinition beanDefinition) { - log("BeanDefinition class: "+beanDefinition.getClass()); - log("# ATTRIBUTES"); - for(String attr:beanDefinition.attributeNames()){ - log(attr+"="+beanDefinition.getAttribute(attr)); - } - log("# PROPERTIES"); - MutablePropertyValues pValues = beanDefinition.getPropertyValues(); - for (PropertyValue pv : pValues.getPropertyValues()) { - log(pv.getName() + "= (" + pv.getValue().getClass() + ") " - + pv.getValue()); - } - } - - protected void log(Object obj){ - System.out.println(obj); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ContextDescriber.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ContextDescriber.java deleted file mode 100644 index 713019b37..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/doc/ContextDescriber.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.doc; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; - -public interface ContextDescriber { - public void describeContext(BeanDefinitionRegistry registry); - public void describeBean(BeanDefinition bd); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java deleted file mode 100644 index f1e80d390..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/CompositeRunnableFactory.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.Map; - -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; - -/** - * Composite RunnableFactory, redirecting the Runnable - * creation to on of the configured RunnableFactory depending - * on an entry of the data of the RunnableDataNode. - */ -public class CompositeRunnableFactory implements RunnableFactory { - - /** - * Key used to access factory ID in the data of the RunnableDataNode - */ - private String factoryKey; - - /** - * Maps a factory ID to an ExecutionFlowFactory - */ - private Map factories; - - public void createAndRegisterRunnable(RunnableDataNode node, - BeanDefinitionRegistry beanDefinitionRegistry) { - findFactory(node).createAndRegisterRunnable(node, beanDefinitionRegistry); - } - - /** - * Finds the RunnableFactory to use for a RunnableDataNode - * @param node - * @return the RunnableFactory to use for the RunnableDataNode - */ - private RunnableFactory findFactory(RunnableDataNode node) { - // get the factory ID from the data of the RunnableDescriptor - Map data = node.getData(); - if (!data.containsKey(factoryKey)) { - throw new SlcException("No data value for key '" + factoryKey + "'"); - } - String factoryId = data.get(factoryKey).toString(); - - // see if we have a factory for the factory ID - if ((factories != null) && factories.containsKey(factoryId)) { - return factories.get(factoryId); - } - // if not, look for a bean of name equals to the factory ID - else { - throw new SlcException("Not implemented"); - } - } - - public void setFactoryKey(String factoryKey) { - this.factoryKey = factoryKey; - } - - public void setFactories(Map factories) { - this.factories = factories; - } - - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java deleted file mode 100644 index daed350b2..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/DefaultRunnableDataNode.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Default implementation of RunnableDataNode - * - */ -public class DefaultRunnableDataNode implements RunnableDataNode { - - private List children = new ArrayList(); - - private RunnableDataNode parent; - - /** - * Data of the RunnableDataNode. Does not contain - * parent data. - */ - private Map properData = new HashMap(); - - private String path; - - private String beanName; - - public boolean isLeaf() { - return children.size() == 0; - } - - public List getChildren() { - return children; - } - - public void addChild(RunnableDataNode child) { - child.setParent(this); - children.add(child); - } - - public Map getData() { - Map data = new HashMap(); - if(parent != null) { - Map parentData = parent.getData(); - if(parentData != null) { - data.putAll(parentData); - } - } - // entries defined in parentData can be overridden - // in properData - if(properData != null) { - data.putAll(properData); - } - return data; - } - - public Map getProperData() { - return properData; - } - - public void setProperData(Map properData) { - this.properData = properData; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getBeanName() { - return beanName; - } - - public void setBeanName(String beanName) { - this.beanName = beanName; - } - - public void setParent(RunnableDataNode parent) { - this.parent = parent; - } - - public RunnableDataNode getParent() { - return parent; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java deleted file mode 100644 index d9400e42e..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGenerator.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.HashMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.aop.scope.ScopedProxyUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.GenericBeanDefinition; -import org.springframework.core.Ordered; - -/** - * Generates ExecutionFlows and Runnables as - * beans in the Spring Application Context. - * Called by the Application Context as a BeanFactoryPostProcessor. - * Two kinds of beans are generated: - * RunnableCallFlow, calling a list of Runnables from the - * Application Context after configuring the ExecutionContext, - * and outputs of a RunnableFactory. - */ -public class ExecutionFlowGenerator implements BeanFactoryPostProcessor, - Ordered { - - private final Log log = LogFactory.getLog(getClass()); - - /** - * Source providing a list of RunnableCallFlowDescriptor - * used to create RunnableCallFlow and a list of - * RunnableDataNode used to create any kind of flow via a factory - */ - protected ExecutionFlowGeneratorSource source; - - /** - * Factory used to create Runnables in the Application context from - * the RunnableDataNode provided from the source. - */ - protected RunnableFactory runnableFactory; - - /** - * Bean name of the ExecutionContext. - * Used to provide the created RunnableCallFlow beans - * with a RuntimeBeanReference to - * the ExecutionContext - */ - private String executionContextBeanName = "executionContext"; - - /** - * Bean name of the context values Map. - * A bean of class HashMap is created with this name, and a - * RuntimeBeanReference is provided to the created - * RunnableCallFlow beans. - */ - private String contextValuesBeanName = "executionFlowGenerator.contextValues"; - - /** - * Prefix added to the bean names defined in each - * RunnableCallFlowDescriptor - */ - private String flowBeanNamesPrefix = ""; - - private int order = Ordered.HIGHEST_PRECEDENCE; - - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { - - // assert that the beanFactory is a BeanDefinitionRegistry - if (!(beanFactory instanceof BeanDefinitionRegistry)) { - throw new SlcException("Can only work on " - + BeanDefinitionRegistry.class); - } - - // add bean for the Context Values Map - createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory); - - // add beans for each RunnableDataNode - for(RunnableDataNode node : source.getRunnableDataNodes()) { - runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory); - } - - // add beans for each RunnableCallFlowDescriptor of the source to the application context - for (RunnableCallFlowDescriptor descriptor : source - .getRunnableCallFlowDescriptors()) { - createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory); - } - } - - /** - * Creates a RunnableCallFlow bean - * for a RunnableCallFlowDescriptor and registers - * it in the BeanDefinitionRegistry - * @param flowDescriptor - * @param registry - */ - private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) { - // create the flow bean - GenericBeanDefinition flowBean = new GenericBeanDefinition(); - flowBean.setBeanClass(RunnableCallFlow.class); - - String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName(); - - MutablePropertyValues mpv = new MutablePropertyValues(); - mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls()); - mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName)); - - mpv.addPropertyValue("name", beanName); - mpv.addPropertyValue("path", flowDescriptor.getPath()); - - mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName)); - - flowBean.setPropertyValues(mpv); - - // register it - if(log.isDebugEnabled()) { - log.debug("Registering bean definition for RunnableCallFlow " + beanName); - } - registry.registerBeanDefinition(beanName, flowBean); - } - - /** - * Creates the Context Values bean and register it in the - * BeanDefinitionRegistry - * @param registry - */ - private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) { - GenericBeanDefinition contextValuesBean = new GenericBeanDefinition(); - contextValuesBean.setBeanClass(HashMap.class); - - BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true); - registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition()); - } - - public int getOrder() { - return order; - } - - public void setOrder(int order) { - this.order = order; - } - - public void setSource(ExecutionFlowGeneratorSource source) { - this.source = source; - } - - public void setRunnableFactory(RunnableFactory runnableFactory) { - this.runnableFactory = runnableFactory; - } - - public void setExecutionContextBeanName(String executionContextBeanName) { - this.executionContextBeanName = executionContextBeanName; - } - - public void setContextValuesBeanName(String contextValuesBeanName) { - this.contextValuesBeanName = contextValuesBeanName; - } - - public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) { - this.flowBeanNamesPrefix = flowBeanNamesPrefix; - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java deleted file mode 100644 index 8d699c660..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/ExecutionFlowGeneratorSource.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.List; - -/** - * Provides 2 types of information required by an ExecutionFlowGenerator: - * a list of RunnableCallFlowDescriptor used to create RunnableCallFlow - * and a list of RunnableDataNode used to create any kind of flow via a factory. - */ -public interface ExecutionFlowGeneratorSource { - - /** - * @return a list of RunnableCallFlowDescriptor used - * by a ExecutionFlowGenerator to create RunnableCallFlow - */ - public List getRunnableCallFlowDescriptors(); - - /** - * @return a list of RunnableDataNode used - * by a ExecutionFlowGenerator to create any kind of flow via a factory - */ - public List getRunnableDataNodes(); - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCall.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCall.java deleted file mode 100644 index c3fd5f2d8..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCall.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.Map; - -/** - * Storage class for information required to call a flow - * of the Spring execution context: - * bean name of the flow, - * variables to add to the Execution Context before the call - * and variables (context values) to add to a Map - * potentially referenced by the called flow - */ -public class RunnableCall { - - /** - * Bean name of the flow to call - */ - private String beanName; - - /** - * Variables to add to the execution context before the call - */ - private Map executionVariables; - - /** - * Variables to add to the Map potentially referenced by - * the called flow - */ - private Map contextValues; - - public String getBeanName() { - return beanName; - } - - public void setBeanName(String beanName) { - this.beanName = beanName; - } - - public Map getExecutionVariables() { - return executionVariables; - } - - public void setExecutionVariables(Map executionVariables) { - this.executionVariables = executionVariables; - } - - public Map getContextValues() { - return contextValues; - } - - public void setContextValues(Map contextValues) { - this.contextValues = contextValues; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlow.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlow.java deleted file mode 100644 index 695606c21..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlow.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.DefaultExecutionSpec; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.execution.ExecutionSpec; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; - -/** - * Execution Flow calling a list of Runnable (identified by their - * bean name in the Spring Application Context) after configuring the Execution - * context and a Map potentially shared by the called Runnable - * - */ -public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware { - - private final static Log log = LogFactory.getLog(RunnableCallFlow.class); - - /** - * Key in the execution context for the index of the call (e.g. 0 for the - * first runnable called, ...) - */ - public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex"; - - /** - * Name of the flow. Also bean name - */ - private String name; - - /** - * Path of the flow - */ - private String path; - - /** - * Whether an exception in a Runnable shall stop the execution - * of the flow - */ - private Boolean failOnError = true; - - /** - * List of Runnable to call, with bean name, execution - * variables and context values - */ - private List runnableCalls; - - /** - * Map potentially referenced by called flows. Updated with the context - * values of a Runnable before calling it. - */ - private Map sharedContextValuesMap; - - /** - * ExecutionSpec of the flow. Does not contain any attribute. - */ - private ExecutionSpec executionSpec = new DefaultExecutionSpec(); - - /** - * Reference to the ExecutionContext - */ - private ExecutionContext executionContext; - - /** - * Reference to the Spring ApplicationContext. Set via - * setApplicationContext, the class implementing - * ApplicationContextAware - */ - private ApplicationContext applicationContext; - - /** - * Runs a Runnable after configuring the Execution Context and - * sharedContextValuesMap - * - * @param runnable - * the Runnable to call - * @param executionVariables - * the variables to add to the ExecutionContext - * @param contextValues - * the variables to add to sharedContextValuesMap - * @param callIndex - * index of the call (0 for the first called - * Runnable) set as variable of the - * ExecutionContext - */ - private void run(Runnable runnable, Map executionVariables, - Map contextValues, int callIndex) { - // add all variables to the Execution Context - for (Map.Entry entry : executionVariables.entrySet()) { - executionContext.setVariable(entry.getKey(), entry.getValue()); - } - - // add call Index Variable - executionContext.setVariable(VAR_CALL_INDEX, callIndex); - - // clear sharedContextValues and add all values of contextValues - if (sharedContextValuesMap != null) { - sharedContextValuesMap.clear(); - sharedContextValuesMap.putAll(contextValues); - } - - // then run the runnable - doExecuteRunnable(runnable); - } - - public void doExecuteRunnable(Runnable runnable) { - runnable.run(); - } - - /** - * Executes the flow. For each RunnableCall, the corresponding - * flow is retrieved from the Spring Application Context, the - * ExecutionContext and sharedContextValuesMap are - * configured and the Runnable is called. - */ - public void run() { - if (applicationContext == null) { - throw new SlcException("No ApplicationContext defined"); - } - - try { - for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { - RunnableCall runnableCall = runnableCalls.get(callIndex); - Object bean = applicationContext.getBean( - runnableCall.getBeanName(), Runnable.class); - if (log.isDebugEnabled()) - log.debug("Running flow '" + runnableCall.getBeanName() - + "'"); - run((Runnable) bean, runnableCall.getExecutionVariables(), - runnableCall.getContextValues(), callIndex); - } - } catch (RuntimeException e) { - if (failOnError) - throw e; - else { - log.error("Execution flow failed," - + " but process did not fail" - + " because failOnError property" - + " is set to false: " + e); - if (log.isTraceEnabled()) - e.printStackTrace(); - } - } - } - - public Iterator runnables() { - List runnables = new ArrayList(); - for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) { - RunnableCall runnableCall = runnableCalls.get(callIndex); - Object bean = applicationContext.getBean( - runnableCall.getBeanName(), Runnable.class); - runnables.add((Runnable) bean); - } - return runnables.iterator(); - } - - public Runnable getRunnable() { - if (runnableCalls.size() == 1) - return runnables().next(); - else - throw new SlcException("There are " + runnableCalls.size() - + " runnables in flow " + getName()); - } - - @Override - public String toString() { - return new StringBuffer("RunnableCallFlow ").append(name).toString(); - } - - public ExecutionSpec getExecutionSpec() { - return executionSpec; - } - - public String getName() { - return name; - } - - public Object getParameter(String key) { - throw new SlcException("RunnableCallFlow have no parameters"); - } - - public String getPath() { - return path; - } - - public Boolean isSetAsParameter(String key) { - // The ExecutionSpec having no attribute, - // always return false - return false; - } - - public void setName(String name) { - this.name = name; - } - - public void setPath(String path) { - this.path = path; - } - - public void setExecutionContext(ExecutionContext executionContext) { - this.executionContext = executionContext; - } - - public void setRunnableCalls(List runnableCalls) { - this.runnableCalls = runnableCalls; - } - - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - public void setSharedContextValuesMap(Map contextValues) { - this.sharedContextValuesMap = contextValues; - } - - public void setFailOnError(Boolean failOnError) { - this.failOnError = failOnError; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java deleted file mode 100644 index e0bbbdda9..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableCallFlowDescriptor.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.ArrayList; -import java.util.List; - -/** - * Storage Class for information required to - * instantiate a RunnableCallFlow: - * bean name of the flow, - * path of the flow - * and list of RunnableCall. - * - */ -public class RunnableCallFlowDescriptor { - - /** - * Bean name of the flow to instantiate - */ - private String beanName; - - /** - * Path of the flow to instantiate - */ - private String path; - - /** - * List of RunnableCall - */ - private List runnableCalls = new ArrayList(); - - public String getBeanName() { - return beanName; - } - - public void setBeanName(String beanName) { - this.beanName = beanName; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public List getRunnableCalls() { - return runnableCalls; - } - - public void setRunnableCalls(List runnableCalls) { - this.runnableCalls = runnableCalls; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableDataNode.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableDataNode.java deleted file mode 100644 index 51843dcd0..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableDataNode.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import java.util.List; -import java.util.Map; - -/** - * Stores information relative to a Runnable. - * Allows to structure the information as a tree, each node - * storing data as a Map. - */ -public interface RunnableDataNode { - - /** - * @return a Map containing the data associated with this node. - * Data associated with parent nodes are expected - * to be contained in the returned Map - */ - public Map getData(); - - /** - * @return the name of the bean to create. - * Can be null if no bean shall be created for the - * RunnableDataNode (e.g. is is a sub-node) - */ - public String getBeanName(); - - /** - * @return the path of the flow bean to create. - * Can be null if the bean to created is not an - * ExecutionFlow or if no bean shall be created for the - * RunnableDataNode (e.g. is is a sub-node) - */ - public String getPath(); - - /** - * @return whether the RunnableDataNode has - * children or not. - * Expected to be equivalent to getChildren().empty() - */ - public boolean isLeaf(); - - /** - * @return the list of RunnableDataNode children. - * Can be empty. Shall not be null. - */ - public List getChildren(); - - /** - * @return the RunnableDataNode parent. - * Can be null if no parent is defined (top node). - */ - public RunnableDataNode getParent(); - - /** - * Sets the RunnableDataNode parent - * @param parent - */ - public void setParent(RunnableDataNode parent); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableFactory.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableFactory.java deleted file mode 100644 index 2b3702889..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/generator/RunnableFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.generator; - -import org.springframework.beans.factory.support.BeanDefinitionRegistry; - -/** - * Interprets a RunnableDataNode by creating corresponding - * beans and registering them in a BeanDefinitionRegistry - * - */ -public interface RunnableFactory { - - public void createAndRegisterRunnable(RunnableDataNode node, - BeanDefinitionRegistry beanDefinitionRegistry); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/CloseTestResult.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/CloseTestResult.java deleted file mode 100644 index 43b296106..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/CloseTestResult.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import org.argeo.slc.test.TestResult; - -public class CloseTestResult implements Runnable { - private TestResult testResult; - - public void run() { - testResult.close(); - } - - public void setTestResult(TestResult testResult) { - this.testResult = testResult; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/Echo.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/Echo.java deleted file mode 100644 index d47149b86..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/Echo.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.io.File; -import java.io.IOException; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.core.io.Resource; - -public class Echo implements Runnable { - private final static Log defaultLog = LogFactory.getLog(Echo.class); - private Resource writeTo = null; - - private Log log; - private Object message; - - public void run() { - log().info(message); - - if (writeTo != null) { - try { - File file = writeTo.getFile(); - if (log().isDebugEnabled()) - log().debug("Write to " + file); - if (message != null) - FileUtils.writeStringToFile(file, message.toString()); - } catch (IOException e) { - throw new SlcException("Could not write to " + writeTo, e); - } - } - } - - private Log log() { - return log != null ? log : defaultLog; - } - - public void setMessage(Object message) { - this.message = message; - } - - public void setWriteTo(Resource writeTo) { - this.writeTo = writeTo; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/If.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/If.java deleted file mode 100644 index 0d22e437d..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/If.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import org.argeo.slc.SlcException; - -/** Conditional execution */ -public class If implements Runnable { - private Boolean is; - private Boolean not; - private Runnable then; - private Runnable els; - - public void run() { - if (is == null && not == null) - throw new SlcException("No condition set"); - if (is != null && not != null) - throw new SlcException("Both is and not cannot be set"); - - boolean bool = (is != null ? is : !not); - if (bool) { - if (then != null) - then.run(); - } else { - if (els != null) - els.run(); - } - - } - - public void setIs(Boolean bool) { - this.is = bool; - } - - public void setThen(Runnable then) { - this.then = then; - } - - public void setEls(Runnable els) { - this.els = els; - } - - public Boolean getNot() { - return not; - } - - public void setNot(Boolean not) { - this.not = not; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/JvmProcess.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/JvmProcess.java deleted file mode 100644 index 01f11012f..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/JvmProcess.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import org.apache.commons.io.IOUtils; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.io.Resource; - -/** A Java Virtual Machine process. */ -public class JvmProcess extends SystemCall implements InitializingBean { - private Properties systemProperties = new Properties(); - private List classpath = new ArrayList(); - private List pBootClasspath = new ArrayList(); - private Resource jvm = null; - private String mainClass; - private String mainJar; - private List jvmArgs = new ArrayList(); - private List args = new ArrayList(); - - private String systemPropertiesFileProperty = null; - private String systemPropertiesFileDir = null; - private String systemPropertiesFileName = null; - - public void afterPropertiesSet() throws Exception { - List command = new ArrayList(); - if (jvm != null) - command.add(asFile(jvm).getPath()); - else - command.add("java"); - - if (pBootClasspath.size() > 0) { - StringBuffer buf = new StringBuffer("-Xbootclasspath/p:"); - Boolean first = true; - for (Resource res : pBootClasspath) { - if (first) - first = false; - else - buf.append(File.pathSeparatorChar); - - buf.append(asFile(res)); - } - command.add(buf.toString()); - } - - for (String jvmArg : jvmArgs) { - command.add(jvmArg); - } - - if (classpath.size() > 0) { - command.add("-cp"); - StringBuffer buf = new StringBuffer(""); - for (Resource res : classpath) { - if (buf.length() != 0) - buf.append(File.pathSeparatorChar); - buf.append(asFile(res)); - } - command.add(buf.toString()); - } - - if (systemPropertiesFileProperty == null) { - // pass system properties as argument - for (Map.Entry entry : systemProperties.entrySet()) { - command.add("-D" + entry.getKey() + "=" + entry.getValue()); - } - } else { - // write system properties in a file to work around OS limitations - // with command line (e.g. Win XP) - String dir = systemPropertiesFileDir; - if (dir == null) - dir = getExecDirToUse(); - String fileName = systemPropertiesFileName; - if (fileName == null) - fileName = systemPropertiesFileProperty + ".properties"; - - // Write file - FileOutputStream fos = null; - File file = new File(dir + File.separator + fileName); - try { - - if (!file.getParentFile().exists()) - file.getParentFile().mkdirs(); - fos = new FileOutputStream(file); - systemProperties.store(fos, "Automatically generated by " - + getClass()); - command.add("-D" + systemPropertiesFileProperty + "=" - + file.getCanonicalPath()); - } catch (IOException e) { - throw new SlcException("Cannot write to system properties to " - + file, e); - } finally { - IOUtils.closeQuietly(fos); - } - } - - // Program - if (mainClass != null) { - command.add(mainClass); - } else if (mainJar != null) { - command.add("-jar"); - command.add(mainJar); - } else { - throw new SlcException("No main class or jar defined"); - } - - for (String arg : args) { - command.add(arg); - } - - setCommand(command); - } - - protected File asFile(Resource res) { - try { - return res.getFile(); - } catch (FileNotFoundException e) { - return copyToTempFile(res); - } catch (IOException e) { - throw new SlcException("Cannot convert resource to file", e); - } - - } - - protected File copyToTempFile(Resource res) { - File tempFile; - FileOutputStream fos; - try { - tempFile = File.createTempFile("slcJvmProcess-", res.getFilename()); - tempFile.deleteOnExit(); - fos = new FileOutputStream(tempFile); - IOUtils.copy(res.getInputStream(), fos); - } catch (IOException e) { - throw new SlcException("Cannot copy " + res + " to temp file.", e); - } - IOUtils.closeQuietly(fos); - return tempFile; - } - - /** Append the argument (for chaining) */ - @Override - public SystemCall arg(String arg) { - args.add(arg); - return this; - } - - /** Append the argument (for chaining) */ - @Override - public SystemCall arg(String arg, String value) { - args.add(arg); - args.add(value); - return this; - } - - public Properties getSystemProperties() { - return systemProperties; - } - - public void setSystemProperties(Properties systemProperties) { - this.systemProperties = systemProperties; - } - - public List getClasspath() { - return classpath; - } - - public void setClasspath(List classpath) { - this.classpath = classpath; - } - - public List getPBootClasspath() { - return pBootClasspath; - } - - public void setPBootClasspath(List bootClasspath) { - pBootClasspath = bootClasspath; - } - - public Resource getJvm() { - return jvm; - } - - public void setJvm(Resource jvm) { - this.jvm = jvm; - } - - public String getMainClass() { - return mainClass; - } - - public void setMainClass(String mainClass) { - this.mainClass = mainClass; - } - - public String getMainJar() { - return mainJar; - } - - public void setMainJar(String mainJar) { - this.mainJar = mainJar; - } - - public List getJvmArgs() { - return jvmArgs; - } - - public void setJvmArgs(List jvmArgs) { - this.jvmArgs = jvmArgs; - } - - public List getArgs() { - return args; - } - - public void setArgs(List args) { - this.args = args; - } - - public void setSystemPropertiesFileProperty( - String systemPropertiesFilePropertyName) { - this.systemPropertiesFileProperty = systemPropertiesFilePropertyName; - } - - public void setSystemPropertiesFileDir(String systemPropertiesFileDir) { - this.systemPropertiesFileDir = systemPropertiesFileDir; - } - - public void setSystemPropertiesFileName(String systemPropertiesFileName) { - this.systemPropertiesFileName = systemPropertiesFileName; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MergedLists.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MergedLists.java deleted file mode 100644 index ab6f59efc..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MergedLists.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.beans.factory.FactoryBean; - -/** Merge the provided lists in one single list, in the order provided. */ -public class MergedLists implements FactoryBean { - private List> lists = new ArrayList>(); - - public void setLists(List> lists) { - this.lists = lists; - } - - public Object getObject() throws Exception { - List merged = new ArrayList(); - for (List lst : lists) { - merged.addAll(lst); - } - return merged; - } - - public Class getObjectType() { - return List.class; - } - - public boolean isSingleton() { - return false; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java deleted file mode 100644 index e4fa77222..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/MethodCall.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - -public class MethodCall implements Runnable { - private Object target; - private String method; - private List args = new ArrayList(); - - public void run() { - Assert.notNull(target, "target"); - Assert.notNull(method, "method"); - Method methodRef = ReflectionUtils - .findMethod(target.getClass(), method); - if (args.size() == 0) - ReflectionUtils.invokeMethod(methodRef, target); - else - ReflectionUtils.invokeMethod(methodRef, methodRef, args.toArray()); - } - - public void setTarget(Object target) { - this.target = target; - } - - public void setMethod(String method) { - this.method = method; - } - - public void setArgs(List args) { - this.args = args; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/OverrideContextAware.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/OverrideContextAware.java deleted file mode 100644 index 9afa8468c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/OverrideContextAware.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import org.argeo.slc.SlcException; -import org.argeo.slc.core.test.context.SimpleContextAware; -import org.argeo.slc.test.context.ContextAware; - -/** - * Overrides Values and Expected values of a target - * SimpleContextAware with the corresponding - * values and expected values of a source ContextAware - * - */ -public class OverrideContextAware implements Runnable { - - private ContextAware source; - - private SimpleContextAware target; - - /** - * Whether an exception shall be thrown if a value - * or expected value of the source is not defined - * in the target - */ - private Boolean failIfUndefinedInSource = true; - - public void run() { - // override values - if(source.getValues() != null) - for(String key : source.getValues().keySet()) { - if(failIfUndefinedInSource && !target.getValues().containsKey(key)) { - throw new SlcException("No entry in target values for key '" + key + "'"); - } - target.getValues().put(key, source.getValues().get(key)); - } - - // override expected values - if(source.getExpectedValues() != null) - for(String key : source.getExpectedValues().keySet()) { - if(failIfUndefinedInSource && !target.getExpectedValues().containsKey(key)) { - throw new SlcException("No entry in target expected values for key '" + key + "'"); - } - target.getExpectedValues().put(key, source.getExpectedValues().get(key)); - } - } - - public void setSource(ContextAware source) { - this.source = source; - } - - public void setTarget(SimpleContextAware target) { - this.target = target; - } - - public void setFailIfUndefinedInSource(Boolean failIfUndefinedInSource) { - this.failIfUndefinedInSource = failIfUndefinedInSource; - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java deleted file mode 100644 index 04da5242f..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import javax.security.auth.callback.CallbackHandler; - -import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.DefaultExecutor; -import org.apache.commons.exec.ExecuteException; -import org.apache.commons.exec.ExecuteResultHandler; -import org.apache.commons.exec.ExecuteStreamHandler; -import org.apache.commons.exec.ExecuteWatchdog; -import org.apache.commons.exec.Executor; -import org.apache.commons.exec.LogOutputStream; -import org.apache.commons.exec.PumpStreamHandler; -import org.apache.commons.exec.ShutdownHookProcessDestroyer; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.UnsupportedException; -import org.argeo.slc.core.execution.ExecutionResources; -import org.argeo.slc.core.test.SimpleResultPart; -import org.argeo.slc.test.TestResult; -import org.argeo.slc.test.TestStatus; -import org.springframework.core.io.Resource; -import org.springframework.security.Authentication; -import org.springframework.security.context.SecurityContextHolder; - -/** Execute an OS specific system call. */ -public class SystemCall implements Runnable { - public final static String LOG_STDOUT = "System.out"; - - private final Log log = LogFactory.getLog(getClass()); - - private String execDir; - - private String cmd = null; - private List command = null; - - private Executor executor = new DefaultExecutor(); - private Boolean synchronous = true; - - private String stdErrLogLevel = "ERROR"; - private String stdOutLogLevel = "INFO"; - - private Resource stdOutFile = null; - private Resource stdErrFile = null; - - private Resource stdInFile = null; - /** - * If no {@link #stdInFile} provided, writing to this stream will write to - * the stdin of the process. - */ - private OutputStream stdInSink = null; - - private Boolean redirectStdOut = false; - - private List outputListeners = Collections - .synchronizedList(new ArrayList()); - - private Map> osCommands = new HashMap>(); - private Map osCmds = new HashMap(); - private Map environmentVariables = new HashMap(); - - private Boolean logCommand = false; - private Boolean redirectStreams = true; - private Boolean exceptionOnFailed = true; - private Boolean mergeEnvironmentVariables = true; - - private Authentication authentication; - - private String osConsole = null; - private String generateScript = null; - - /** 24 hours */ - private Long watchdogTimeout = 24 * 60 * 60 * 1000l; - - private TestResult testResult; - - private ExecutionResources executionResources; - - /** Sudo the command, as root if empty or as user if not. */ - private String sudo = null; - // TODO make it more secure and robust, test only once - private final String sudoPrompt = UUID.randomUUID().toString(); - private String askPassProgram = "/usr/libexec/openssh/ssh-askpass"; - private boolean firstLine = true; - private CallbackHandler callbackHandler; - /** Chroot to the this path (must not be empty) */ - private String chroot = null; - - // Current - /** Current watchdog, null if process is completed */ - ExecuteWatchdog currentWatchdog = null; - - /** Empty constructor */ - public SystemCall() { - - } - - /** - * Constructor based on the provided command list. - * - * @param command - * the command list - */ - public SystemCall(List command) { - this.command = command; - } - - /** - * Constructor based on the provided command. - * - * @param cmd - * the command. If the provided string contains no space a - * command list is initialized with the argument as first - * component (useful for chained construction) - */ - public SystemCall(String cmd) { - if (cmd.indexOf(' ') < 0) { - command = new ArrayList(); - command.add(cmd); - } else { - this.cmd = cmd; - } - } - - /** Executes the system call. */ - public void run() { - authentication = SecurityContextHolder.getContext().getAuthentication(); - - // Manage streams - Writer stdOutWriter = null; - OutputStream stdOutputStream = null; - Writer stdErrWriter = null; - InputStream stdInStream = null; - if (stdOutFile != null) - if (redirectStdOut) - stdOutputStream = createOutputStream(stdOutFile); - else - stdOutWriter = createWriter(stdOutFile, true); - - if (stdErrFile != null) { - stdErrWriter = createWriter(stdErrFile, true); - } else { - if (stdOutFile != null && !redirectStdOut) - stdErrWriter = createWriter(stdOutFile, true); - } - - try { - if (stdInFile != null) - stdInStream = stdInFile.getInputStream(); - else { - stdInStream = new PipedInputStream(); - stdInSink = new PipedOutputStream( - (PipedInputStream) stdInStream); - } - } catch (IOException e2) { - throw new SlcException("Cannot open a stream for " + stdInFile, e2); - } - - if (log.isTraceEnabled()) { - log.debug("os.name=" + System.getProperty("os.name")); - log.debug("os.arch=" + System.getProperty("os.arch")); - log.debug("os.version=" + System.getProperty("os.version")); - } - - // Execution directory - File dir = new File(getExecDirToUse()); - // if (!dir.exists()) - // dir.mkdirs(); - - // Watchdog to check for lost processes - Executor executorToUse; - if (executor != null) - executorToUse = executor; - else - executorToUse = new DefaultExecutor(); - executorToUse.setWatchdog(createWatchdog()); - - if (redirectStreams) { - // Redirect standard streams - executorToUse.setStreamHandler(createExecuteStreamHandler( - stdOutWriter, stdOutputStream, stdErrWriter, stdInStream)); - } else { - // Dummy stream handler (otherwise pump is used) - executorToUse.setStreamHandler(new DummyexecuteStreamHandler()); - } - - executorToUse.setProcessDestroyer(new ShutdownHookProcessDestroyer()); - executorToUse.setWorkingDirectory(dir); - - // Command line to use - final CommandLine commandLine = createCommandLine(); - if (logCommand) - log.info("Execute command:\n" + commandLine - + "\n in working directory: \n" + dir + "\n"); - - // Env variables - Map environmentVariablesToUse = null; - environmentVariablesToUse = new HashMap(); - if (mergeEnvironmentVariables) - environmentVariablesToUse.putAll(System.getenv()); - if (environmentVariables.size() > 0) - environmentVariablesToUse.putAll(environmentVariables); - - // Execute - ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); - - // - // THE EXECUTION PROPER - // - try { - if (synchronous) - try { - int exitValue = executorToUse.execute(commandLine, - environmentVariablesToUse); - executeResultHandler.onProcessComplete(exitValue); - } catch (ExecuteException e1) { - if (e1.getExitValue() == Executor.INVALID_EXITVALUE) { - Thread.currentThread().interrupt(); - return; - } - // Sleep 1s in order to make sure error logs are flushed - Thread.sleep(1000); - executeResultHandler.onProcessFailed(e1); - } - else - executorToUse.execute(commandLine, environmentVariablesToUse, - executeResultHandler); - } catch (SlcException e) { - throw e; - } catch (Exception e) { - throw new SlcException("Could not execute command " + commandLine, - e); - } finally { - IOUtils.closeQuietly(stdOutWriter); - IOUtils.closeQuietly(stdErrWriter); - IOUtils.closeQuietly(stdInStream); - IOUtils.closeQuietly(stdInSink); - } - - } - - public synchronized String function() { - final StringBuffer buf = new StringBuffer(""); - SystemCallOutputListener tempOutputListener = new SystemCallOutputListener() { - private Long lineCount = 0l; - - public void newLine(SystemCall systemCall, String line, - Boolean isError) { - if (!isError) { - if (lineCount != 0l) - buf.append('\n'); - buf.append(line); - lineCount++; - } - } - }; - addOutputListener(tempOutputListener); - run(); - removeOutputListener(tempOutputListener); - return buf.toString(); - } - - public String asCommand() { - return createCommandLine().toString(); - } - - @Override - public String toString() { - return asCommand(); - } - - /** - * Build a command line based on the properties. Can be overridden by - * specific command wrappers. - */ - protected CommandLine createCommandLine() { - // Check if an OS specific command overrides - String osName = System.getProperty("os.name"); - List commandToUse = null; - if (osCommands.containsKey(osName)) - commandToUse = osCommands.get(osName); - else - commandToUse = command; - String cmdToUse = null; - if (osCmds.containsKey(osName)) - cmdToUse = osCmds.get(osName); - else - cmdToUse = cmd; - - CommandLine commandLine = null; - - // Which command definition to use - if (commandToUse == null && cmdToUse == null) - throw new SlcException("Please specify a command."); - else if (commandToUse != null && cmdToUse != null) - throw new SlcException( - "Specify the command either as a line or as a list."); - else if (cmdToUse != null) { - if (chroot != null && !chroot.trim().equals("")) - cmdToUse = "chroot \"" + chroot + "\" " + cmdToUse; - if (sudo != null) { - environmentVariables.put("SUDO_ASKPASS", askPassProgram); - if (!sudo.trim().equals("")) - cmdToUse = "sudo -p " + sudoPrompt + " -u " + sudo + " " - + cmdToUse; - else - cmdToUse = "sudo -p " + sudoPrompt + " " + cmdToUse; - } - - // GENERATE COMMAND LINE - commandLine = CommandLine.parse(cmdToUse); - } else if (commandToUse != null) { - if (commandToUse.size() == 0) - throw new SlcException("Command line is empty."); - - if (chroot != null && sudo != null) { - commandToUse.add(0, "chroot"); - commandToUse.add(1, chroot); - } - - if (sudo != null) { - environmentVariables.put("SUDO_ASKPASS", askPassProgram); - commandToUse.add(0, "sudo"); - commandToUse.add(1, "-p"); - commandToUse.add(2, sudoPrompt); - if (!sudo.trim().equals("")) { - commandToUse.add(3, "-u"); - commandToUse.add(4, sudo); - } - } - - // GENERATE COMMAND LINE - commandLine = new CommandLine(commandToUse.get(0).toString()); - - for (int i = 1; i < commandToUse.size(); i++) { - if (log.isTraceEnabled()) - log.debug(commandToUse.get(i)); - commandLine.addArgument(commandToUse.get(i).toString()); - } - } else { - // all cases covered previously - throw new UnsupportedException(); - } - - if (generateScript != null) { - File scriptFile = new File(getExecDirToUse() + File.separator - + generateScript); - try { - FileUtils.writeStringToFile(scriptFile, - (osConsole != null ? osConsole + " " : "") - + commandLine.toString()); - } catch (IOException e) { - throw new SlcException("Could not generate script " - + scriptFile, e); - } - commandLine = new CommandLine(scriptFile); - } else { - if (osConsole != null) - commandLine = CommandLine.parse(osConsole + " " - + commandLine.toString()); - } - - return commandLine; - } - - /** - * Creates a {@link PumpStreamHandler} which redirects streams to the custom - * logging mechanism. - */ - protected ExecuteStreamHandler createExecuteStreamHandler( - final Writer stdOutWriter, final OutputStream stdOutputStream, - final Writer stdErrWriter, final InputStream stdInStream) { - - // Log writers - OutputStream stdout = stdOutputStream != null ? stdOutputStream - : new LogOutputStream() { - protected void processLine(String line, int level) { - // if (firstLine) { - // if (sudo != null && callbackHandler != null - // && line.startsWith(sudoPrompt)) { - // try { - // PasswordCallback pc = new PasswordCallback( - // "sudo password", false); - // Callback[] cbs = { pc }; - // callbackHandler.handle(cbs); - // char[] pwd = pc.getPassword(); - // char[] arr = Arrays.copyOf(pwd, - // pwd.length + 1); - // arr[arr.length - 1] = '\n'; - // IOUtils.write(arr, stdInSink); - // stdInSink.flush(); - // } catch (Exception e) { - // throw new SlcException( - // "Cannot retrieve sudo password", e); - // } - // } - // firstLine = false; - // } - - if (line != null && !line.trim().equals("")) - logStdOut(line); - - if (stdOutWriter != null) - appendLineToFile(stdOutWriter, line); - } - }; - - OutputStream stderr = new LogOutputStream() { - protected void processLine(String line, int level) { - if (line != null && !line.trim().equals("")) - logStdErr(line); - if (stdErrWriter != null) - appendLineToFile(stdErrWriter, line); - } - }; - - PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, - stderr, stdInStream) { - - @Override - public void stop() { - // prevents the method to block when joining stdin - if (stdInSink != null) - IOUtils.closeQuietly(stdInSink); - - super.stop(); - } - }; - return pumpStreamHandler; - } - - /** Creates the default {@link ExecuteResultHandler}. */ - protected ExecuteResultHandler createExecuteResultHandler( - final CommandLine commandLine) { - return new ExecuteResultHandler() { - - public void onProcessComplete(int exitValue) { - String msg = "System call '" + commandLine - + "' properly completed."; - if (log.isTraceEnabled()) - log.trace(msg); - if (testResult != null) { - forwardPath(testResult); - testResult.addResultPart(new SimpleResultPart( - TestStatus.PASSED, msg)); - } - releaseWatchdog(); - } - - public void onProcessFailed(ExecuteException e) { - - String msg = "System call '" + commandLine + "' failed."; - if (testResult != null) { - forwardPath(testResult); - testResult.addResultPart(new SimpleResultPart( - TestStatus.ERROR, msg, e)); - } else { - if (exceptionOnFailed) - throw new SlcException(msg, e); - else - log.error(msg, e); - } - releaseWatchdog(); - } - }; - } - - @Deprecated - protected void forwardPath(TestResult testResult) { - // TODO: allocate a TreeSPath - } - - /** - * Shortcut method getting the execDir to use - */ - protected String getExecDirToUse() { - try { - if (execDir != null) { - return execDir; - } - return System.getProperty("user.dir"); - } catch (Exception e) { - throw new SlcException("Cannot find exec dir", e); - } - } - - protected void logStdOut(String line) { - for (SystemCallOutputListener outputListener : outputListeners) - outputListener.newLine(this, line, false); - log(stdOutLogLevel, line); - } - - protected void logStdErr(String line) { - for (SystemCallOutputListener outputListener : outputListeners) - outputListener.newLine(this, line, true); - log(stdErrLogLevel, line); - } - - /** Log from the underlying streams. */ - protected void log(String logLevel, String line) { - // TODO optimize - if (SecurityContextHolder.getContext().getAuthentication() == null) { - SecurityContextHolder.getContext() - .setAuthentication(authentication); - } - - if ("ERROR".equals(logLevel)) - log.error(line); - else if ("WARN".equals(logLevel)) - log.warn(line); - else if ("INFO".equals(logLevel)) - log.info(line); - else if ("DEBUG".equals(logLevel)) - log.debug(line); - else if ("TRACE".equals(logLevel)) - log.trace(line); - else if (LOG_STDOUT.equals(logLevel)) - System.out.println(line); - else if ("System.err".equals(logLevel)) - System.err.println(line); - else - throw new SlcException("Unknown log level " + logLevel); - } - - /** Append line to a log file. */ - protected void appendLineToFile(Writer writer, String line) { - try { - writer.append(line).append('\n'); - } catch (IOException e) { - log.error("Cannot write to log file", e); - } - } - - /** Creates the writer for the output/err files. */ - protected Writer createWriter(Resource target, Boolean append) { - FileWriter writer = null; - try { - - final File file; - if (executionResources != null) - file = new File(executionResources.getAsOsPath(target, true)); - else - file = target.getFile(); - writer = new FileWriter(file, append); - } catch (IOException e) { - log.error("Cannot get file for " + target, e); - IOUtils.closeQuietly(writer); - } - return writer; - } - - /** Creates an outputstream for the output/err files. */ - protected OutputStream createOutputStream(Resource target) { - FileOutputStream out = null; - try { - - final File file; - if (executionResources != null) - file = new File(executionResources.getAsOsPath(target, true)); - else - file = target.getFile(); - out = new FileOutputStream(file, false); - } catch (IOException e) { - log.error("Cannot get file for " + target, e); - IOUtils.closeQuietly(out); - } - return out; - } - - /** Append the argument (for chaining) */ - public SystemCall arg(String arg) { - if (command == null) - command = new ArrayList(); - command.add(arg); - return this; - } - - /** Append the argument (for chaining) */ - public SystemCall arg(String arg, String value) { - if (command == null) - command = new ArrayList(); - command.add(arg); - command.add(value); - return this; - } - - // CONTROL - public synchronized Boolean isRunning() { - return currentWatchdog != null; - } - - private synchronized ExecuteWatchdog createWatchdog() { -// if (currentWatchdog != null) -// throw new SlcException("A process is already being monitored"); - currentWatchdog = new ExecuteWatchdog(watchdogTimeout); - return currentWatchdog; - } - - private synchronized void releaseWatchdog() { - currentWatchdog = null; - } - - public synchronized void kill() { - if (currentWatchdog != null) - currentWatchdog.destroyProcess(); - } - - /** */ - public void setCmd(String command) { - this.cmd = command; - } - - public void setCommand(List command) { - this.command = command; - } - - public void setExecDir(String execdir) { - this.execDir = execdir; - } - - public void setStdErrLogLevel(String stdErrLogLevel) { - this.stdErrLogLevel = stdErrLogLevel; - } - - public void setStdOutLogLevel(String stdOutLogLevel) { - this.stdOutLogLevel = stdOutLogLevel; - } - - public void setSynchronous(Boolean synchronous) { - this.synchronous = synchronous; - } - - public void setOsCommands(Map> osCommands) { - this.osCommands = osCommands; - } - - public void setOsCmds(Map osCmds) { - this.osCmds = osCmds; - } - - public void setEnvironmentVariables(Map environmentVariables) { - this.environmentVariables = environmentVariables; - } - - public Map getEnvironmentVariables() { - return environmentVariables; - } - - public void setWatchdogTimeout(Long watchdogTimeout) { - this.watchdogTimeout = watchdogTimeout; - } - - public void setStdOutFile(Resource stdOutFile) { - this.stdOutFile = stdOutFile; - } - - public void setStdErrFile(Resource stdErrFile) { - this.stdErrFile = stdErrFile; - } - - public void setStdInFile(Resource stdInFile) { - this.stdInFile = stdInFile; - } - - public void setTestResult(TestResult testResult) { - this.testResult = testResult; - } - - public void setLogCommand(Boolean logCommand) { - this.logCommand = logCommand; - } - - public void setRedirectStreams(Boolean redirectStreams) { - this.redirectStreams = redirectStreams; - } - - public void setExceptionOnFailed(Boolean exceptionOnFailed) { - this.exceptionOnFailed = exceptionOnFailed; - } - - public void setMergeEnvironmentVariables(Boolean mergeEnvironmentVariables) { - this.mergeEnvironmentVariables = mergeEnvironmentVariables; - } - - public void setOsConsole(String osConsole) { - this.osConsole = osConsole; - } - - public void setGenerateScript(String generateScript) { - this.generateScript = generateScript; - } - - public void setExecutionResources(ExecutionResources executionResources) { - this.executionResources = executionResources; - } - - public void setRedirectStdOut(Boolean redirectStdOut) { - this.redirectStdOut = redirectStdOut; - } - - public void addOutputListener(SystemCallOutputListener outputListener) { - outputListeners.add(outputListener); - } - - public void removeOutputListener(SystemCallOutputListener outputListener) { - outputListeners.remove(outputListener); - } - - public void setOutputListeners( - List outputListeners) { - this.outputListeners = outputListeners; - } - - public void setExecutor(Executor executor) { - this.executor = executor; - } - - public void setSudo(String sudo) { - this.sudo = sudo; - } - - public void setCallbackHandler(CallbackHandler callbackHandler) { - this.callbackHandler = callbackHandler; - } - - public void setChroot(String chroot) { - this.chroot = chroot; - } - - private class DummyexecuteStreamHandler implements ExecuteStreamHandler { - - public void setProcessErrorStream(InputStream is) throws IOException { - } - - public void setProcessInputStream(OutputStream os) throws IOException { - } - - public void setProcessOutputStream(InputStream is) throws IOException { - } - - public void start() throws IOException { - } - - public void stop() { - } - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java deleted file mode 100644 index b28f1ade2..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/SystemCallOutputListener.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -public interface SystemCallOutputListener { - public void newLine(SystemCall systemCall, String line, Boolean isError); -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/UploadAttachments.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/UploadAttachments.java deleted file mode 100644 index 13cc51918..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/tasks/UploadAttachments.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.argeo.slc.SlcException; -import org.argeo.slc.core.attachment.Attachment; -import org.argeo.slc.core.attachment.AttachmentUploader; -import org.argeo.slc.core.attachment.AttachmentsEnabled; -import org.springframework.core.io.Resource; - -public class UploadAttachments implements Runnable { - private AttachmentUploader attachmentUploader; - private Attachment attachment = null; - private Resource resource = null; - private Map attachments = new HashMap(); - private List attachTo = new ArrayList(); - private Boolean newUuidPerExecution = true; - - public void run() { - if (attachment != null) { - if (resource == null) - throw new SlcException("A resource must be specified."); - uploadAndAdd(attachment, resource); - } - - for (Attachment attachmentT : attachments.keySet()) { - Resource resourceT = attachments.get(attachmentT); - uploadAndAdd(attachmentT, resourceT); - } - - } - - protected void uploadAndAdd(Attachment attachment, Resource resource) { - if (newUuidPerExecution) - attachment.setUuid(UUID.randomUUID().toString()); - attachmentUploader.upload(attachment, resource); - for (AttachmentsEnabled attachmentsEnabled : attachTo) { - attachmentsEnabled.addAttachment(attachment); - } - } - - public void setAttachmentUploader(AttachmentUploader attachmentUploader) { - this.attachmentUploader = attachmentUploader; - } - - public void setAttachments(Map attachments) { - this.attachments = attachments; - } - - public void setAttachTo(List attachTo) { - this.attachTo = attachTo; - } - - public void setAttachment(Attachment attachment) { - this.attachment = attachment; - } - - public void setResource(Resource resource) { - this.resource = resource; - } - - public void setNewUuidPerExecution(Boolean newUuidPerExecution) { - this.newUuidPerExecution = newUuidPerExecution; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/AsFlowDecorator.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/AsFlowDecorator.java deleted file mode 100644 index ecdf5b56a..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/AsFlowDecorator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.DefaultExecutionFlow; -import org.argeo.slc.execution.ExecutionFlow; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.xml.BeanDefinitionDecorator; -import org.springframework.beans.factory.xml.ParserContext; -import org.w3c.dom.Attr; -import org.w3c.dom.Node; - -/** Publishes a {@link Runnable} as an {@link ExecutionFlow} */ -public class AsFlowDecorator implements BeanDefinitionDecorator { - private Log log = LogFactory.getLog(AsFlowDecorator.class); - - @SuppressWarnings("unchecked") - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder bean, - ParserContext ctx) { - String attrValue = ((Attr) node).getValue(); - if (attrValue.charAt(attrValue.length() - 1) == '/') - throw new SlcException(attrValue + " cannot end with a path"); - final String flowBeanName = attrValue; - - if (log.isTraceEnabled()) - log.trace("flowBeanName=" + flowBeanName); - - if (ctx.getRegistry().containsBeanDefinition(flowBeanName)) - throw new SlcException("A bean named " + flowBeanName - + " is already defined."); - BeanDefinitionBuilder flow = BeanDefinitionBuilder - .rootBeanDefinition(DefaultExecutionFlow.class); - ManagedList executables = new ManagedList(1); - - String beanName = bean.getBeanName(); - if (beanName == null) - executables.add(bean.getBeanDefinition()); - else - executables.add(new RuntimeBeanReference(beanName)); - - // if (path != null) - // flow.addPropertyValue("path", path); - flow.addPropertyValue("executables", executables); - - if (beanName != null) - ctx.getRegistry().registerBeanDefinition(flowBeanName, - flow.getBeanDefinition()); - return bean; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java deleted file mode 100644 index dfca9d512..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ExecutionScopeDecorator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.springframework.aop.scope.ScopedProxyUtils; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.parsing.BeanComponentDefinition; -import org.springframework.beans.factory.xml.BeanDefinitionDecorator; -import org.springframework.beans.factory.xml.ParserContext; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * Inspired by org.springframework.aop.config.ScopedProxyBeanDefinitionDecorator - */ -public class ExecutionScopeDecorator implements BeanDefinitionDecorator { - private static final String PROXY_TARGET_CLASS = "proxy-target-class"; - - public BeanDefinitionHolder decorate(Node node, - BeanDefinitionHolder definition, ParserContext parserContext) { - - definition.getBeanDefinition().setScope("execution"); - - // Default: CGLib not used - boolean proxyTargetClass = false; - if (node instanceof Element) { - Element ele = (Element) node; - if (ele.hasAttribute(PROXY_TARGET_CLASS)) { - proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)).booleanValue(); - } - } - - // Register the original bean definition as it will be referenced by the scoped proxy and is relevant for tooling (validation, navigation). - String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName()); - parserContext.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName)); - - return ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java deleted file mode 100644 index ca64d12f5..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.DefaultExecutionFlow; -import org.argeo.slc.execution.ExecutionFlow; -import org.springframework.beans.factory.BeanDefinitionStoreException; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.support.ManagedMap; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** Interprets the tag */ -public class FlowBeanDefinitionParser extends - AbstractSingleBeanDefinitionParser { - private Log log = LogFactory.getLog(FlowBeanDefinitionParser.class); - - /** Whether the user has already be warned on path attribute usage. */ - private Boolean warnedAboutPathAttribute = false; - - @SuppressWarnings("unchecked") - @Override - protected void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder) { - String path = element.getAttribute("path"); - if (StringUtils.hasText(path)) { - builder.addPropertyValue("path", path); - - // warns user only once - if (!warnedAboutPathAttribute) - log.warn("The path=\"\" attribute is deprecated" - + " and will be removed in a later release." - + " Use ."); - warnedAboutPathAttribute = true; - } - - String spec = element.getAttribute("spec"); - if (StringUtils.hasText(spec)) - builder.getBeanDefinition().getConstructorArgumentValues() - .addGenericArgumentValue(new RuntimeBeanReference(spec)); - - String abstrac = element.getAttribute("abstract"); - if (StringUtils.hasText(abstrac)) - builder.setAbstract(Boolean.parseBoolean(abstrac)); - - String parent = element.getAttribute("parent"); - if (StringUtils.hasText(parent)) - builder.setParentName(parent); - - builder.getBeanDefinition().setDescription( - DomUtils.getChildElementValueByTagName(element, "description")); - - List argsElems = new ArrayList(); - List execElems = new ArrayList(); - List specElems = new ArrayList(); - NodeList nodeList = element.getChildNodes(); - for (int i = 0; i < nodeList.getLength(); i++) { - Node node = nodeList.item(i); - if (node instanceof Element) { - if (DomUtils.nodeNameEquals(node, "arg")) - argsElems.add((Element) node); - else if (DomUtils.nodeNameEquals(node, "spec")) - specElems.add((Element) node); - else if (!DomUtils.nodeNameEquals(node, "description")) - execElems.add((Element) node); - } - } - - // Arguments - if (argsElems.size() != 0) { - ManagedMap args = new ManagedMap(argsElems.size()); - for (Element argElem : argsElems) { - Object value = NamespaceUtils.parseValue(argElem, - parserContext, builder.getBeanDefinition(), null); - if (value != null) - args.put(argElem.getAttribute("name"), value); - else - throw new SlcException("No value defined."); - } - builder.getBeanDefinition().getConstructorArgumentValues() - .addGenericArgumentValue(args); - } - - // Execution specs - if (StringUtils.hasText(spec) && specElems.size() != 0) - throw new SlcException("A flow cannot have multiple specs"); - if (specElems.size() == 1) { - Object specObj = NamespaceUtils.parseBeanOrReference( - specElems.get(0), parserContext, - builder.getBeanDefinition()); - builder.getBeanDefinition().getConstructorArgumentValues() - .addGenericArgumentValue(specObj); - } else if (specElems.size() > 1) - throw new SlcException("A flow cannot have multiple specs"); - - // Executables - if (execElems.size() != 0) { - ManagedList executables = new ManagedList(execElems.size()); - for (Element child : execElems) { - // child validity check is performed in xsd - executables.add(NamespaceUtils.parseBeanOrReference(child, - parserContext, builder.getBeanDefinition())); - } - if (executables.size() > 0) - builder.addPropertyValue("executables", executables); - } - } - - @SuppressWarnings("unchecked") - @Override - protected Class getBeanClass(Element element) { - String clss = element.getAttribute("class"); - if (StringUtils.hasText(clss)) - // TODO: check that it actually works - try { - return (Class) getClass() - .getClassLoader().loadClass(clss); - } catch (ClassNotFoundException e) { - try { - return (Class) Thread - .currentThread().getContextClassLoader() - .loadClass(clss); - } catch (ClassNotFoundException e1) { - throw new SlcException("Cannot load class " + clss, e); - } - } - else - return DefaultExecutionFlow.class; - } - - // parse nested bean definition - // private Object parseBeanReference(Element element, - // ParserContext parserContext, BeanDefinitionBuilder builder) { - // return parserContext.getDelegate().parsePropertySubElement(element, - // builder.getBeanDefinition()); - // } - - @Override - protected String resolveId(Element element, - AbstractBeanDefinition definition, ParserContext parserContext) - throws BeanDefinitionStoreException { - String name = element.getAttribute("name"); - if (StringUtils.hasText(name)) { - return name; - } else { - return super.resolveId(element, definition, parserContext); - } - } - - protected boolean shouldGenerateIdAsFallback() { - return true; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java deleted file mode 100644 index 2deba8bb2..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.springframework.beans.factory.xml.NamespaceHandlerSupport; - -public class FlowNamespaceHandler extends NamespaceHandlerSupport { - - public void init() { - registerBeanDefinitionParser("flow", new FlowBeanDefinitionParser()); - registerBeanDefinitionParser("spec", new SpecBeanDefinitionParser()); - registerBeanDefinitionDecoratorForAttribute("as-flow", - new AsFlowDecorator()); - registerBeanDefinitionParser("param", new ParamDecorator()); - - // The objective was to replace - // - attribute scope="execution" - // - and element "aop:scoped-proxy" - // by a single attribute, using an attribute decorator - // this does not work correctly with other attribute decorators (e.g. - // p namespace) since this decorator needs to be called after all - // properties have been set on target bean. - // It works properly with element decorators (called after all attribute - // decorators - registerBeanDefinitionDecorator("variable", new ExecutionScopeDecorator()); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/NamespaceUtils.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/NamespaceUtils.java deleted file mode 100644 index ccf94f131..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/NamespaceUtils.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * Utilities to simplify common tasks when interpreting a custom namespace and - * converting it into bean definitions. - */ -public class NamespaceUtils { - // private final static Log log = LogFactory.getLog(NamespaceUtils.class); - - /** - * Returns the value defined either: directly by the the 'value' attribute, - * as reference by the 'ref' attribute or as a nested bean. - */ - public static Object parseValue(Element element, - ParserContext parserContext, - BeanDefinition containingBeanDefintion, String valueTagName) { - Object value = null; - if (element.hasAttribute("value")) { - value = element.getAttribute("value"); - } - - if (element.hasAttribute("ref")) { - if (value != null) - throw new SlcException("Multiple value definition for " - + element); - value = new RuntimeBeanReference(element.getAttribute("ref")); - } - - Element uniqueSubElem = null; - if (valueTagName != null) { - Element valueElem = DomUtils.getChildElementByTagName(element, - valueTagName); - if (valueElem != null) { - uniqueSubElem = findUniqueSubElement(valueElem); - if (uniqueSubElem == null) - throw new SlcException("No subelement found under " - + valueElem); - } - } else {// no intermediary tag - uniqueSubElem = findUniqueSubElement(element); - } - - if (uniqueSubElem != null) { - if (value != null) - throw new SlcException("Multiple value definition for " - + element); - value = parseBeanOrReference(uniqueSubElem, parserContext, - containingBeanDefintion); - } - return value; - } - - public static Element findUniqueSubElement(Element element) { - NodeList childNodes = element.getChildNodes(); - - Element uniqueSubElem = null; - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if (node != null && node instanceof Element) { - if (uniqueSubElem == null) - uniqueSubElem = (Element) node; - else - throw new SlcException( - "There are more than one sub element under " - + element); - } - } - return uniqueSubElem; - } - - public static Object parseBeanOrReference(Element element, - ParserContext parserContext, BeanDefinition beanDefinition) { - // return parserContext.getDelegate().parsePropertySubElement(element, - // beanDefinition); - - BeanDefinitionParserDelegate deleg = parserContext.getDelegate(); - // if ("bean".equals(element.getNodeName())) - // return deleg.parseBeanDefinitionElement(element, beanDefinition); - // else - return deleg.parsePropertySubElement(element, beanDefinition); - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ParamDecorator.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ParamDecorator.java deleted file mode 100644 index 16839c042..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/ParamDecorator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.argeo.slc.core.execution.ParameterRef; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; -import org.w3c.dom.Element; - -public class ParamDecorator extends AbstractSingleBeanDefinitionParser { - - // public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder - // bean, - // ParserContext ctx) { - // String paramName = ((Element) node).getAttribute("name"); - // String propertyName = ((Element) node.getParentNode()) - // .getAttribute("name"); - // BeanDefinitionBuilder parameterRef = BeanDefinitionBuilder - // .genericBeanDefinition(ParameterRef.class); - // parameterRef.addPropertyReference("instantiationManager", - // "instantiationManager"); - // parameterRef.addConstructorArgValue(paramName); - // bean.getBeanDefinition().getPropertyValues().addPropertyValue( - // propertyName, parameterRef.getBeanDefinition()); - // return bean; - // } - - @Override - protected void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder) { - String paramName = element.getAttribute("name"); - - String instantationManagerRef = element - .getAttribute("instantiationManager"); - if (!StringUtils.hasText(instantationManagerRef)) - instantationManagerRef = "instantiationManager"; - builder.addPropertyReference("instantiationManager", - instantationManagerRef); - builder.addConstructorArgValue(paramName); - } - - @Override - protected Class getBeanClass(Element element) { - return ParameterRef.class; - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java deleted file mode 100644 index 4ef3f9788..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.execution.DefaultExecutionSpec; -import org.argeo.slc.core.execution.PrimitiveSpecAttribute; -import org.argeo.slc.core.execution.RefSpecAttribute; -import org.argeo.slc.core.execution.RefValueChoice; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.support.ManagedMap; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; - -/** Interprets the tag */ -public class SpecBeanDefinitionParser extends - AbstractSingleBeanDefinitionParser { - private Log log = LogFactory.getLog(SpecBeanDefinitionParser.class); - - @SuppressWarnings("unchecked") - @Override - protected void doParse(Element element, ParserContext parserContext, - BeanDefinitionBuilder builder) { - builder.getBeanDefinition().setDescription( - DomUtils.getChildElementValueByTagName(element, "description")); - - ManagedMap attributes = new ManagedMap(); - - // Primitives - for (Element child : (List) DomUtils - .getChildElementsByTagName(element, "primitive")) { - BeanDefinitionBuilder childBuilder = BeanDefinitionBuilder - .genericBeanDefinition(PrimitiveSpecAttribute.class); - addCommonProperties(child, parserContext, childBuilder); - - String type = child.getAttribute("type"); - if (StringUtils.hasText(type)) - childBuilder.addPropertyValue("type", type); - - putInAttributes(attributes, child, - childBuilder.getBeanDefinition(), "primitive"); - } - - // Refs - for (Element refAttrElem : (List) DomUtils - .getChildElementsByTagName(element, "ref")) { - BeanDefinitionBuilder refAttrBuilder = BeanDefinitionBuilder - .genericBeanDefinition(RefSpecAttribute.class); - addCommonProperties(refAttrElem, parserContext, refAttrBuilder); - - String targetClassName = refAttrElem.getAttribute("targetClass"); - if (StringUtils.hasText(targetClassName)) - refAttrBuilder.addPropertyValue("targetClass", targetClassName); - - // Choices - Element choicesElem = DomUtils.getChildElementByTagName( - refAttrElem, "choices"); - if (choicesElem != null) { - List choices = DomUtils.getChildElementsByTagName( - choicesElem, "choice"); - ManagedList choiceBeans = new ManagedList(choices.size()); - for (Element choiceElem : choices) { - BeanDefinitionBuilder choiceBuilder = BeanDefinitionBuilder - .genericBeanDefinition(RefValueChoice.class); - choiceBuilder.addPropertyValue("name", - choiceElem.getAttribute("name")); - String desc = choiceElem.getAttribute("description"); - if (StringUtils.hasText(desc)) - choiceBuilder.addPropertyValue("description", desc); - - choiceBeans.add(choiceBuilder.getBeanDefinition()); - } - refAttrBuilder.addPropertyValue("choices", choiceBeans); - } - - putInAttributes(attributes, refAttrElem, - refAttrBuilder.getBeanDefinition(), "ref"); - } - - builder.addPropertyValue("attributes", attributes); - } - - protected void addCommonProperties(Element element, - ParserContext parserContext, BeanDefinitionBuilder specAttr) { - addBooleanProperty("isImmutable", specAttr, element); - addBooleanProperty("isConstant", specAttr, element); - addBooleanProperty("isHidden", specAttr, element); - addBooleanProperty("isParameter", specAttr, element); - addBooleanProperty("isFrozen", specAttr, element); - - Object value = NamespaceUtils.parseValue(element, parserContext, - specAttr.getBeanDefinition(), "value"); - if (value != null) - specAttr.addPropertyValue("value", value); - - } - - @SuppressWarnings("unchecked") - protected void putInAttributes(ManagedMap attributes, Element child, - BeanDefinition beanDefinition, String nature) { - String name = child.getAttribute("name"); - attributes.put(name, beanDefinition); - if (log.isTraceEnabled()) - log.debug("Added " + nature + " attribute " + name); - - } - - private void addBooleanProperty(String name, - BeanDefinitionBuilder specAttr, Element element) { - String bool = element.getAttribute(name); - if (StringUtils.hasText(bool)) - specAttr.addPropertyValue(name, Boolean.parseBoolean(bool)); - - } - - @Override - protected Class getBeanClass(Element element) { - return DefaultExecutionSpec.class; - } - - protected boolean shouldGenerateIdAsFallback() { - return false; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestData.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestData.java deleted file mode 100644 index 39a97f290..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestData.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import org.argeo.slc.test.TestData; - -public class BasicTestData implements TestData { - private Object expected; - private Object reached; - - public Object getExpected() { - return expected; - } - - public void setExpected(Object expected) { - this.expected = expected; - } - - public Object getReached() { - return reached; - } - - public void setReached(Object reached) { - this.reached = reached; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java deleted file mode 100644 index 6b92135e8..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/BasicTestDefinition.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import org.argeo.slc.SlcException; -import org.argeo.slc.core.test.context.ContextUtils; -import org.argeo.slc.test.IncompatibleTestDataException; -import org.argeo.slc.test.TestData; -import org.argeo.slc.test.TestDefinition; -import org.argeo.slc.test.TestResult; -import org.argeo.slc.test.TestRun; -import org.argeo.slc.test.TestStatus; -import org.argeo.slc.test.context.ContextAware; - -/** Understands basic test data and context aware test data. */ -public class BasicTestDefinition implements TestDefinition { - - public void execute(TestRun testRun) { - if (testRun. getTestData() instanceof BasicTestData) { - BasicTestData testData = testRun.getTestData(); - TestResult result = testRun.getTestResult(); - - if (result == null) - throw new SlcException("No test result defined."); - - try { - if (testData.getExpected().equals(testData.getReached())) { - result.addResultPart(new SimpleResultPart( - TestStatus.PASSED, "Reached and expected equals")); - } else { - result.addResultPart(new SimpleResultPart( - TestStatus.FAILED, "Expected " - + testData.getExpected() + " but reached " - + testData.getReached())); - } - } catch (Exception e) { - result.addResultPart(new SimpleResultPart(TestStatus.ERROR, - "Could not compare", e)); - } - } else if (testRun. getTestData() instanceof ContextAware) { - TestData testData = testRun.getTestData(); - ContextUtils.compareReachedExpected((ContextAware) testData, - testRun.getTestResult()); - } else { - throw new IncompatibleTestDataException(testRun); - } - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java deleted file mode 100644 index 8ad81af1c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleResultPart.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import java.io.Serializable; - -import org.argeo.slc.test.TestResultPart; -import org.argeo.slc.test.TestRun; -import org.argeo.slc.test.TestRunAware; -import org.argeo.slc.test.TestStatus; - -/** - *

- * Basic implementation of a result part, implementing the standard three status - * approach for test results. - *

- * - * @see TestStatus - */ -public class SimpleResultPart implements TestResultPart, TestStatus, - TestRunAware, Serializable { - private static final long serialVersionUID = 6669675957685071901L; - - private Long tid; - - private String testRunUuid; - - /** The status. Default to ERROR since it should always be explicitely set. */ - private Integer status = ERROR; - private String message; - private String exceptionMessage; - - public SimpleResultPart() { - } - - public SimpleResultPart(Integer status, String message) { - this(status, message, null); - } - - public SimpleResultPart(Integer status, String message, Exception exception) { - this.status = status; - this.message = message; - setException(exception); - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public void setStatus(Integer status) { - this.status = status; - } - - public Integer getStatus() { - return status; - } - - public String getExceptionMessage() { - return exceptionMessage; - } - - public void setException(Exception exception) { - if (exception == null) - return; - - StringBuffer buf = new StringBuffer(""); - buf.append(exception.toString()); - buf.append('\n'); - for (StackTraceElement elem : exception.getStackTrace()) { - buf.append('\t').append(elem.toString()).append('\n'); - } - - if (exception.getCause() != null) - addRootCause(buf, exception.getCause()); - - this.exceptionMessage = buf.toString(); - } - - protected void addRootCause(StringBuffer buf, Throwable cause) { - if (cause == null) - return; - - buf.append("Caused by: " + cause.getMessage()); - for (StackTraceElement elem : cause.getStackTrace()) { - buf.append('\t').append(elem.toString()).append('\n'); - } - - if (cause.getCause() != null) { - addRootCause(buf, cause.getCause()); - } - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(""); - buf.append(SlcTestUtils.statusToString(status)); - if (status == PASSED || status == FAILED) { - buf.append(' '); - } else if (status == ERROR) { - buf.append(" "); - } - buf.append(message); - return buf.toString(); - } - - /** @deprecated */ - Long getTid() { - return tid; - } - - /** @deprecated */ - void setTid(Long tid) { - this.tid = tid; - } - - public String getTestRunUuid() { - return testRunUuid; - } - - /** For ORM */ - public void setTestRunUuid(String testRunUuid) { - this.testRunUuid = testRunUuid; - } - - public void notifyTestRun(TestRun testRun) { - testRunUuid = testRun.getUuid(); - } - - public void setExceptionMessage(String exceptionMessage) { - this.exceptionMessage = exceptionMessage; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java deleted file mode 100644 index 5fca5a9d7..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestResult.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.UUID; -import java.util.Vector; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.argeo.slc.SlcException; -import org.argeo.slc.test.TestResult; -import org.argeo.slc.test.TestResultPart; -import org.argeo.slc.test.TestRun; - -/** - * Basic implementation of a test result containing only a list of result parts. - */ -public class SimpleTestResult implements TestResult { - private static Log log = LogFactory.getLog(SimpleTestResult.class); - - private String uuid; - private String currentTestRunUuid; - - private Boolean throwError = true; - - private Date closeDate; - private List parts = new Vector(); - - private Map attributes = new TreeMap(); - - public void addResultPart(TestResultPart part) { - if (throwError && part.getStatus() == ERROR) { - throw new SlcException( - "There was an error in the underlying test: " - + part.getExceptionMessage()); - } - parts.add(part); - if (log.isDebugEnabled()) - log.debug(part); - } - - public void close() { - parts.clear(); - closeDate = new Date(); - } - - public List getParts() { - return parts; - } - - public Date getCloseDate() { - return closeDate; - } - - public void setThrowError(Boolean throwError) { - this.throwError = throwError; - } - - public void notifyTestRun(TestRun testRun) { - currentTestRunUuid = testRun.getUuid(); - } - - public String getUuid() { - if (uuid == null) { - uuid = UUID.randomUUID().toString(); - } - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getCurrentTestRunUuid() { - return currentTestRunUuid; - } - - public Map getAttributes() { - return attributes; - } - - public void setAttributes(Map attributes) { - this.attributes = attributes; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java deleted file mode 100644 index 4f6a12f81..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SimpleTestRun.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import java.util.UUID; - -import org.argeo.slc.deploy.DeployedSystem; -import org.argeo.slc.test.ExecutableTestRun; -import org.argeo.slc.test.TestData; -import org.argeo.slc.test.TestDefinition; -import org.argeo.slc.test.TestResult; -import org.argeo.slc.test.WritableTestRun; - -/** - * A basic bean implementation of a WritableTestRun, holding - * references to the various parts of a test run. - */ -public class SimpleTestRun implements WritableTestRun, ExecutableTestRun { - private String uuid; - - // private String slcExecutionUuid; - // private String slcExecutionStepUuid; - - private DeployedSystem deployedSystem; - private TestData testData; - private TestDefinition testDefinition; - private TestResult testResult; - - /** Executes the underlying test definition. */ - public void run() { - uuid = UUID.randomUUID().toString(); - if (testResult != null) - testResult.notifyTestRun(this); - - testDefinition.execute(this); - } - - @SuppressWarnings("unchecked") - public T getDeployedSystem() { - return (T) deployedSystem; - } - - public void setDeployedSystem(DeployedSystem deployedSystem) { - this.deployedSystem = deployedSystem; - } - - @SuppressWarnings("unchecked") - public T getTestData() { - return (T) testData; - } - - public void setTestData(TestData testData) { - this.testData = testData; - } - - @SuppressWarnings("unchecked") - public T getTestDefinition() { - return (T) testDefinition; - } - - public void setTestDefinition(TestDefinition testDefinition) { - this.testDefinition = testDefinition; - } - - @SuppressWarnings("unchecked") - public T getTestResult() { - return (T) testResult; - } - - public void setTestResult(TestResult testResult) { - this.testResult = testResult; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - // public String getSlcExecutionUuid() { - // return slcExecutionUuid; - // } - // - // public void setSlcExecutionUuid(String slcExecutionUuid) { - // this.slcExecutionUuid = slcExecutionUuid; - // } - // - // public String getSlcExecutionStepUuid() { - // return slcExecutionStepUuid; - // } - // - // public void setSlcExecutionStepUuid(String slcExecutionStepUuid) { - // this.slcExecutionStepUuid = slcExecutionStepUuid; - // } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java deleted file mode 100644 index c926a691d..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/SlcTestUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import org.argeo.slc.SlcException; -import org.argeo.slc.test.TestStatus; - -public abstract class SlcTestUtils { - public static String statusToString(Integer status) { - if (status.equals(TestStatus.PASSED)) { - return TestStatus.STATUSSTR_PASSED; - } else if (status.equals(TestStatus.FAILED)) { - return TestStatus.STATUSSTR_FAILED; - } else if (status.equals(TestStatus.ERROR)) { - return TestStatus.STATUSSTR_ERROR; - } else { - throw new SlcException("Unrecognized status " + status); - } - } - - public static Integer stringToStatus(String statusStr) { - if (statusStr.equals(TestStatus.STATUSSTR_PASSED)) { - return TestStatus.PASSED; - } else if (statusStr.equals(TestStatus.STATUSSTR_FAILED)) { - return TestStatus.FAILED; - } else if (statusStr.equals(TestStatus.STATUSSTR_ERROR)) { - return TestStatus.ERROR; - } else { - throw new SlcException("Unrecognized status string " + statusStr); - } - } - - private SlcTestUtils() { - - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/TestDataUtils.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/TestDataUtils.java deleted file mode 100644 index b32da3801..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/TestDataUtils.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test; - -import org.argeo.slc.UnsupportedException; -import org.argeo.slc.test.TestData; -import org.argeo.slc.test.TestDataProvider; - -/** Utilities for dealing with test datas. */ -public class TestDataUtils { - /** Extracts the test data from the given provider. */ - public static T getFromProvider(Object obj, - Class clss, String key) { - if (obj instanceof TestDataProvider) { - TestDataProvider testDataProvider = (TestDataProvider) obj; - return testDataProvider.getTestData(clss, key); - } else { - throw new UnsupportedException("test data provider", obj); - } - } - - /** - * Extracts the test data from the given provider using null - * as key. - */ - public static T getFromProvider(Object obj, - Class clss) { - return getFromProvider(obj, clss, null); - } - - /** - * Returns it self after making the proper checks. Used for test data being - * their own data providers. - */ - @SuppressWarnings("unchecked") - public static T getItSelf(Class clss, - TestData testDataObject) { - if (clss.isAssignableFrom(testDataObject.getClass())) { - return (T) testDataObject; - } else { - throw new UnsupportedException("test data", testDataObject); - } - - } - - /** Makes sure this is an utility class. */ - private TestDataUtils() { - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java deleted file mode 100644 index f62fb5ca3..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/ContextUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import java.util.Map; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.test.SimpleResultPart; -import org.argeo.slc.test.TestResult; -import org.argeo.slc.test.TestStatus; -import org.argeo.slc.test.context.ContextAware; -import org.argeo.slc.test.context.ParentContextAware; - -/** Utilities for comparing and synchronising contexts. */ -public class ContextUtils { - private final static Log log = LogFactory.getLog(ContextUtils.class); - - public static void compareReachedExpected(ContextAware contextAware, - TestResult testResult) { - for (String key : contextAware.getExpectedValues().keySet()) { - - // Compare expected values with reached ones - Object expectedValue = contextAware.getExpectedValues().get(key); - - if (expectedValue.toString().equals( - contextAware.getContextSkipFlag())) { - if (log.isDebugEnabled()) - log.debug("Skipped check for key '" + key + "'"); - continue; - } - - if (contextAware.getValues().containsKey(key)) { - Object reachedValue = contextAware.getValues().get(key); - - if (expectedValue.equals(contextAware.getContextAnyFlag())) { - testResult.addResultPart(new SimpleResultPart( - TestStatus.PASSED, "Expected any value for key '" - + key + "'")); - } else if (expectedValue.equals(reachedValue)) { - testResult.addResultPart(new SimpleResultPart( - TestStatus.PASSED, "Values matched for key '" + key - + "'")); - } else { - testResult.addResultPart(new SimpleResultPart( - TestStatus.FAILED, "Mismatch for key '" + key - + "': expected '" + expectedValue - + "' but reached '" + reachedValue + "'")); - } - } else { - testResult.addResultPart(new SimpleResultPart( - TestStatus.FAILED, "No value reached for key '" + key - + "'")); - } - } - } - - /** - * Makes sure that all children and sub-children of parent share the same - * maps for values and expected values. - */ - public static void synchronize(ParentContextAware parent) { - Map expectedValuesCommon = new TreeMap( - parent.getExpectedValues()); - synchronize(parent, expectedValuesCommon); - if (log.isDebugEnabled()) - log.debug("Synchronized context " + parent); - - } - - private static void synchronize(ParentContextAware parent, - Map expectedValuesCommon) { - for (ContextAware child : parent.getChildContexts()) { - // Values - putNotContained(parent.getValues(), child.getValues()); - child.setValues(parent.getValues()); - - // Expected Values - // Expected values reference is not overridden: each child has its - // own expected values map. - overrideContained(expectedValuesCommon, child.getExpectedValues()); - - // Creates a new Map in order not to disturb other context using the - // same keys - Map expectedValuesCommonChild = new TreeMap( - expectedValuesCommon); - putNotContained(expectedValuesCommonChild, - child.getExpectedValues()); - - if (child instanceof ParentContextAware) { - // Recursive sync - synchronize((ParentContextAware) child, - expectedValuesCommonChild); - } - } - - } - - /** - * Put into common map the values from child map which are not already - * defined in common map. - */ - public static void putNotContained(Map commonMap, - Map childMap) { - for (String key : childMap.keySet()) { - if (!commonMap.containsKey(key)) { - commonMap.put(key, childMap.get(key)); - } - } - } - - /** Overrides child map values with the values already set in common map */ - public static void overrideContained(Map commonMap, - Map childMap) { - for (String key : childMap.keySet()) { - if (commonMap.containsKey(key)) { - childMap.put(key, commonMap.get(key)); - } - } - } - - /** Makes sure this cannot be instantiated. */ - private ContextUtils() { - - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java deleted file mode 100644 index ca0bf5ffb..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/DefaultContextTestData.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import org.argeo.slc.core.test.TestDataUtils; -import org.argeo.slc.test.TestData; -import org.argeo.slc.test.TestDataProvider; - -public class DefaultContextTestData extends SimpleContextAware implements - TestData, TestDataProvider { - - public T getTestData(Class clss, String key) { - return TestDataUtils.getItSelf(clss, this); - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java deleted file mode 100644 index 8ed38720c..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleContextAware.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import java.util.Map; -import java.util.TreeMap; - -import org.springframework.beans.factory.InitializingBean; - -import org.argeo.slc.SlcException; -import org.argeo.slc.test.context.ContextAware; -import org.argeo.slc.test.context.ParentContextAware; - -public class SimpleContextAware implements ContextAware, InitializingBean { - private ParentContextAware parentContext; - - private Map values = new TreeMap(); - private Map expectedValues = new TreeMap(); - - private String contextSkipFlag = DEFAULT_SKIP_FLAG; - private String contextAnyFlag = DEFAULT_ANY_FLAG; - - public Map getValues() { - return values; - } - - public void setValues(Map values) { - this.values = values; - } - - public Map getExpectedValues() { - return expectedValues; - } - - public void setExpectedValues(Map expectedValues) { - this.expectedValues = expectedValues; - } - - /** Used to add this context as a child by setting a property. */ - public void setParentContext(ParentContextAware parentContextAware) { - if (parentContext != null) - throw new SlcException("Parent context already set"); - this.parentContext = parentContextAware; - this.parentContext.addChildContext(this); - } - - protected ParentContextAware getParentContext() { - return parentContext; - } - - public void afterPropertiesSet() throws Exception { - if (parentContext != null) { - ContextUtils.synchronize(parentContext); - } - } - - public String getContextSkipFlag() { - return contextSkipFlag; - } - - public void setContextSkipFlag(String contextSkipFlag) { - this.contextSkipFlag = contextSkipFlag; - } - - public String getContextAnyFlag() { - return contextAnyFlag; - } - - public void setContextAnyFlag(String contextAnyFlag) { - this.contextAnyFlag = contextAnyFlag; - } - -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java deleted file mode 100644 index b8abf7fde..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/SimpleParentContextAware.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import java.util.Collection; -import java.util.List; -import java.util.Vector; - -import org.argeo.slc.test.context.ContextAware; -import org.argeo.slc.test.context.ParentContextAware; -import org.springframework.beans.factory.InitializingBean; - -public class SimpleParentContextAware extends SimpleContextAware implements - ParentContextAware, InitializingBean { - private List children = new Vector(); - - public Collection getChildContexts() { - return children; - } - - public void addChildContext(ContextAware contextAware) { - children.add(contextAware); - } - - @Override - public void afterPropertiesSet() throws Exception { - if (getParentContext() != null) { - // If has a parent, sync it. - super.afterPropertiesSet(); - } else { - if (children.size() > 0) { - // No need to synchronize if no children - ContextUtils.synchronize(this); - } - } - } -} diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/package.html b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/package.html deleted file mode 100644 index cd08d63f3..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/context/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -Context variables to be passed between parts of tests. - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/package.html b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/package.html deleted file mode 100644 index c70d2d151..000000000 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/test/package.html +++ /dev/null @@ -1,6 +0,0 @@ - - - -SLC Test: test of software systems. - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/defaults.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/defaults.xml deleted file mode 100644 index d84ba10eb..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/defaults.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/runtime.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/runtime.xml deleted file mode 100644 index 990d85cb2..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/runtime.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - Bare minimal runtime configuration. In general you will - want to use simple.xml instead. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/simple.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/simple.xml deleted file mode 100644 index b25f3d130..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/simple.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - Default Capabilities - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/specs.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/specs.xml deleted file mode 100644 index 7cc960475..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/specs.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/spring.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/spring.xml deleted file mode 100644 index de1c06b1e..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/spring.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - Simple runtime enriched with defaults and templates used - to simplify XML files. These templates have been deprecated by the - custom XML namespace and will be removed in SLC 2.x. Use the XML - namespace instead. - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/tasks/core.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/tasks/core.xml deleted file mode 100644 index df35944ee..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/tasks/core.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/templates.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/templates.xml deleted file mode 100644 index 28b742af7..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/templates.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/utils.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/utils.xml deleted file mode 100644 index 527e701f6..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/utils.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd deleted file mode 100644 index 8b31a60bf..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd +++ /dev/null @@ -1,384 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd deleted file mode 100644 index a70798f2d..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-1.2.xsd +++ /dev/null @@ -1,402 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/spring.xml b/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/spring.xml deleted file mode 100644 index 31cf67167..000000000 --- a/runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/test/spring.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/deploy/DefaultResourceSetTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/deploy/DefaultResourceSetTest.java deleted file mode 100644 index 15fb42903..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/deploy/DefaultResourceSetTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.deploy; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.test.context.AbstractInternalSpringTestCase; -import org.springframework.core.io.Resource; - -public class DefaultResourceSetTest extends AbstractInternalSpringTestCase { - private final static Log log = LogFactory - .getLog(DefaultResourceSetTest.class); - - public void testListResources() { - DefaultResourceSet rrs = getBean("relativeResourceSet"); - Map res = rrs.listResources(); - for (String relativePath : res.keySet()) - log.debug(relativePath + "=" + res.get(relativePath)); - assertEquals(2, res.size()); - } - - @Override - protected String getApplicationContextLocation() { - return inPackage("relativeResourceSet.xml"); - } - -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java deleted file mode 100644 index 7cc8705f5..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.test.SimpleTestResult; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.test.TestResultPart; -import org.argeo.slc.test.TestStatus; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -public abstract class AbstractExecutionFlowTestCase extends TestCase { - - protected final Log log = LogFactory.getLog(getClass()); - - protected void logException(Throwable ex) { - log.info("Got Exception of class " + ex.getClass().toString() - + " with message '" + ex.getMessage() + "'."); - } - - protected void validateTestResult(SimpleTestResult testResult) { - validateTestResult(testResult, TestStatus.PASSED); - } - - protected void validateTestResult(SimpleTestResult testResult, - int expectedStatus) { - for (TestResultPart part : testResult.getParts()) { - if (part.getStatus() != expectedStatus) { - fail("Error found in TestResult: " + part.getMessage()); - } - } - } - - protected ConfigurableApplicationContext createApplicationContext( - String applicationContextSuffix) { - ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext( - inPackage(applicationContextSuffix)); - // applicationContext.start(); - return applicationContext; - } - - protected void configureAndExecuteSlcFlow(String applicationContextSuffix, - String beanName) { - ConfigurableApplicationContext applicationContext = createApplicationContext(applicationContextSuffix); - ExecutionFlow executionFlow = (ExecutionFlow) applicationContext - .getBean(beanName); - executionFlow.run(); - applicationContext.close(); - } - - protected String inPackage(String suffix) { - String prefix = getClass().getPackage().getName().replace('.', '/'); - return prefix + '/' + suffix; - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/BasicExecutionFlowTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/BasicExecutionFlowTest.java deleted file mode 100644 index 91be3bdbe..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/BasicExecutionFlowTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.util.HashMap; -import java.util.Map; - -import org.argeo.slc.core.test.SimpleTestResult; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.test.TestStatus; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.ConfigurableApplicationContext; - -public class BasicExecutionFlowTest extends AbstractExecutionFlowTestCase { - // TO TEST - // - post-processing for @{} replacement in beans with complex properties - // - bean of scope other than execution are not resolved at execution - - // public void testMyTest() throws Exception { - // ConfigurableApplicationContext applicationContext = - // createApplicationContext("test.xml"); - // log.info("Start Execution"); - // ((ExecutionFlow) applicationContext.getBean("flow1")).execute(); - // applicationContext.close(); - // } - - public void testSpecOverriding() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("specOverriding.xml"); - ((ExecutionFlow) applicationContext.getBean("flow2")).run(); - SimpleTestResult res = (SimpleTestResult) applicationContext - .getBean("myTestResult"); - validateTestResult(res); - } - - public void testMultipleFlows() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("multipleFlow.xml"); - ((ExecutionFlow) applicationContext.getBean("flow1")).run(); - SimpleTestResult res = (SimpleTestResult) applicationContext - .getBean("myTestResult"); - validateTestResult(res); - res.getParts().clear(); - ((ExecutionFlow) applicationContext.getBean("flow2")).run(); - validateTestResult(res, TestStatus.FAILED); - applicationContext.close(); - } - - /** - * Test placeholder resolution in a context without scope execution or proxy - * and with cascading flows (the flow A contains the flow B) - * - * @throws Exception - */ - public void testPlaceHolders() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml"); - ((ExecutionFlow) applicationContext.getBean("flowA")).run(); - validateTestResult((SimpleTestResult) applicationContext - .getBean("myTestResult")); - applicationContext.close(); - } - - /** - * Test placeholder resolution in a context without scope execution or proxy - * and with cascading flows (the flow A contains the flow B) setting - * execution values (should have no effect) - * - * @throws Exception - */ - public void testPlaceHoldersWithExecutionValues() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml"); - - ExecutionContext executionContext = (ExecutionContext) applicationContext - .getBean("executionContext"); - Map executionParameters = new HashMap(); - executionParameters.put("p1", "e1"); - executionParameters.put("p2", "e2"); - executionParameters.put("p3", "e3"); - executionParameters.put("p4", "e4"); - executionParameters.put("p5", "e5"); - executionParameters.put("p6", "e6"); - executionParameters.put("p7", "e7"); - executionParameters.put("p8", "e8"); - addVariables(executionContext, executionParameters); - - ((ExecutionFlow) applicationContext.getBean("flowA")).run(); - validateTestResult((SimpleTestResult) applicationContext - .getBean("myTestResult")); - applicationContext.close(); - } - - public void testPlaceHoldersExec() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.exec.xml"); - - ExecutionContext executionContext = (ExecutionContext) applicationContext - .getBean("executionContext"); - Map executionParameters = new HashMap(); - executionParameters.put("p1", "e1"); - executionParameters.put("p2", "e2"); - executionParameters.put("p3", "e3"); - executionParameters.put("p4", "e4"); - executionParameters.put("p5", "e5"); - executionParameters.put("p6", "e6"); - addVariables(executionContext, executionParameters); - - ((ExecutionFlow) applicationContext.getBean("flowA")).run(); - validateTestResult((SimpleTestResult) applicationContext - .getBean("myTestResult")); - applicationContext.close(); - } - - public void testCanonicFlowParameters() throws Exception { - configureAndExecuteSlcFlow("canonic-001.xml", "canonic.001"); - } - - public void testCanonicDefaultValues() throws Exception { - configureAndExecuteSlcFlow("canonic-002.xml", "canonic.002"); - } - - public void testCanonicMissingValues() throws Exception { - try { - configureAndExecuteSlcFlow("canonic-003.error.xml", "canonic.003"); - fail("Parameter not set - should be rejected."); - } catch (BeanCreationException e) { - // exception expected - logException(e); - } - } - - public void testCanonicUnknownParameter() throws Exception { - try { - configureAndExecuteSlcFlow("canonic-004.error.xml", "canonic.004"); - fail("Unknown parameter set - should be rejected."); - } catch (BeanCreationException e) { - // exception expected - logException(e); - } - } - - public void testListSetMap() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMap.xml"); - ExecutionFlow executionFlow = (ExecutionFlow) applicationContext - .getBean("myFlow"); - executionFlow.run(); - - validateTestResult((SimpleTestResult) applicationContext - .getBean("myTestResult")); - - // BasicTestData res = (BasicTestData) - // applicationContext.getBean("cascadingComplex.testData"); - // log.info("res=" + res.getReached().toString()); - - applicationContext.close(); - } - - public void testListSetMapMultipleFlows() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMapMultipleFlow.xml"); - ((ExecutionFlow) applicationContext.getBean("flow1")).run(); - SimpleTestResult res = (SimpleTestResult) applicationContext - .getBean("myTestResult"); - validateTestResult(res); - res.getParts().clear(); - ((ExecutionFlow) applicationContext.getBean("flow2")).run(); - validateTestResult(res, TestStatus.FAILED); - applicationContext.close(); - } - - protected void addVariables(ExecutionContext executionContext, - Map vars) { - for (String key : vars.keySet()) - executionContext.setVariable(key, vars.get(key)); - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/DefaultAgentCliTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/DefaultAgentCliTest.java deleted file mode 100644 index a7d9b8b78..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/DefaultAgentCliTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.argeo.slc.core.execution; - -import java.net.URI; -import java.util.List; - -import junit.framework.TestCase; - -public class DefaultAgentCliTest extends TestCase { - public void testArgsToUris() { - String[] args = { "org.argeo.slc.demo.minimal", "HelloWorld/WithVar", - "--testKey", "555" }; - List uris = DefaultAgentCli.asURIs(args); - assertEquals(1, uris.size()); - assertEquals( - "flow:/org.argeo.slc.demo.minimal/HelloWorld/WithVar?testKey=555", - uris.get(0).toString()); - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java deleted file mode 100644 index 55afdc0c8..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ExceptionIfInitCalledTwice.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.InitializingBean; - -public class ExceptionIfInitCalledTwice implements Runnable, InitializingBean { - private final static Log log = LogFactory - .getLog(ExceptionIfInitCalledTwice.class); - - private Boolean calledOnce = false; - - public void run() { - log.info(getClass().getSimpleName() + " ran properly"); - } - - public void afterPropertiesSet() throws Exception { - log.info(getClass().getSimpleName() + " init method called"); - - if (calledOnce) - throw new SlcException(getClass().getSimpleName() - + "init method called twice."); - else - calledOnce = true; - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java deleted file mode 100644 index 8b3d2ec25..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesSpringTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; - -public class FileExecutionResourcesSpringTest extends - AbstractExecutionFlowTestCase { - private String basePath = FileExecutionResources.DEFAULT_EXECUTION_RESOURCES_TMP_PATH; - - public void testSimple() throws Exception { - File file = getFile("subdir/writeTo"); - try { - assertFalse(file.exists()); - configureAndExecuteSlcFlow("executionResources.xml", - "executionResources.simple"); - assertTrue(file.exists()); - } finally { - file.deleteOnExit(); - } - } - - public void testPlaceholderPass() throws Exception { - File file = getFile("subdir/60"); - try { - assertFalse(file.exists()); - configureAndExecuteSlcFlow("executionResources.xml", - "executionResources.placeholderPass"); - assertTrue(file.exists()); - } finally { - file.deleteOnExit(); - } - } - - /** - * Test that it generate the wrong file because of issue when using - * execution placeholder in contructor-arg - */ - public void testPlaceholderFail() throws Exception { - File file = getFile("subdir/@{var}"); - try { - assertFalse(file.exists()); - configureAndExecuteSlcFlow("executionResources.xml", - "executionResources.placeholderFail"); - assertTrue(file.exists()); - } finally { - file.deleteOnExit(); - } - } - - protected File getFile(String relativePath) { - return new File(basePath + File.separator - + relativePath.replace('/', File.separatorChar)); - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesTest.java deleted file mode 100644 index e2dae6564..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/FileExecutionResourcesTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import java.io.File; - -import junit.framework.TestCase; - -import org.apache.commons.io.FileUtils; -import org.argeo.slc.execution.ExecutionContext; -import org.springframework.core.io.Resource; - -public class FileExecutionResourcesTest extends TestCase { - public void testGetWritableFile() throws Exception { - FileExecutionResources executionResources = new FileExecutionResources(); - ExecutionContext executionContext = new MapExecutionContext(); - executionResources.setExecutionContext(executionContext); - - String expected = "TEST"; - String reached = ""; - try { - // Resource - Resource resource = executionResources - .getWritableResource("subdir1/textRes.txt"); - assertTrue(resource.getFile().getParentFile().exists()); - assertFalse(resource.getFile().exists()); - FileUtils.writeStringToFile(resource.getFile(), expected); - reached = FileUtils.readFileToString(resource.getFile()); - assertEquals(expected, reached); - - // File - File file = executionResources.getFile("subdir2/textFile.txt"); - assertFalse(file.getParentFile().exists()); - assertFalse(file.exists()); - FileUtils.writeStringToFile(file, expected); - reached = FileUtils.readFileToString(file); - assertEquals(expected, reached); - } finally { - if (executionResources.getBaseDir() != null - && executionResources.getBaseDir().exists()) - FileUtils.deleteDirectory(executionResources.getBaseDir()); - } - - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ParameterRefTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ParameterRefTest.java deleted file mode 100644 index 35df7eb53..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/ParameterRefTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution; - -import org.argeo.slc.core.test.SimpleTestResult; -import org.argeo.slc.execution.ExecutionFlow; -import org.argeo.slc.test.TestStatus; -import org.springframework.context.ConfigurableApplicationContext; - -public class ParameterRefTest extends AbstractExecutionFlowTestCase { - public void test001() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("parameterRef.xml"); - ((ExecutionFlow) applicationContext.getBean("parameterRef.001")).run(); - - SimpleTestResult res = (SimpleTestResult) applicationContext - .getBean("parameterRef.testResult"); - assertEquals(res.getParts().get(0).getStatus(), TestStatus.PASSED); - assertEquals(res.getParts().get(1).getStatus(), TestStatus.FAILED); - - applicationContext.close(); - } - -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/tasks/SystemCallTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/tasks/SystemCallTest.java deleted file mode 100644 index 8301b8517..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/tasks/SystemCallTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.tasks; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase; - -public class SystemCallTest extends AbstractExecutionFlowTestCase { - private final static Log log = LogFactory.getLog(SystemCallTest.class); - - private final String defFile = "systemCall.xml"; - - public void testSystemCallSimple() throws Exception { - if (isOsSupported()) - configureAndExecuteSlcFlow(defFile, "systemCallSimple"); - } - - public void testSystemCallList() throws Exception { - if (isOsSupported()) - configureAndExecuteSlcFlow(defFile, "systemCallList"); - } - - public void testSystemCallOsSpecific() throws Exception { - if (isOsSupported()) - configureAndExecuteSlcFlow(defFile, "systemCallOsSpecific"); - } - - public void testSystemCallWithVar() throws Exception { - if (isOsSupported()) - configureAndExecuteSlcFlow(defFile, "systemCallWithVar"); - } - - protected boolean isOsSupported() { - String osName = System.getProperty("os.name"); - final Boolean ret; - if (osName.contains("Windows")) - ret = false; - else - ret = true; - - if (ret == false) - log.warn("Skip test because OS '" + osName + "' is not supported."); - return ret; - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java deleted file mode 100644 index cef5d9e20..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.execution.xml; - -import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase; -import org.argeo.slc.core.test.SimpleTestResult; -import org.argeo.slc.execution.ExecutionContext; -import org.argeo.slc.execution.ExecutionFlow; -import org.springframework.context.ConfigurableApplicationContext; - -public class FlowNamespaceTest extends AbstractExecutionFlowTestCase { - public void testCanonical() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("canonic-ns.xml"); - ((ExecutionFlow) applicationContext.getBean("canonic-ns.001")).run(); - ((ExecutionFlow) applicationContext.getBean("canonic-ns.002")).run(); - } - - public void testAdvanced() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("advanced.xml"); - ((ExecutionFlow) applicationContext.getBean("flow1")).run(); - ((ExecutionFlow) applicationContext.getBean("flow2")).run(); - ((ExecutionFlow) applicationContext.getBean("flow3")).run(); - - validateTestResult((SimpleTestResult) applicationContext - .getBean("testResult")); - } - - public void testAdvancedExecution() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("advanced.xml"); - - ExecutionContext executionContext = (ExecutionContext) applicationContext - .getBean("executionContext"); - executionContext.setVariable("param2", 4); - - ((ExecutionFlow) applicationContext.getBean("flow4")).run(); - - validateTestResult((SimpleTestResult) applicationContext - .getBean("testResult")); - } - - // THis tests causes pb when using Spring 3 - public void testContainers() throws Exception { - ConfigurableApplicationContext applicationContext = createApplicationContext("containers.xml"); - ((ExecutionFlow) applicationContext.getBean("test.list.flow1")).run(); - ((ExecutionFlow) applicationContext.getBean("test.list.flow2")).run(); - - validateTestResult((SimpleTestResult) applicationContext - .getBean("testResult")); - } -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java deleted file mode 100644 index 61eb3b2b3..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/AbstractInternalSpringTestCase.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -/** Helper for tests using a Spring application context. */ -public abstract class AbstractInternalSpringTestCase extends TestCase { - protected final Log log = LogFactory.getLog(getClass()); - private ConfigurableApplicationContext context; - - /** - * Gets (and create if necessary) the application context to use. Default - * implementation uses a class path xml application context and calls - * {@link #getApplicationContextLocation()}. - */ - protected ConfigurableApplicationContext getContext() { - if (context == null) { - context = new ClassPathXmlApplicationContext( - getApplicationContextLocation()); - } - return context; - } - - /** Returns a bean from the underlying context */ - @SuppressWarnings(value = { "unchecked" }) - protected T getBean(String beanId) { - return (T) getContext().getBean(beanId); - } - - protected T getBean(Class clss) { - T bean = loadSingleFromContext(getContext(), clss); - if (bean == null) { - throw new SlcException("Cannot retrieve a unique bean of type " - + clss); - } else { - return bean; - } - } - - /** - * Th location of the application to load. The default implementation - * returns applicationContext.xml found in the same package as the - * test. - */ - protected String getApplicationContextLocation() { - return inPackage("applicationContext.xml"); - } - - /** - * Prefixes the package of the class after converting the '.' to '/' in - * order to have a resource path. - */ - protected String inPackage(String suffix) { - String prefix = getClass().getPackage().getName().replace('.', '/'); - return prefix + '/' + suffix; - } - - @SuppressWarnings(value = { "unchecked" }) - protected T loadSingleFromContext(ListableBeanFactory context, - Class clss) { - Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors( - context, clss, false, false); - if (beans.size() == 1) { - return beans.values().iterator().next(); - } else if (beans.size() > 1) { - if (log.isDebugEnabled()) { - log - .debug(("Found more that on bean for type " + clss - + ": " + beans.keySet())); - } - return null; - } else { - return null; - } - } - -} diff --git a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/ContextTest.java b/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/ContextTest.java deleted file mode 100644 index 694851c82..000000000 --- a/runtime/org.argeo.slc.core/src/test/java/org/argeo/slc/core/test/context/ContextTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.slc.core.test.context; - -import java.util.List; - -import org.argeo.slc.core.test.SimpleTestResult; -import org.argeo.slc.test.TestResultPart; -import org.argeo.slc.test.TestStatus; -import org.argeo.slc.test.context.ContextAware; - -public class ContextTest extends AbstractInternalSpringTestCase { - - public void testComplexContext() { - SimpleTestResult testResult = new SimpleTestResult(); - ContextUtils.compareReachedExpected( - (ContextAware) getBean("context.c1"), testResult); - ContextUtils.compareReachedExpected( - (ContextAware) getBean("context.c2"), testResult); - ContextUtils.compareReachedExpected( - (ContextAware) getBean("context.c3"), testResult); - - List parts = testResult.getParts(); - assertEquals(6, parts.size()); - assertEquals(TestStatus.PASSED, parts.get(0).getStatus()); - assertEquals(TestStatus.PASSED, parts.get(1).getStatus()); - assertEquals(TestStatus.PASSED, parts.get(2).getStatus()); - assertEquals(TestStatus.FAILED, parts.get(3).getStatus()); - assertEquals(TestStatus.PASSED, parts.get(4).getStatus()); - assertEquals(TestStatus.PASSED, parts.get(5).getStatus()); - } -} diff --git a/runtime/org.argeo.slc.core/src/test/resources/org/argeo/slc/core/deploy/data/file1.txt b/runtime/org.argeo.slc.core/src/test/resources/org/argeo/slc/core/deploy/data/file1.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/runtime/org.argeo.slc.core/src/test/resources/org/argeo/slc/core/deploy/data/subdir/file2.txt b/runtime/org.argeo.slc.core/src/test/resources/org/argeo/slc/core/deploy/data/subdir/file2.txt deleted file mode 100644 index e69de29bb..000000000