<!-- Parent dependencies -->
<dependency>
<groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.dep.cms.e4.rap</artifactId>
+ <artifactId>org.argeo.dep.cms.sdk</artifactId>
<version>${version.argeo-commons}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.argeo.slc</groupId>
- <artifactId>org.argeo.slc.dep.spring</artifactId>
+ <artifactId>org.argeo.slc.dep.minimal</artifactId>
<version>2.1.17-SNAPSHOT</version>
<type>pom</type>
</dependency>
</execution>
</executions>
</plugin>
- <!-- <plugin> -->
- <!-- <groupId>org.apache.maven.plugins</groupId> -->
- <!-- <artifactId>maven-dependency-plugin</artifactId> -->
- <!-- <executions> -->
- <!-- <execution> -->
- <!-- <id>copy-argeo</id> -->
- <!-- <phase>package</phase> -->
- <!-- <goals> -->
- <!-- <goal>copy-dependencies</goal> -->
- <!-- </goals> -->
- <!-- <configuration> -->
- <!-- <includeTypes>jar</includeTypes> -->
- <!-- <outputDirectory>${project.build.directory}/lib-argeo</outputDirectory> -->
- <!-- <includeGroupIds>org.argeo.slc</includeGroupIds> -->
- <!-- <excludeTransitive>true</excludeTransitive> -->
- <!-- <excludeArtifactIds>org.argeo.slc.dep.minimal</excludeArtifactIds> -->
- <!-- <includeTypes>jar</includeTypes> -->
- <!-- <includeScope>runtime</includeScope> -->
- <!-- <useRepositoryLayout>true</useRepositoryLayout> -->
- <!-- </configuration> -->
- <!-- </execution> -->
- <!-- </executions> -->
- <!-- </plugin> -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
</source>
</sources>
</mapping>
- <!-- <mapping> -->
- <!-- <directory>/usr/share/osgi/org/argeo/slc/${project.artifactId}/${project.version}</directory> -->
- <!-- <username>root</username> -->
- <!-- <groupname>root</groupname> -->
- <!-- <directoryIncluded>false</directoryIncluded> -->
- <!-- <artifact /> -->
- <!-- </mapping> -->
</mappings>
<requires>
<require>argeo-cms-e4-rap</require>
<require>argeo-cms-sdk-tp</require>
- <require>slc-spring</require>
+ <require>slc-agent</require>
</requires>
</configuration>
</execution>
<artifactId>org.argeo.slc.api</artifactId>
<version>2.1.17-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.argeo.slc</groupId>
- <artifactId>org.argeo.slc.core</artifactId>
- <version>2.1.17-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.argeo.slc</groupId>
<artifactId>org.argeo.slc.support</artifactId>
</dependency>
<!-- Spring-based Agent -->
+ <dependency>
+ <groupId>org.argeo.slc</groupId>
+ <artifactId>org.argeo.slc.core</artifactId>
+ <version>2.1.17-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.argeo.slc</groupId>
<artifactId>org.argeo.slc.agent</artifactId>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" output="target/classes" path="src"/>
- <classpathentry kind="src" path="ext/test"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-/bin/
-/target/
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.slc.core</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- <nature>org.eclipse.pde.PluginNature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-/MANIFEST.MF
+++ /dev/null
-http\://www.argeo.org/schema/slc-flow=org.argeo.slc.core.execution.xml.FlowNamespaceHandler
\ No newline at end of file
+++ /dev/null
-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
+++ /dev/null
-Import-Package: javax.jcr.nodetype,\
-javax.jcr.security,\
-org.apache.tools.ant.*;resolution:="optional",\
-junit.framework;resolution:="optional",\
-org.osgi.*;version=0.0.0,\
-*
+++ /dev/null
-additional.bundles = org.springframework.context
-bin.includes = META-INF/,.
-source.. = src/
+++ /dev/null
-# Set root logger level to DEBUG and its only appender to A1.\r
-log4j.rootLogger=WARN, console\r
-\r
-## Levels\r
-# Slc\r
-log4j.logger.org.argeo=DEBUG\r
-\r
-# Castor\r
-log4j.logger.org.exolab.castor=WARN\r
-\r
-# Spring\r
-log4j.logger.org.springframework=WARN\r
-\r
-\r
-## Appenders\r
-# A1 is set to be a ConsoleAppender.\r
-log4j.appender.console=org.apache.log4j.ConsoleAppender\r
-\r
-# A1 uses PatternLayout.\r
-log4j.appender.console.layout=org.apache.log4j.PatternLayout\r
-log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n\r
-\r
+++ /dev/null
-/*
- * 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<String, Resource> 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");
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
-\r
- <bean id="relativeResourceSet" class="org.argeo.slc.core.deploy.DefaultResourceSet">\r
- <property name="base" value="classpath:/org/argeo/slc/core/deploy/data" />\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution;\r
-\r
-import junit.framework.TestCase;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.core.test.SimpleTestResult;\r
-import org.argeo.slc.execution.ExecutionContext;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.argeo.slc.test.TestResultPart;\r
-import org.argeo.slc.test.TestStatus;\r
-import org.springframework.context.ConfigurableApplicationContext;\r
-import org.springframework.context.support.ClassPathXmlApplicationContext;\r
-\r
-public abstract class AbstractExecutionFlowTestCase extends TestCase {\r
-\r
- protected final Log log = LogFactory.getLog(getClass());\r
-\r
- protected void logException(Throwable ex) {\r
- log.info("Got Exception of class " + ex.getClass().toString()\r
- + " with message '" + ex.getMessage() + "'.");\r
- }\r
-\r
- protected void validateTestResult(SimpleTestResult testResult) {\r
- validateTestResult(testResult, TestStatus.PASSED);\r
- }\r
-\r
- protected void validateTestResult(SimpleTestResult testResult,\r
- int expectedStatus) {\r
- for (TestResultPart part : testResult.getParts()) {\r
- if (part.getStatus() != expectedStatus) {\r
- fail("Error found in TestResult: " + part.getMessage());\r
- }\r
- }\r
- }\r
-\r
- protected ConfigurableApplicationContext createApplicationContext(\r
- String applicationContextSuffix) {\r
- ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext(\r
- inPackage(applicationContextSuffix));\r
- // applicationContext.start();\r
- return applicationContext;\r
- }\r
-\r
- protected void configureAndExecuteSlcFlow(String applicationContextSuffix,\r
- String beanName) {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext(applicationContextSuffix);\r
- ExecutionContext executionContext = (ExecutionContext) applicationContext\r
- .getBean("executionContext");\r
- ExecutionFlow executionFlow = (ExecutionFlow) applicationContext\r
- .getBean(beanName);\r
- if (executionFlow instanceof DefaultExecutionFlow)\r
- ((DefaultExecutionFlow) executionFlow)\r
- .setExecutionContext(executionContext);\r
- try {\r
- executionContext.beforeFlow(executionFlow);\r
- executionFlow.run();\r
- } finally {\r
- executionContext.afterFlow(executionFlow);\r
- }\r
- applicationContext.close();\r
- }\r
-\r
- protected String inPackage(String suffix) {\r
- String prefix = getClass().getPackage().getName().replace('.', '/');\r
- return prefix + '/' + suffix;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution;\r
-\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-\r
-import org.argeo.slc.core.test.SimpleTestResult;\r
-import org.argeo.slc.execution.ExecutionContext;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.argeo.slc.test.TestStatus;\r
-import org.springframework.beans.factory.BeanCreationException;\r
-import org.springframework.context.ConfigurableApplicationContext;\r
-\r
-public class BasicExecutionFlowTest extends AbstractExecutionFlowTestCase {\r
- // TO TEST\r
- // - post-processing for @{} replacement in beans with complex properties\r
- // - bean of scope other than execution are not resolved at execution\r
-\r
- // public void testMyTest() throws Exception {\r
- // ConfigurableApplicationContext applicationContext =\r
- // createApplicationContext("test.xml");\r
- // log.info("Start Execution");\r
- // ((ExecutionFlow) applicationContext.getBean("flow1")).execute();\r
- // applicationContext.close();\r
- // }\r
-\r
- public void testSpecOverriding() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("specOverriding.xml");\r
- ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
- SimpleTestResult res = (SimpleTestResult) applicationContext\r
- .getBean("myTestResult");\r
- validateTestResult(res);\r
- }\r
-\r
- public void testMultipleFlows() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("multipleFlow.xml");\r
- ((ExecutionFlow) applicationContext.getBean("flow1")).run();\r
- SimpleTestResult res = (SimpleTestResult) applicationContext\r
- .getBean("myTestResult");\r
- validateTestResult(res);\r
- res.getParts().clear();\r
- ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
- validateTestResult(res, TestStatus.FAILED);\r
- applicationContext.close();\r
- }\r
-\r
- /**\r
- * Test placeholder resolution in a context without scope execution or proxy\r
- * and with cascading flows (the flow A contains the flow B)\r
- * \r
- * @throws Exception\r
- */\r
- public void testPlaceHolders() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml");\r
- ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
- validateTestResult((SimpleTestResult) applicationContext\r
- .getBean("myTestResult"));\r
- applicationContext.close();\r
- }\r
-\r
- /**\r
- * Test placeholder resolution in a context without scope execution or proxy\r
- * and with cascading flows (the flow A contains the flow B) setting\r
- * execution values (should have no effect)\r
- * \r
- * @throws Exception\r
- */\r
- public void testPlaceHoldersWithExecutionValues() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml");\r
-\r
- ExecutionContext executionContext = (ExecutionContext) applicationContext\r
- .getBean("executionContext");\r
- Map<String, String> executionParameters = new HashMap<String, String>();\r
- executionParameters.put("p1", "e1");\r
- executionParameters.put("p2", "e2");\r
- executionParameters.put("p3", "e3");\r
- executionParameters.put("p4", "e4");\r
- executionParameters.put("p5", "e5");\r
- executionParameters.put("p6", "e6");\r
- executionParameters.put("p7", "e7");\r
- executionParameters.put("p8", "e8");\r
- addVariables(executionContext, executionParameters);\r
-\r
- ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
- validateTestResult((SimpleTestResult) applicationContext\r
- .getBean("myTestResult"));\r
- applicationContext.close();\r
- }\r
-\r
- public void testPlaceHoldersExec() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.exec.xml");\r
-\r
- ExecutionContext executionContext = (ExecutionContext) applicationContext\r
- .getBean("executionContext");\r
- Map<String, String> executionParameters = new HashMap<String, String>();\r
- executionParameters.put("p1", "e1");\r
- executionParameters.put("p2", "e2");\r
- executionParameters.put("p3", "e3");\r
- executionParameters.put("p4", "e4");\r
- executionParameters.put("p5", "e5");\r
- executionParameters.put("p6", "e6");\r
- addVariables(executionContext, executionParameters);\r
-\r
- ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
- validateTestResult((SimpleTestResult) applicationContext\r
- .getBean("myTestResult"));\r
- applicationContext.close();\r
- }\r
-\r
- public void testCanonicFlowParameters() throws Exception {\r
- configureAndExecuteSlcFlow("canonic-001.xml", "canonic.001");\r
- }\r
-\r
- public void testCanonicDefaultValues() throws Exception {\r
- configureAndExecuteSlcFlow("canonic-002.xml", "canonic.002");\r
- }\r
-\r
- public void testCanonicMissingValues() throws Exception {\r
- try {\r
- configureAndExecuteSlcFlow("canonic-003.error.xml", "canonic.003");\r
- fail("Parameter not set - should be rejected.");\r
- } catch (BeanCreationException e) {\r
- // exception expected\r
- logException(e);\r
- }\r
- }\r
-\r
- public void testCanonicUnknownParameter() throws Exception {\r
- try {\r
- configureAndExecuteSlcFlow("canonic-004.error.xml", "canonic.004");\r
- fail("Unknown parameter set - should be rejected.");\r
- } catch (BeanCreationException e) {\r
- // exception expected\r
- logException(e);\r
- }\r
- }\r
-\r
- public void testListSetMap() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMap.xml");\r
- ExecutionFlow executionFlow = (ExecutionFlow) applicationContext\r
- .getBean("myFlow");\r
- executionFlow.run();\r
-\r
- validateTestResult((SimpleTestResult) applicationContext\r
- .getBean("myTestResult"));\r
-\r
- // BasicTestData res = (BasicTestData)\r
- // applicationContext.getBean("cascadingComplex.testData");\r
- // log.info("res=" + res.getReached().toString());\r
-\r
- applicationContext.close();\r
- }\r
-\r
- public void testListSetMapMultipleFlows() throws Exception {\r
- ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMapMultipleFlow.xml");\r
- ((ExecutionFlow) applicationContext.getBean("flow1")).run();\r
- SimpleTestResult res = (SimpleTestResult) applicationContext\r
- .getBean("myTestResult");\r
- validateTestResult(res);\r
- res.getParts().clear();\r
- ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
- validateTestResult(res, TestStatus.FAILED);\r
- applicationContext.close();\r
- }\r
-\r
- protected void addVariables(ExecutionContext executionContext,\r
- Map<String, String> vars) {\r
- for (String key : vars.keySet())\r
- executionContext.setVariable(key, vars.get(key));\r
- }\r
-}\r
+++ /dev/null
-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<URI> uris = DefaultAgentCli.asURIs(args);
- assertEquals(1, uris.size());
- assertEquals(
- "flow:/org.argeo.slc.demo.minimal/HelloWorld/WithVar?testKey=555",
- uris.get(0).toString());
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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));
- }
-}
+++ /dev/null
-/*
- * 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());
- }
-
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="executionModule_1" class="org.argeo.slc.core.execution.SimpleSpringExecutionModule" >\r
- <property name="executionContext">\r
- <ref bean="executionContext" />\r
- </property> \r
- <property name="name" value="dummyname" />\r
- <property name="version" value="dummyversion" />\r
- </bean>\r
- \r
- <bean id="main" parent="slcTemplate.simpleFlow">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testKey">\r
- <bean parent="specAttr.primitive" p:value="660" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <property name="executables">\r
- <list>\r
- <ref local="echo1" />\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="echo1" parent="task.echo" scope="execution">\r
- <property name="message"\r
- value="From main! @{testKey}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="canonic.xml" />\r
-\r
- <bean id="canonic.001" parent="canonic.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="parameterAtInstantiation" value="1" />\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-</beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="canonic.xml" />\r
-\r
- <bean id="canonic.002" parent="canonic.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="parameterAtInstantiation" value="2" />\r
- <entry key="displayWithoutControl" value="102" />\r
- <entry key="displayWithControl" value="202" />\r
- <entry key="hide" value="202" />\r
- <entry key="notParameterAtInstantiation" value="202" />\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-</beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="canonic.xml" />\r
-\r
- <bean id="canonic.003" parent="canonic.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <!-- missing parameter -->\r
- <entry key="displayWithoutControl" value="102" />\r
- <entry key="displayWithControl" value="202" />\r
- <entry key="hide" value="202" />\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-</beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="canonic.xml" />\r
-\r
- <bean id="canonic.004" parent="canonic.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="parameterAtInstantiation" value="2" />\r
- <entry key="displayWithoutControl" value="102" />\r
- <entry key="displayWithControl" value="202" />\r
- <entry key="hide" value="202" />\r
- <entry key="unknownParameter" value="1" />\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-</beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" />\r
-\r
- <bean id="canonic.spec" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="parameterAtInstantiation">\r
- <bean parent="specAttr.primitive" p:isParameter="true" p:type="integer" />\r
- </entry>\r
- <entry key="displayWithoutControl">\r
- <bean parent="specAttr.primitive" p:value="100" p:isParameter="true"\r
- p:isFrozen="true" p:type="integer" />\r
- </entry>\r
- <entry key="displayWithControl">\r
- <bean parent="specAttr.primitive" p:value="200" p:isParameter="true"\r
- p:isFrozen="false" p:type="integer" />\r
- </entry>\r
- <entry key="hide">\r
- <bean parent="specAttr.primitive" p:value="300" p:isParameter="true"\r
- p:isFrozen="false" p:isHidden="true" p:type="integer" />\r
- </entry> \r
- <entry key="notParameterAtInstantiation">\r
- <bean parent="specAttr.primitive" p:value="400" p:isParameter="false"\r
- p:isFrozen="false" p:isHidden="false" p:type="integer" />\r
- </entry> \r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="canonic.flowTemplate" parent="slcTemplate.simpleFlow"\r
- abstract="true">\r
- <constructor-arg ref="canonic.spec" />\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo"\r
- p:message="Canonical: displayWithControl=@{displayWithControl}, displayWithoutControl=@{displayWithoutControl}, hide=@{hide}">\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" />\r
-\r
- <bean id="executionResources.spec" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="var">\r
- <bean parent="specAttr.primitive" p:isParameter="false"\r
- p:type="integer" p:value="60" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="executionResources.placeholderPass" parent="slcTemplate.simpleFlow">\r
- <constructor-arg ref="executionResources.spec" />\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo">\r
- <property name="message" value="DATA" />\r
- <property name="writeTo">\r
- <bean parent="slcTemplate.resourcesFactoryBean" scope="execution">\r
- <property name="executionResources" ref="executionResources" />\r
- <property name="relativePath" value="subdir/@{var}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="executionResources.placeholderFail" parent="slcTemplate.simpleFlow">\r
- <constructor-arg ref="executionResources.spec" />\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo">\r
- <property name="message" value="DATA" />\r
- <property name="writeTo">\r
- <bean factory-bean="executionResources" factory-method="getWritableResource"\r
- scope="execution">\r
- <constructor-arg value="subdir/@{var}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="executionResources.simple" parent="slcTemplate.simpleFlow">\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo">\r
- <property name="message" value="DATA" />\r
- <property name="writeTo">\r
- <bean factory-bean="executionResources" factory-method="getWritableResource"\r
- scope="execution">\r
- <constructor-arg value="subdir/writeTo" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="executionResources" parent="slcTemplate.fileResources">\r
- <property name="executionContext" ref="executionContext" />\r
- <property name="withExecutionSubdirectory" value="false" />\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<!-- Copyright (C) 2007-2012 Mathieu Baudier 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. -->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />
- <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />
-
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="basic.testDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
-\r
- <bean id="myFlow" parent="slcTemplate.simpleFlow">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testKey">\r
- <bean parent="specAttr.primitive" p:value="myValue" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <property name="executables">\r
- <list>\r
- <ref local="echo1" />\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingMap.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleList.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingList.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleSet.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingSet.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingListMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingSetMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingComplex.testData" />\r
- </bean> \r
- \r
- </list>\r
- </property>\r
- </bean>\r
-\r
-\r
- <bean id="simpleMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <map>\r
- <entry key="key1" value="myValue_myValue" />\r
- </map>\r
- </property>\r
- <property name="reached">\r
- <map>\r
- <entry key="key1" value="@{testKey}_@{testKey}" />\r
- </map>\r
- </property>\r
- </bean>\r
- \r
- <bean id="cascadingMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <map>\r
- <entry key="key3">\r
- <map>\r
- <entry key="key2">\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map>\r
- </entry>\r
- <entry key="key2bis" value="myValue" />\r
- </map>\r
- </entry>\r
- </map>\r
- </property>\r
- <property name="reached">\r
- <map>\r
- <entry key="key3">\r
- <map>\r
- <entry key="key2">\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map>\r
- </entry>\r
- <entry key="key2bis" value="@{testKey}" />\r
- </map>\r
- </entry>\r
- </map>\r
- </property>\r
- </bean> \r
- \r
- <bean id="simpleList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value> \r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- <value>myValue</value>\r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </list>\r
- <value>@{testKey}</value>\r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="simpleSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </set>\r
- <value>myValue</value>\r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </set>\r
- <value>@{testKey}</value>\r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingListMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingSetMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingComplex.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- <list>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- <set>\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- <list>\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- <value>myValue</value>\r
- </list> \r
- </set>\r
- <value>myValue</value>\r
- </set> \r
- </list> \r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </set> \r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- <list>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- <set>\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- <list>\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </list>\r
- <value>@{testKey}</value>\r
- </list> \r
- </set>\r
- <value>@{testKey}</value>\r
- </set> \r
- </list> \r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </set> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="basic.testDef" class="org.argeo.slc.core.test.BasicTestDefinition">\r
- </bean> \r
-\r
-\r
- <bean id="echo1" parent="task.echo" scope="prototype">\r
- <property name="message"\r
- value="testKey=@{testKey}" />\r
- </bean>\r
- \r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="basic.testDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
-\r
- <bean id="abstractFlow" parent="slcTemplate.simpleFlow" abstract="true">\r
- <property name="executables">\r
- <list>\r
- <ref local="echo1" />\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingMap.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleList.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingList.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="simpleSet.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingSet.testData" />\r
- </bean> \r
- \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingListMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingSetMap.testData" />\r
- </bean> \r
- <bean parent="myTestRunTemplate">\r
- <property name="testData" ref="cascadingComplex.testData" />\r
- </bean> \r
- \r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flow1" parent="abstractFlow" scope="prototype">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testKey">\r
- <bean parent="specAttr.primitive" p:value="myValue" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- </bean> \r
-\r
- <bean id="flow2" parent="abstractFlow" scope="prototype">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testKey">\r
- <bean parent="specAttr.primitive" p:value="myValue2" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- </bean> \r
-\r
-\r
- <bean id="simpleMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <map>\r
- <entry key="key1" value="myValue_myValue" />\r
- </map>\r
- </property>\r
- <property name="reached">\r
- <map>\r
- <entry key="key1" value="@{testKey}_@{testKey}" />\r
- </map>\r
- </property>\r
- </bean>\r
- \r
- <bean id="cascadingMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <map>\r
- <entry key="key3">\r
- <map>\r
- <entry key="key2">\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map>\r
- </entry>\r
- <entry key="key2bis" value="myValue" />\r
- </map>\r
- </entry>\r
- </map>\r
- </property>\r
- <property name="reached">\r
- <map>\r
- <entry key="key3">\r
- <map>\r
- <entry key="key2">\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map>\r
- </entry>\r
- <entry key="key2bis" value="@{testKey}" />\r
- </map>\r
- </entry>\r
- </map>\r
- </property>\r
- </bean> \r
- \r
- <bean id="simpleList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value> \r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- <value>myValue</value>\r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </list>\r
- <value>@{testKey}</value>\r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="simpleSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </set>\r
- <value>myValue</value>\r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </set>\r
- <value>@{testKey}</value>\r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingListMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <list>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </list>\r
- </property>\r
- <property name="reached">\r
- <list>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </list>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingSetMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="cascadingComplex.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
- <property name="expected">\r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- <list>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- <set>\r
- <set>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- <list>\r
- <list>\r
- <value>myValue</value>\r
- <value>_myValue_</value>\r
- </list>\r
- <value>myValue</value>\r
- </list> \r
- </set>\r
- <value>myValue</value>\r
- </set> \r
- </list> \r
- <set>\r
- <map>\r
- <entry key="key1" value="myValue" />\r
- </map> \r
- </set> \r
- </set>\r
- </property>\r
- <property name="reached">\r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- <list>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- <set>\r
- <set>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- <list>\r
- <list>\r
- <value>@{testKey}</value>\r
- <value>_@{testKey}_</value>\r
- </list>\r
- <value>@{testKey}</value>\r
- </list> \r
- </set>\r
- <value>@{testKey}</value>\r
- </set> \r
- </list> \r
- <set>\r
- <map>\r
- <entry key="key1" value="@{testKey}" />\r
- </map> \r
- </set> \r
- </set>\r
- </property>\r
- </bean> \r
- \r
- <bean id="basic.testDef" class="org.argeo.slc.core.test.BasicTestDefinition">\r
- </bean> \r
-\r
-\r
- <bean id="echo1" parent="task.echo" scope="prototype">\r
- <property name="message"\r
- value="testKey=@{testKey}" />\r
- </bean>\r
- \r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="minimal" parent="slcTemplate.simpleFlow">\r
- <property name="executionSpec">\r
- <bean parent="slcTemplate.simpleSpec">\r
-<!-- <property name="attributes">\r
- <map>\r
- <entry key="testKey">\r
- <bean parent="specAttr.primitive" p:value="660" />\r
- </entry>\r
- </map>\r
- </property> -->\r
- </bean>\r
- </property>\r
- <property name="executables">\r
- <list>\r
- <ref local="echo1" />\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="echo1" parent="task.echo" scope="execution">\r
- <property name="message"\r
- value="From minimal" />\r
- <aop:scoped-proxy />\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="myTestDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
-\r
- <bean id="fileDiff.spec" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="fileName">\r
- <bean parent="specAttr.primitive" p:isParameter="true" p:type="string"\r
- p:isFrozen="true" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
-\r
- <bean id="fileDiff.flowTemplate" parent="slcTemplate.simpleFlow"\r
- abstract="true">\r
- <property name="path" value="/fileDiff/testcases" />\r
- <constructor-arg ref="fileDiff.spec" />\r
- <property name="executables">\r
- <list> \r
- <bean parent="task.echo">\r
- <property name="message" value="fileName=@{fileName}" />\r
- </bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="file1" />\r
- <property name="reached" value="@{fileName}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
- \r
- <bean id="echo" parent="task.echo" scope="prototype">\r
- <property name="message" value="fileName=@{fileName}" />\r
- </bean> \r
- \r
- <bean id="flow1" parent="fileDiff.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="fileName" value="file1" />\r
- </map>\r
- </constructor-arg>\r
- </bean> \r
-\r
- <bean id="flow2" parent="fileDiff.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="fileName" value="file2" />\r
- </map>\r
- </constructor-arg>\r
- </bean> \r
- \r
- \r
- <!-- \r
- <bean id="flow1" parent="slcTemplate.simpleFlow">\r
- <property name="path" value="/fileDiff/testcases" />\r
- <constructor-arg ref="fileDiff.spec" />\r
- <constructor-arg>\r
- <map>\r
- <entry key="fileName" value="file1" />\r
- </map>\r
- </constructor-arg> \r
- <property name="executables">\r
- <list> \r
- <bean parent="task.echo" scope="execution">\r
- <property name="message" value="fileName=@{fileName}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flow2" parent="slcTemplate.simpleFlow">\r
- <property name="path" value="/fileDiff/testcases" />\r
- <constructor-arg ref="fileDiff.spec" />\r
- <constructor-arg>\r
- <map>\r
- <entry key="fileName" value="file2" />\r
- </map>\r
- </constructor-arg> \r
- <property name="executables">\r
- <list> \r
- <bean parent="task.echo" scope="execution">\r
- <property name="message" value="fileName=@{fileName}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
- -->\r
-<!-- \r
- <bean id="main" parent="slcTemplate.simpleFlow">\r
- <property name="executables">\r
- <list> \r
- <ref bean="flow1"/> \r
- <ref bean="flow2"/> \r
- </list>\r
- </property>\r
- </bean>\r
- -->\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" />\r
-\r
- <!-- DEFINITIONS -->\r
- <bean id="parameterRef.spec" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="exceptionIfInitCalledTwice">\r
- <bean parent="specAttr.ref"\r
- p:targetClass="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- <entry key="testData1">\r
- <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- <entry key="testData2">\r
- <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- <entry key="testedComponentId">\r
- <bean parent="specAttr.primitive" p:value="100" p:isParameter="true"\r
- p:type="integer" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="parameterRef.flowTemplate" parent="slcTemplate.simpleFlow"\r
- abstract="true">\r
- <constructor-arg ref="parameterRef.spec" />\r
- <property name="executables">\r
- <list>\r
- <!-- Primitive -->\r
- <bean parent="task.echo" scope="execution">\r
- <property name="message" value="testedComponentId=@{testedComponentId}" />\r
- </bean>\r
-\r
- <!-- Exception if init called twice -->\r
- <bean parent="parameterRef">\r
- <constructor-arg value="exceptionIfInitCalledTwice" />\r
- </bean>\r
- <bean parent="parameterRef">\r
- <property name="name" value="exceptionIfInitCalledTwice" />\r
- </bean>\r
-\r
- <!-- Basic tests -->\r
- <bean parent="parameterRef.testRun">\r
- <property name="testData">\r
- <bean parent="parameterRef">\r
- <constructor-arg value="testData1" />\r
- </bean>\r
- </property>\r
- </bean>\r
- <bean parent="parameterRef.testRun">\r
- <property name="testData" ref="ref1" />\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <!-- TEST CASES -->\r
- <bean id="parameterRef.001" parent="parameterRef.flowTemplate">\r
- <constructor-arg>\r
- <map>\r
- <entry key="exceptionIfInitCalledTwice">\r
- <bean class="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice" />\r
- </entry>\r
- <entry key="testData1">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="toto" />\r
- <property name="reached" value="toto" />\r
- </bean>\r
- </entry>\r
- <entry key="testData2">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="tata" />\r
- <property name="reached" value="toto" />\r
- </bean>\r
- </entry>\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-\r
- <!-- UTILITIES -->\r
-\r
- <bean id="ref1" parent="parameterRef">\r
- <constructor-arg value="testData2" />\r
- </bean>\r
-\r
- <bean id="parameterRef.testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="parameterRef.testRun" class="org.argeo.slc.core.test.SimpleTestRun"\r
- abstract="true">\r
- <property name="testResult" ref="parameterRef.testResult" />\r
- <property name="testDefinition">\r
- <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
- </property>\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="echo1" parent="task.echo">\r
- <property name="message" value="From minimal" />\r
- </bean>\r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="myTestDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
-\r
- <!-- \r
- The Flow A contains the flow B as executable.\r
- \r
- Parameters\r
- p1: flow A: default - flow B: - \r
- p2: flow A: set - flow B: - \r
- p3: flow A: default - flow B: default \r
- p4: flow A: set - flow B: default\r
- p5: flow A: default - flow B: set \r
- p6: flow A: set - flow B: set\r
- p7: flow A: - - flow B: default\r
- p8: flow A: - - flow B: set\r
- \r
- \r
- -->\r
-\r
- <bean id="flowA" parent="slcTemplate.simpleFlow">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="p1"><bean parent="specAttr.primitive" p:value="da1" /></entry>\r
- <entry key="p2"><bean parent="specAttr.primitive" p:value="da2" /></entry> \r
- <entry key="p3"><bean parent="specAttr.primitive" p:value="da3" /></entry> \r
- <entry key="p4"><bean parent="specAttr.primitive" p:value="da4" /></entry> \r
- <entry key="p5"><bean parent="specAttr.primitive" p:value="da5" /></entry> \r
- <entry key="p6"><bean parent="specAttr.primitive" p:value="da6" /></entry> \r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <constructor-arg> \r
- <map>\r
- <entry key="p2" value="va2"/>\r
- <entry key="p4" value="va4"/>\r
- <entry key="p6" value="va6"/>\r
- </map>\r
- </constructor-arg>\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da1" />\r
- <property name="reached" value="@{p1}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va2" />\r
- <property name="reached" value="@{p2}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da3" />\r
- <property name="reached" value="@{p3}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va4" />\r
- <property name="reached" value="@{p4}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da5" />\r
- <property name="reached" value="@{p5}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va6" />\r
- <property name="reached" value="@{p6}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <ref bean="flowB"/> \r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flowB" parent="slcTemplate.simpleFlow" scope="prototype">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="p3"><bean parent="specAttr.primitive" p:value="db3" /></entry> \r
- <entry key="p4"><bean parent="specAttr.primitive" p:value="db4" /></entry>\r
- <entry key="p5"><bean parent="specAttr.primitive" p:value="db5" /></entry> \r
- <entry key="p6"><bean parent="specAttr.primitive" p:value="db6" /></entry>\r
- <entry key="p7"><bean parent="specAttr.primitive" p:value="db7" /></entry> \r
- <entry key="p8"><bean parent="specAttr.primitive" p:value="db8" /></entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <constructor-arg> \r
- <map>\r
- <entry key="p3" value="vb3"/>\r
- <entry key="p4" value="vb4"/>\r
- <entry key="p7" value="vb7"/>\r
- </map>\r
- </constructor-arg> \r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da1" />\r
- <property name="reached" value="@{p1}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va2" />\r
- <property name="reached" value="@{p2}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da3" />\r
- <property name="reached" value="@{p3}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va4" />\r
- <property name="reached" value="@{p4}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da5" />\r
- <property name="reached" value="@{p5}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va6" />\r
- <property name="reached" value="@{p6}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p7=@{p7}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="vb7" />\r
- <property name="reached" value="@{p7}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p8=@{p8}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="db8" />\r
- <property name="reached" value="@{p8}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- \r
- <!-- test in scope execution -->\r
- <bean parent="task.echo" scope="execution"><property name="message" value="p1=@{p1}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e1" />\r
- <property name="reached" value="@{p1}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean>\r
- <bean parent="task.echo" scope="execution"><property name="message" value="p2=@{p2}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e2" />\r
- <property name="reached" value="@{p2}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo" scope="execution"><property name="message" value="p3=@{p3}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e3" />\r
- <property name="reached" value="@{p3}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo" scope="execution"><property name="message" value="p4=@{p4}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e4" />\r
- <property name="reached" value="@{p4}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo" scope="execution"><property name="message" value="p5=@{p5}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e5" />\r
- <property name="reached" value="@{p5}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo" scope="execution"><property name="message" value="p6=@{p6}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="e6" />\r
- <property name="reached" value="@{p6}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean>\r
- \r
- <!-- \r
- p7 and p8 are not in the spec of FlowA and therefore can not be overridden\r
- at the execution\r
- -->\r
- <bean parent="task.echo" scope="execution"><property name="message" value="p7=@{p7}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="vb7" />\r
- <property name="reached" value="@{p7}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo" scope="execution"><property name="message" value="p8=@{p8}" /><aop:scoped-proxy /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <property name="expected" value="db8" />\r
- <property name="reached" value="@{p8}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property> \r
- </bean> \r
- \r
- </list>\r
- </property>\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="echo1" parent="task.echo">\r
- <property name="message" value="From minimal" />\r
- </bean>\r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="myTestDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
-\r
- <!-- \r
- The Flow A contains the flow B as executable.\r
- \r
- Parameters\r
- p1: flow A: default - flow B: - \r
- p2: flow A: set - flow B: - \r
- p3: flow A: default - flow B: default \r
- p4: flow A: set - flow B: default\r
- p5: flow A: default - flow B: set \r
- p6: flow A: set - flow B: set\r
- p7: flow A: - - flow B: default\r
- p8: flow A: - - flow B: set\r
- \r
- \r
- -->\r
-\r
- <bean id="flowA" parent="slcTemplate.simpleFlow">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="p1"><bean parent="specAttr.primitive" p:value="da1" /></entry>\r
- <entry key="p2"><bean parent="specAttr.primitive" p:value="da2" /></entry> \r
- <entry key="p3"><bean parent="specAttr.primitive" p:value="da3" /></entry> \r
- <entry key="p4"><bean parent="specAttr.primitive" p:value="da4" /></entry> \r
- <entry key="p5"><bean parent="specAttr.primitive" p:value="da5" /></entry> \r
- <entry key="p6"><bean parent="specAttr.primitive" p:value="da6" /></entry> \r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <constructor-arg> \r
- <map>\r
- <entry key="p2" value="va2"/>\r
- <entry key="p4" value="va4"/>\r
- <entry key="p6" value="va6"/>\r
- </map>\r
- </constructor-arg>\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da1" />\r
- <property name="reached" value="@{p1}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va2" />\r
- <property name="reached" value="@{p2}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da3" />\r
- <property name="reached" value="@{p3}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va4" />\r
- <property name="reached" value="@{p4}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da5" />\r
- <property name="reached" value="@{p5}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va6" />\r
- <property name="reached" value="@{p6}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <ref bean="flowB"/> \r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flowB" parent="slcTemplate.simpleFlow" scope="prototype">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="p3"><bean parent="specAttr.primitive" p:value="db3" /></entry> \r
- <entry key="p4"><bean parent="specAttr.primitive" p:value="db4" /></entry>\r
- <entry key="p5"><bean parent="specAttr.primitive" p:value="db5" /></entry> \r
- <entry key="p6"><bean parent="specAttr.primitive" p:value="db6" /></entry>\r
- <entry key="p7"><bean parent="specAttr.primitive" p:value="db7" /></entry> \r
- <entry key="p8"><bean parent="specAttr.primitive" p:value="db8" /></entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <constructor-arg> \r
- <map>\r
- <entry key="p3" value="vb3"/>\r
- <entry key="p4" value="vb4"/>\r
- <entry key="p7" value="vb7"/>\r
- </map>\r
- </constructor-arg> \r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da1" />\r
- <property name="reached" value="@{p1}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va2" />\r
- <property name="reached" value="@{p2}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da3" />\r
- <property name="reached" value="@{p3}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va4" />\r
- <property name="reached" value="@{p4}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="da5" />\r
- <property name="reached" value="@{p5}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="va6" />\r
- <property name="reached" value="@{p6}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p7=@{p7}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="vb7" />\r
- <property name="reached" value="@{p7}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- <bean parent="task.echo"><property name="message" value="p8=@{p8}" /></bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="db8" />\r
- <property name="reached" value="@{p8}" />\r
- </bean>\r
- </property> \r
- </bean> \r
- </list>\r
- </property>\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
- \r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="myTestDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
- \r
- <bean id="spec1" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testedComponentId">\r
- <bean parent="specAttr.primitive" p:isParameter="true"\r
- p:type="integer" />\r
- </entry>\r
- <entry key="testData1">\r
- <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flowTemplate1" parent="slcTemplate.simpleFlow"\r
- abstract="true">\r
- <constructor-arg ref="spec1" />\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo" scope="execution">\r
- <property name="message" value="From basic @{testedComponentId}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean parent="parameterRef">\r
- <constructor-arg value="testData1" />\r
- </bean>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flow1" parent="flowTemplate1" scope="prototype">\r
- <constructor-arg>\r
- <map>\r
- <entry key="testedComponentId" value="200" />\r
- <entry key="testData1">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <aop:scoped-proxy/>\r
- <property name="expected" value="tata101" />\r
- <property name="reached" value="tata@{testedComponentId}" />\r
- </bean>\r
- </entry>\r
- </map> \r
- </constructor-arg>\r
- </bean>\r
-\r
- <bean id="spec2" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testData1">\r
- <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flowTemplate2" parent="slcTemplate.simpleFlow" abstract="true">\r
- <constructor-arg ref="spec2" />\r
- <property name="executables">\r
- <list>\r
- <ref bean="flow1"/>\r
- </list>\r
- </property>\r
- </bean>\r
- \r
- <bean id="flow2" parent="flowTemplate2">\r
- <constructor-arg>\r
- <map>\r
- <entry key="testData1">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected" value="tata100" />\r
- <property name="reached" value="tata100" />\r
- </bean>\r
- </entry>\r
- </map> \r
- </constructor-arg>\r
- </bean> \r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="../imports.xml" />\r
-\r
- <bean id="systemCallSimple" parent="slcTemplate.simpleFlow">\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo">\r
- <property name="message" value="os.name=${os.name}" />\r
- </bean>\r
- <bean parent="task.systemCall">\r
- <property name="cmd" value="echo Hello World" />\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="systemCallList" parent="slcTemplate.simpleFlow">\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.systemCall">\r
- <property name="command">\r
- <list>\r
- <value>echo</value>\r
- <value>Hello</value>\r
- <value>World</value>\r
- </list>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="systemCallOsSpecific" parent="slcTemplate.simpleFlow">\r
- <!-- Direct call to dir under Windows isnot working -->\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.systemCall">\r
- <property name="cmd" value="dir" />\r
- <property name="execDir" value="../.." />\r
- <property name="osCmds">\r
- <map>\r
- <entry key="Linux" value="ls" />\r
- <entry key="Mac OS X" value="ls" />\r
- </map>\r
- </property>\r
- </bean>\r
- <bean parent="task.systemCall">\r
- <property name="command">\r
- <list>\r
- <value>dir</value>\r
- </list>\r
- </property>\r
- <property name="osCommands">\r
- <map>\r
- <entry key="Linux">\r
- <list>\r
- <value>ls</value>\r
- </list>\r
- </entry>\r
- <entry key="Mac OS X">\r
- <list>\r
- <value>ls</value>\r
- </list>\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="systemCallWithVar" parent="slcTemplate.simpleFlow">\r
- <constructor-arg>\r
- <bean parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="var">\r
- <bean parent="specAttr.primitive" p:value="660" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
- </constructor-arg>\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.systemCall" scope="execution">\r
- <property name="cmd" value="echo var=@{var}" />\r
- <aop:scoped-proxy />\r
- </bean>\r
- </list>\r
- </property>\r
- </bean>\r
-\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
-\r
- <import resource="imports.xml" /> \r
-\r
- <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="myTestDef" />\r
- <property name="testResult" ref="myTestResult"/>\r
- </bean> \r
- \r
- <bean id="spec1" parent="slcTemplate.simpleSpec">\r
- <property name="attributes">\r
- <map>\r
- <entry key="testedComponentId">\r
- <bean parent="specAttr.primitive" p:isParameter="true"\r
- p:type="integer" />\r
- </entry>\r
- <entry key="testData1">\r
- <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
- p:isParameter="true" p:isFrozen="true" />\r
- </entry>\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flowTemplate1" parent="slcTemplate.simpleFlow"\r
- abstract="true">\r
- <constructor-arg ref="spec1" />\r
- <property name="executables">\r
- <list>\r
- <bean parent="task.echo">\r
- <property name="message" value="From basic @{testedComponentId}" />\r
- </bean>\r
- <bean parent="myTestRunTemplate">\r
- <property name="testData">\r
- <bean parent="parameterRef">\r
- <constructor-arg value="testData1" />\r
- </bean>\r
- </property>\r
- </bean>\r
- <bean parent="task.echo">\r
- <property name="message"><value>From basic @{testedComponentId}</value></property>\r
- </bean> \r
- <bean parent="task.echo">\r
- <property name="message"><value>testData1='@{testData1}'</value></property>\r
- </bean> \r
- </list>\r
- </property>\r
- </bean>\r
-\r
- <bean id="flow1" parent="flowTemplate1" scope="prototype">\r
- <constructor-arg>\r
- <map>\r
- <entry key="testedComponentId" value="200" />\r
- <entry key="testData1">\r
- <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
- <aop:scoped-proxy/>\r
- <property name="expected" value="tata101" />\r
- <property name="reached" value="tata@{testedComponentId}" />\r
- </bean>\r
- </entry>\r
- </map> \r
- </constructor-arg>\r
- </bean>\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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"));
- // }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
- <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
-\r
- <bean id="testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="testRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="testDef" />\r
- <property name="testResult" ref="testResult"/>\r
- </bean> \r
-\r
- <flow:spec id="advanced.spec">\r
- <description>spec description</description>\r
- <flow:primitive name="param1" isParameter="true"\r
- type="integer" />\r
- <flow:primitive name="param2" isParameter="true"\r
- type="integer" /> \r
- </flow:spec>\r
-\r
-\r
- <flow:flow id="advanced.flowTemplate" abstract="true" spec="advanced.spec"\r
- path="/path">\r
- <description>flow description</description>\r
- <bean parent="task.echo">\r
- <property name="message" value="Advanced: param1=@{param1}, param2=@{param2}" />\r
- <flow:variable/>\r
- </bean> \r
- <flow:flow>\r
- <bean parent="task.echo" p:message="Flow in Flow - param1=@{param1}, param2=@{param2} [Not variable]" />\r
- </flow:flow>\r
- \r
- <bean parent="testRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <flow:variable/>\r
- <property name="expected" value="@{param1}" />\r
- <property name="reached" value="@{param2}" />\r
- </bean>\r
- </property> \r
- </bean>\r
- \r
- </flow:flow>\r
-\r
- <flow:flow id="advanced.flowTemplate2" abstract="true" spec="advanced.spec"\r
- path="/path">\r
- <bean parent="task.echo" p:message="Advanced2: param1=@{param1}, param2=@{param2}">\r
- <flow:variable/>\r
- </bean>\r
- <flow:flow parent="advanced.flowTemplate">\r
- <flow:arg name="param1" value="@{param1}"/>\r
- <flow:arg name="param2">\r
- <!-- flow:param in flow:arg -->\r
- <flow:param name="param2" />\r
- </flow:arg>\r
- </flow:flow>\r
- </flow:flow>\r
-\r
- \r
- <flow:flow id="flow1" parent="advanced.flowTemplate">\r
- <flow:arg name="param1" value="1" />\r
- <flow:arg name="param2" value="1" />\r
- </flow:flow>\r
- \r
- <flow:flow id="flow2">\r
- <flow:flow parent="advanced.flowTemplate">\r
- <flow:arg name="param1" value="2" />\r
- <flow:arg name="param2" value="2" />\r
- </flow:flow>\r
- </flow:flow>\r
-\r
- <flow:flow id="flow3" parent="advanced.flowTemplate2">\r
- <flow:arg name="param1" value="3" />\r
- <flow:arg name="param2" value="3" />\r
- </flow:flow>\r
- \r
- <flow:flow id="flow4" parent="advanced.flowTemplate">\r
- <description>Would fail if param 2 is not changed at execution</description>\r
- <flow:arg name="param1" value="4" />\r
- <flow:arg name="param2" value="3" />\r
- </flow:flow> \r
-\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <bean id="canonic-ns.001" parent="canonic-ns.flowTemplate">\r
- <description>Canonic 001</description>\r
- <constructor-arg>\r
- <map>\r
- <entry key="parameterAtInstantiation" value="1" />\r
- </map>\r
- </constructor-arg>\r
- </bean>\r
-</beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
- xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:p="http://www.springframework.org/schema/p"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <flow id="canonic-ns.002" parent="canonic-ns.flowTemplate">\r
- <arg name="parameterAtInstantiation" value="2" />\r
- <arg name="displayWithoutControl" value="102" />\r
- <arg name="displayWithControl" value="202" />\r
- <arg name="hide" value="202" />\r
- <arg name="refWithoutValue">\r
- <beans:bean id="testDataOk" p:expected="tata" p:reached="tata"\r
- class="org.argeo.slc.core.test.BasicTestData" />\r
- </arg>\r
- </flow>\r
-</beans:beans>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
- xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <beans:import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
- <beans:import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
-\r
- <beans:import resource="canonic-ns-001.xml" />\r
- <beans:import resource="canonic-ns-002.xml" />\r
- <beans:import resource="tests.xml" />\r
-\r
- <!--\r
- Specifications definition is greatly simplified by the flow namespace\r
- -->\r
- <spec id="canonic-ns.spec">\r
- <primitive name="parameterAtInstantiation" isParameter="true"\r
- type="integer" />\r
- <primitive name="displayWithoutControl" value="100"\r
- isParameter="true" type="integer" isFrozen="true" />\r
- <primitive name="displayWithControl" value="200"\r
- isParameter="true" type="integer" />\r
- <primitive name="hide" value="300" isParameter="true" type="integer"\r
- isHidden="true" />\r
- <ref name="refWithValue" targetClass="org.argeo.slc.core.test.BasicTestData"\r
- isParameter="true" ref="testDataNok" />\r
- <ref name="refWithoutValue" targetClass="org.argeo.slc.core.test.BasicTestData" />\r
- <ref name="refWithoutValueFrozen" targetClass="org.argeo.slc.core.test.BasicTestData"\r
- isParameter="true" isFrozen="true">\r
- <value>\r
- <beans:bean class="org.argeo.slc.core.test.BasicTestData">\r
- <aop:scoped-proxy />\r
- <beans:property name="expected" value="tata" />\r
- <beans:property name="reached" value="tata" />\r
- </beans:bean>\r
- </value>\r
- </ref>\r
- </spec>\r
-\r
- <flow id="canonic-ns.flowTemplate" abstract="true" spec="canonic-ns.spec"\r
- path="/path">\r
- <beans:bean parent="task.echo"\r
- p:message="Canonical: displayWithControl=@{displayWithControl}, displayWithoutControl=@{displayWithoutControl}, hide=@{hide}"\r
- scope="execution">\r
- <aop:scoped-proxy />\r
- </beans:bean>\r
- <beans:ref bean="testRun" />\r
- </flow>\r
-\r
- <beans:bean id="testDataOk" class="org.argeo.slc.core.test.BasicTestData">\r
- <aop:scoped-proxy />\r
- <beans:property name="expected" value="tata" />\r
- <beans:property name="reached" value="tata" />\r
- </beans:bean>\r
-\r
- <beans:bean id="testDataNok" class="org.argeo.slc.core.test.BasicTestData">\r
- <aop:scoped-proxy />\r
- <beans:property name="expected" value="tata" />\r
- <beans:property name="reached" value="toto" />\r
- </beans:bean>\r
-</beans:beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
- xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
- <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
-\r
- <bean id="testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
-\r
- <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
-\r
- <bean id="testRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
- <property name="testDefinition" ref="testDef" />\r
- <property name="testResult" ref="testResult"/>\r
- </bean> \r
-\r
- <flow:spec id="test.list.spec">\r
- <flow:ref name="list1" targetClass="java.util.List">\r
- <flow:value>\r
- <!-- a list element can be used directly as default value-->\r
- <list>\r
- <value>val1</value>\r
- </list>\r
- </flow:value>\r
- </flow:ref>\r
- <flow:ref name="list2" targetClass="java.util.List" />\r
- <!-- following parameters are not used in flow -->\r
- <flow:ref name="dummyMap" targetClass="java.util.Map">\r
- <flow:value>\r
- <map></map>\r
- </flow:value>\r
- </flow:ref>\r
- <flow:ref name="dummySet" targetClass="java.util.Set">\r
- <flow:value>\r
- <set></set>\r
- </flow:value>\r
- </flow:ref>\r
- <flow:ref name="dummyProperties" targetClass="java.util.Properties">\r
- <flow:value>\r
- <props></props>\r
- </flow:value>\r
- </flow:ref>\r
- \r
- </flow:spec>\r
-\r
-\r
- <flow:flow id="test.list.flowTemplate" abstract="true" spec="test.list.spec"\r
- path="/path">\r
- <bean parent="task.echo">\r
- <property name="message" value="list1=@{list1}, list2=@{list2}" />\r
- <flow:variable/>\r
- </bean> \r
-\r
- <bean parent="testRunTemplate">\r
- <property name="testData">\r
- <bean class="org.argeo.slc.core.test.BasicTestData">\r
- <property name="expected">\r
- <flow:param name="list1"/>\r
- </property>\r
- <property name="reached">\r
- <flow:param name="list2"/>\r
- </property>\r
- </bean>\r
- </property> \r
- </bean>\r
- \r
- </flow:flow>\r
-\r
- <flow:flow id="test.list.flow1" parent="test.list.flowTemplate">\r
- <flow:arg name="list1">\r
- <list>\r
- <value>val1</value>\r
- <value>val2</value> \r
- </list>\r
- </flow:arg>\r
- <flow:arg name="list2">\r
- <list>\r
- <value>val1</value>\r
- <value>val2</value> \r
- </list>\r
- </flow:arg>\r
- \r
- <!-- not used in flow (just to test that the syntax is accepted): -->\r
- <flow:arg name="dummyMap">\r
- <map></map>\r
- </flow:arg>\r
- <flow:arg name="dummySet">\r
- <set></set>\r
- </flow:arg>\r
- <flow:arg name="dummyProperties">\r
- <props></props>\r
- </flow:arg> \r
- \r
- </flow:flow>\r
- \r
- <flow:flow id="test.list.flow2" parent="test.list.flowTemplate">\r
- <description>use default value for parameter "list1"</description>\r
- <flow:arg name="list2">\r
- <list>\r
- <value>val1</value>\r
- </list>\r
- </flow:arg>\r
- </flow:flow>\r
-\r
-\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
- xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
- xsi:schemaLocation="\r
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
- http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
-\r
- <bean id="testRun" class="org.argeo.slc.core.test.SimpleTestRun">\r
- <property name="testDefinition">\r
- <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
- </property>\r
- <property name="testData">\r
- <flow:param name="refWithValue" />\r
- </property>\r
- <!-- <property name="testData">-->\r
- <!-- <bean parent="parameterRef">-->\r
- <!-- <constructor-arg value="refWithValue" />-->\r
- <!-- </bean>-->\r
- <!-- </property>-->\r
- <property name="testResult">\r
- <bean parent="slcDefault.test.basicSimpleTestResult" scope="execution">\r
- <property name="attributes">\r
- <map>\r
- <entry key="displayWithControl" value="@{displayWithControl}" />\r
- </map>\r
- </property>\r
- <aop:scoped-proxy />\r
- </bean>\r
- </property>\r
- </bean>\r
-</beans>
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import java.util.Map;\r
-\r
-import junit.framework.TestCase;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.springframework.beans.factory.BeanFactoryUtils;\r
-import org.springframework.beans.factory.ListableBeanFactory;\r
-import org.springframework.context.ConfigurableApplicationContext;\r
-import org.springframework.context.support.ClassPathXmlApplicationContext;\r
-\r
-/** Helper for tests using a Spring application context. */\r
-public abstract class AbstractInternalSpringTestCase extends TestCase {\r
- protected final Log log = LogFactory.getLog(getClass());\r
- private ConfigurableApplicationContext context;\r
-\r
- /**\r
- * Gets (and create if necessary) the application context to use. Default\r
- * implementation uses a class path xml application context and calls\r
- * {@link #getApplicationContextLocation()}.\r
- */\r
- protected ConfigurableApplicationContext getContext() {\r
- if (context == null) {\r
- context = new ClassPathXmlApplicationContext(\r
- getApplicationContextLocation());\r
- }\r
- return context;\r
- }\r
-\r
- /** Returns a bean from the underlying context */\r
- @SuppressWarnings(value = { "unchecked" })\r
- protected <T> T getBean(String beanId) {\r
- return (T) getContext().getBean(beanId);\r
- }\r
-\r
- protected <T> T getBean(Class<? extends T> clss) {\r
- T bean = loadSingleFromContext(getContext(), clss);\r
- if (bean == null) {\r
- throw new SlcException("Cannot retrieve a unique bean of type "\r
- + clss);\r
- } else {\r
- return bean;\r
- }\r
- }\r
-\r
- /**\r
- * Th location of the application to load. The default implementation\r
- * returns <i>applicationContext.xml</i> found in the same package as the\r
- * test.\r
- */\r
- protected String getApplicationContextLocation() {\r
- return inPackage("applicationContext.xml");\r
- }\r
-\r
- /**\r
- * Prefixes the package of the class after converting the '.' to '/' in\r
- * order to have a resource path.\r
- */\r
- protected String inPackage(String suffix) {\r
- String prefix = getClass().getPackage().getName().replace('.', '/');\r
- return prefix + '/' + suffix;\r
- }\r
-\r
- @SuppressWarnings(value = { "unchecked" })\r
- protected <T> T loadSingleFromContext(ListableBeanFactory context,\r
- Class<T> clss) {\r
- Map<String, T> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(\r
- context, clss, false, false);\r
- if (beans.size() == 1) {\r
- return beans.values().iterator().next();\r
- } else if (beans.size() > 1) {\r
- if (log.isDebugEnabled()) {\r
- log\r
- .debug(("Found more that on bean for type " + clss\r
- + ": " + beans.keySet()));\r
- }\r
- return null;\r
- } else {\r
- return null;\r
- }\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import java.util.List;\r
-\r
-import org.argeo.slc.core.test.SimpleTestResult;\r
-import org.argeo.slc.test.TestResultPart;\r
-import org.argeo.slc.test.TestStatus;\r
-import org.argeo.slc.test.context.ContextAware;\r
-\r
-public class ContextTest extends AbstractInternalSpringTestCase {\r
-\r
- public void testComplexContext() {\r
- SimpleTestResult testResult = new SimpleTestResult();\r
- ContextUtils.compareReachedExpected(\r
- (ContextAware) getBean("context.c1"), testResult);\r
- ContextUtils.compareReachedExpected(\r
- (ContextAware) getBean("context.c2"), testResult);\r
- ContextUtils.compareReachedExpected(\r
- (ContextAware) getBean("context.c3"), testResult);\r
-\r
- List<TestResultPart> parts = testResult.getParts();\r
- assertEquals(6, parts.size());\r
- assertEquals(TestStatus.PASSED, parts.get(0).getStatus());\r
- assertEquals(TestStatus.PASSED, parts.get(1).getStatus());\r
- assertEquals(TestStatus.PASSED, parts.get(2).getStatus());\r
- assertEquals(TestStatus.FAILED, parts.get(3).getStatus());\r
- assertEquals(TestStatus.PASSED, parts.get(4).getStatus());\r
- assertEquals(TestStatus.PASSED, parts.get(5).getStatus());\r
- }\r
-}\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<!--\r
-\r
- Copyright (C) 2007-2012 Argeo GmbH\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
--->\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
-\r
- <bean id="parentContext.pc1" parent="parentContext.template">\r
- <property name="values">\r
- <map>\r
- <entry key="rootvar" value="text" />\r
- </map>\r
- </property>\r
- <property name="expectedValues">\r
- <map>\r
- <entry key="reference" value="20" />\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="context.c1" parent="context.template">\r
- <property name="parentContext" ref="parentContext.pc1" />\r
- <property name="values">\r
- <map>\r
- <entry key="reference" value="20" />\r
- <entry key="any" value="999" />\r
- <entry key="skipped" value="999" />\r
- </map>\r
- </property>\r
- <property name="expectedValues">\r
- <map>\r
- <entry key="reference" value="21" />\r
- <entry key="any" value="*" />\r
- <entry key="skipped" value="!" />\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="context.c2" parent="context.template">\r
- <property name="parentContext" ref="parentContext.pc1" />\r
- <property name="values">\r
- <map>\r
- <entry key="var" value="37" />\r
- <entry key="bad" value="56" />\r
- </map>\r
- </property>\r
- <property name="expectedValues">\r
- <map>\r
- <entry key="var" value="37" />\r
- <entry key="bad" value="57" />\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="parentContext.pc2" parent="parentContext.template">\r
- <property name="parentContext" ref="parentContext.pc1" />\r
- <property name="expectedValues">\r
- <map>\r
- <entry key="reference" value="40" />\r
- </map>\r
- </property>\r
- </bean>\r
-\r
- <bean id="context.c3" parent="context.template">\r
- <property name="parentContext" ref="parentContext.pc2" />\r
- <property name="values">\r
- <map>\r
- <entry key="reference" value="41" />\r
- <entry key="rootvar" value="textX" />\r
- </map>\r
- </property>\r
- <property name="expectedValues">\r
- <map>\r
- <entry key="reference" value="40" />\r
- <entry key="rootvar" value="text" />\r
- </map>\r
- </property>\r
- </bean>\r
-\r
-\r
- <bean id="parentContext.template"\r
- class="org.argeo.slc.core.test.context.SimpleParentContextAware"\r
- abstract="true">\r
- </bean>\r
-\r
- <bean id="context.template"\r
- class="org.argeo.slc.core.test.context.SimpleContextAware"\r
- abstract="true">\r
- </bean>\r
-</beans>
\ No newline at end of file
+++ /dev/null
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.argeo.slc</groupId>
- <artifactId>argeo-slc</artifactId>
- <version>2.1.17-SNAPSHOT</version>
- <relativePath>..</relativePath>
- </parent>
- <artifactId>org.argeo.slc.core</artifactId>
- <name>SLC Runtime</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <skipTests>true</skipTests>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <!-- Commons -->
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.enterprise</artifactId>
- <version>${version.argeo-commons}</version>
- </dependency>
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.node.api</artifactId>
- <version>${version.argeo-commons}</version>
- </dependency>
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.cms</artifactId>
- <version>${version.argeo-commons}</version>
- </dependency>
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.jcr</artifactId>
- <version>${version.argeo-commons}</version>
- </dependency>
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.util</artifactId>
- <version>${version.argeo-commons}</version>
- </dependency>
-
- <!-- SLC -->
- <dependency>
- <groupId>org.argeo.slc</groupId>
- <artifactId>org.argeo.slc.api</artifactId>
- <version>2.1.17-SNAPSHOT</version>
- </dependency>
-
- <!-- Spring -->
- <dependency>
- <groupId>org.argeo.tp.spring</groupId>
- <artifactId>org.springframework.beans</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.spring</groupId>
- <artifactId>org.springframework.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.spring</groupId>
- <artifactId>org.springframework.context</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.spring</groupId>
- <artifactId>org.springframework.aop</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.gemini</groupId>
- <artifactId>org.eclipse.gemini.blueprint.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.gemini</groupId>
- <artifactId>org.eclipse.gemini.blueprint.io</artifactId>
- </dependency>
-
- <!-- Ant -->
- <dependency>
- <groupId>org.argeo.tp.apache.ant</groupId>
- <artifactId>org.apache.ant</artifactId>
- </dependency>
-
- </dependencies>
-</project>
\ No newline at end of file
+++ /dev/null
-/*
- * 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.ant;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.argeo.slc.core.execution.AbstractExecutionFlowGenerator;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.core.io.Resource;
-
-public class AntFlowGenerator extends AbstractExecutionFlowGenerator {
- private List<Resource> antFiles = new ArrayList<Resource>();
-
- protected Map<String, BeanDefinition> createExecutionFlowDefinitions(
- ConfigurableListableBeanFactory beanFactory) {
- Map<String, BeanDefinition> definitions = new HashMap<String, BeanDefinition>();
-
- for (Resource antFile : antFiles) {
- AntRun antRun = new AntRun();
- antRun.setBuildFile(antFile);
-
- List<Runnable> executables = new ArrayList<Runnable>();
- executables.add(antRun);
- definitions.put("ant." + antFile.getFilename(),
- createDefaultFlowDefinition(executables));
- }
- return definitions;
- }
-
- public void setAntFiles(List<Resource> antFiles) {
- this.antFiles = antFiles;
- }
-
-}
+++ /dev/null
-/*
- * 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.ant;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Vector;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.tools.ant.BuildEvent;
-import org.apache.tools.ant.BuildListener;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.ProjectHelper;
-import org.apache.tools.ant.helper.ProjectHelper2;
-import org.argeo.slc.SlcException;
-import org.springframework.core.io.Resource;
-
-public class AntRun implements Runnable {
- private final static Log log = LogFactory.getLog(AntRun.class);
-
- private Resource buildFile;
- private File baseDir;
-
- private List<String> targets = new ArrayList<String>();
- private Map<Object, Object> properties = new HashMap<Object, Object>();
-
- public void run() {
- Project project = new Project();
-
- try {
- String path = buildFile.getURL().getPath();
- project.setUserProperty("ant.file", path);
- project.setBaseDir(extractBaseDir(path));
-
- project.init();
- ProjectHelper projectHelper = new ProjectHelper2();
- project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE,
- projectHelper);
- projectHelper.parse(project, buildFile.getURL());
- } catch (Exception e) {
- throw new SlcException("Could not parse " + buildFile, e);
- }
-
- if (properties != null) {
- for (Map.Entry<Object, Object> entry : properties.entrySet()) {
- project.setUserProperty(entry.getKey().toString(), entry
- .getValue().toString());
- }
- }
-
- project.fireBuildStarted();
- Throwable exception = null;
- try {
- project.addBuildListener(new LoggingListener());
- if (targets.size() == 0) {
- project.executeTarget(project.getDefaultTarget());
- } else {
- project.executeTargets(new Vector<String>(targets));
- }
- } catch (Throwable e) {
- exception = e;
- throw new SlcException("Could not run Ant script " + buildFile, e);
- } finally {
- project.fireBuildFinished(exception);
- }
- }
-
- private File extractBaseDir(String path) {
- if(this.baseDir!=null)
- return this.baseDir;
-
- String baseDir = null;
- if (path.length() > 1) {
- int indx = path.lastIndexOf('/', path.length() - 1);
- if (indx == -1 || indx == 0) {
- baseDir = "/";
- } else {
- baseDir = path.substring(0, indx) + "/";
- }
- } else {
- baseDir = "/";
- }
- File file = new File(baseDir);
- if (file.exists()) {
- return file;
- } else {
- return new File(System.getProperty("user.dir"));
- }
- }
-
- public void setBuildFile(Resource buildFile) {
- this.buildFile = buildFile;
- }
-
- public void setTargets(List<String> targets) {
- this.targets = targets;
- }
-
- public void setProperties(Map<Object, Object> properties) {
- this.properties = properties;
- }
-
- public void setBaseDir(File baseDir) {
- this.baseDir = baseDir;
- }
-
- protected static class LoggingListener implements BuildListener {
-
- public void buildFinished(BuildEvent event) {
- if (log.isDebugEnabled())
- log.debug("Ant build finished: " + event);
- }
-
- public void buildStarted(BuildEvent event) {
- if (log.isDebugEnabled())
- log.debug("Ant build started: " + event);
- }
-
- public void messageLogged(BuildEvent event) {
- if (event.getPriority() == Project.MSG_DEBUG) {
- if (log.isTraceEnabled())
- log.trace(event.getMessage());
- } else if (event.getPriority() == Project.MSG_VERBOSE) {
- if (log.isDebugEnabled())
- log.debug(event.getMessage());
- } else if (event.getPriority() == Project.MSG_INFO) {
- log.info(event.getMessage());
-
- } else if (event.getPriority() == Project.MSG_WARN) {
- log.warn(event.getMessage());
-
- } else if (event.getPriority() == Project.MSG_ERR) {
- log.error(event.getMessage());
- } else {
- log.error(event.getMessage());
- }
- }
-
- public void targetFinished(BuildEvent event) {
- if (log.isTraceEnabled())
- log.debug("Target finished: " + event.getTarget());
- }
-
- public void targetStarted(BuildEvent event) {
- if (log.isTraceEnabled())
- log.debug("Target started: " + event.getTarget());
- }
-
- public void taskFinished(BuildEvent event) {
- }
-
- public void taskStarted(BuildEvent event) {
- }
- }
-}
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.build;\r
-\r
-import java.util.StringTokenizer;\r
-\r
-/**\r
- * <p>\r
- * An implementation of the distribution id using the standard\r
- * Major.Minor.Release notation. And additional arbitrary string can also be\r
- * added.\r
- * </p>\r
- * \r
- * <p>\r
- * <b>Examples:</b><br>\r
- * 0.2.6<br>\r
- * 2.4.12.RC1\r
- * </p>\r
- */\r
-public class VersionDistributionId {\r
-\r
- private Integer major;\r
- private Integer minor;\r
- private Integer release;\r
- private String additional;\r
-\r
- /** Parse the provided string in order to set the various components. */\r
- public void setVersionString(String str) {\r
- StringTokenizer st = new StringTokenizer(str, ".");\r
- if (st.hasMoreTokens())\r
- major = Integer.parseInt(st.nextToken());\r
- if (st.hasMoreTokens())\r
- minor = Integer.parseInt(st.nextToken());\r
- if (st.hasMoreTokens())\r
- release = Integer.parseInt(st.nextToken());\r
- if (st.hasMoreTokens())\r
- additional = st.nextToken();\r
- }\r
-\r
- public Integer getMajor() {\r
- return major;\r
- }\r
-\r
- public void setMajor(Integer major) {\r
- this.major = major;\r
- }\r
-\r
- public Integer getMinor() {\r
- return minor;\r
- }\r
-\r
- public void setMinor(Integer minor) {\r
- this.minor = minor;\r
- }\r
-\r
- public Integer getRelease() {\r
- return release;\r
- }\r
-\r
- public void setRelease(Integer release) {\r
- this.release = release;\r
- }\r
-\r
- public String getAdditional() {\r
- return additional;\r
- }\r
-\r
- public void setAdditional(String additional) {\r
- this.additional = additional;\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- // TODO Auto-generated method stub\r
- return super.equals(obj);\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return major + "." + minor + "." + release\r
- + (additional != null ? "." + additional : "");\r
- }\r
-\r
-}\r
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-<html>\r
-<head></head>\r
-<body>\r
-SLC Build: building of software systems.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-/*
- * 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<String> includes = new ArrayList<String>();
- private String exclude;
- private List<String> excludes = new ArrayList<String>();
- 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<String, Resource> listResources() {
- try {
- Map<String, Resource> res = new TreeMap<String, Resource>();
- 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<String, Resource> 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<String> 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<String> includes) {
- this.includes = includes;
- }
-
- public void setExclude(String exclude) {
- this.exclude = exclude;
- }
-
- public void setExcludes(List<String> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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.springframework.core.io.Resource;
-import org.springframework.util.DigestUtils;
-
-/** 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 org.argeo.util.DigestUtils.digest(algorithm, file);
- } catch (IOException e) {
- try {
- return org.argeo.util.DigestUtils.digest(algorithm,
- resource.getInputStream());
- } catch (IOException e1) {
- throw new SlcException("Cannot digest " + resource
- + " with algorithm " + algorithm, e);
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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<String, Resource> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<ResourceSet> resourceSets = new ArrayList<ResourceSet>();
-
- public Map<String, Resource> listResources() {
- Map<String, Resource> res = new HashMap<String, Resource>();
- for (ResourceSet resourceSet : resourceSets) {
- res.putAll(resourceSet.listResources());
- }
- return res;
- }
-
- /** Last listed override previous for the same relative paths. */
- public void setResourceSets(List<ResourceSet> resourceSets) {
- this.resourceSets = resourceSets;
- }
-
- public List<ResourceSet> getResourceSets() {
- return resourceSets;
- }
-
-}
+++ /dev/null
-/*
- * 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<String, Resource> listResources();
-}
+++ /dev/null
-/*
- * 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<String, String> paths = new TreeMap<String, String>();
-
- 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<String, String> getPaths() {
- return paths;
- }
-
- public void setPaths(Map<String, String> paths) {
- this.paths = paths;
- }
-
- public void setDistribution(Distribution distribution) {
- this.distribution = distribution;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-<html>\r
-<head></head>\r
-<body>\r
-SLC Deploy: deployment of software systems.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-/*
- * 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<String, BeanDefinition> createExecutionFlowDefinitions(
- ConfigurableListableBeanFactory beanFactory);
-
- public void postProcessBeanFactory(
- ConfigurableListableBeanFactory beanFactory) throws BeansException {
- if (!(beanFactory instanceof BeanDefinitionRegistry)) {
- throw new SlcException("Can only work on "
- + BeanDefinitionRegistry.class);
- }
-
- Map<String, BeanDefinition> 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<Runnable> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<FilteredNotifier> filteredNotifiers = Collections
- // .synchronizedList(new ArrayList<FilteredNotifier>());
-
- 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<? extends String, ? extends Object> 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
- //
- executionContext.beforeFlow(flow);
- try {
- flow.run();
- } finally {
- executionContext.afterFlow(flow);
- }
- //
- //
- //
- }
-
- // public void dispatchUpdateStatus(ExecutionProcess process,
- // String oldStatus, String newStatus) {
- // // filtered notifiers
- // for (Iterator<FilteredNotifier> 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<ExecutionStep> steps) {
- // process.addSteps(steps);
- // for (Iterator<FilteredNotifier> it = filteredNotifiers.iterator(); it
- // .hasNext();) {
- // FilteredNotifier filteredNotifier = it.next();
- // if (filteredNotifier.receiveFrom(process))
- // filteredNotifier.getNotifier().addSteps(process, steps);
- // }
- // }
-
- // public void registerProcessNotifier(ExecutionProcessNotifier notifier,
- // Map<String, String> properties) {
- // filteredNotifiers.add(new FilteredNotifier(notifier, properties));
- // }
- //
- // public void unregisterProcessNotifier(ExecutionProcessNotifier notifier,
- // Map<String, String> properties) {
- // filteredNotifiers.remove(notifier);
- // }
-
- // protected class FilteredNotifier {
- // private final ExecutionProcessNotifier notifier;
- // private final String processId;
- //
- // public FilteredNotifier(ExecutionProcessNotifier notifier,
- // Map<String, String> properties) {
- // super();
- // this.notifier = notifier;
- // if (properties == null)
- // properties = new HashMap<String, String>();
- // 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;
- // }
- //
- // }
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<String, ExecutionFlow> 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<String, Object> values = new TreeMap<String, Object>();
- 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<String, ExecutionFlow> listFlows() {
- GenericBeanFactoryAccessor accessor = new GenericBeanFactoryAccessor(
- applicationContext);
- Map<String, ExecutionFlow> 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;
- }*/
-
-}
+++ /dev/null
-/*
- * 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.DefaultNameVersion;
-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<String, ProcessThread> runningProcesses = Collections
- .synchronizedMap(new HashMap<String, ProcessThread>());
-
- 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<ProcessThread> it = runningProcesses.values().iterator();
- while (it.hasNext()) {
- ProcessThread pThread = it.next();
- if (!pThread.isAlive())
- it.remove();
- }
- }
-
- public String process(List<URI> 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 DefaultNameVersion(path[1]);
- StringBuilder flow = new StringBuilder();
- for (int i = 2; i < path.length; i++)
- flow.append('/').append(path[i]);
-
- Map<String, Object> 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 DefaultNameVersion(moduleName, moduleVersion));
- emd = modulesManager.getExecutionModuleDescriptor(moduleName,
- moduleVersion);
- } catch (SlcException e) {
- if (defaultModulePrefix != null) {
- moduleName = defaultModulePrefix + "." + moduleName;
- modulesManager.start(new DefaultNameVersion(moduleName,
- moduleVersion));
- emd = modulesManager.getExecutionModuleDescriptor(moduleName,
- moduleVersion);
- } else
- throw e;
- }
- return emd;
- }
-
- public List<ExecutionModuleDescriptor> listExecutionModuleDescriptors() {
- return modulesManager.listExecutionModules();
- }
-
- public boolean ping() {
- return true;
- }
-
- /*
- * UTILITIES
- */
- /**
- * @param query
- * can be null
- */
- static Map<String, Object> getQueryMap(String query) {
- Map<String, Object> map = new LinkedHashMap<String, Object>();
- 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();
- }
-}
+++ /dev/null
-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.slc.DefaultNameVersion;
-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;
-
-/**
- * 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<URI> 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 DefaultNameVersion(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<URI> 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 DefaultNameVersion(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<String, Object> 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<URI> asURIs(String[] args) {
- try {
- List<URI> uris = new ArrayList<URI>();
- List<String> leftOvers = new ArrayList<String>();
-
- Boolean hasArgs = false;
- String currKey = null;
- StringBuilder currUri = null;
- Iterator<String> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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.ExecutionContext;
-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<String, Object> parameters = new HashMap<String, Object>();
- private List<Runnable> executables = new ArrayList<Runnable>();
-
- private String path;
-
- private Boolean failOnError = true;
-
- // Only needed if stacked execution flows are used
- private ExecutionContext executionContext = null;
-
- public DefaultExecutionFlow() {
- this.executionSpec = new DefaultExecutionSpec();
- }
-
- public DefaultExecutionFlow(ExecutionSpec executionSpec) {
- this.executionSpec = executionSpec;
- }
-
- public DefaultExecutionFlow(ExecutionSpec executionSpec,
- Map<String, Object> 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<Runnable> 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) {
- try {
- if (executionContext != null)
- if (runnable instanceof ExecutionFlow)
- executionContext.beforeFlow((ExecutionFlow) runnable);
- runnable.run();
- } finally {
- if (executionContext != null)
- if (runnable instanceof ExecutionFlow)
- executionContext.afterFlow((ExecutionFlow) runnable);
- }
- }
-
- 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<Runnable> executables) {
- this.executables = executables;
- }
-
- public void setParameters(Map<String, Object> 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;
- }
-
- public void setExecutionContext(ExecutionContext executionContext) {
- this.executionContext = executionContext;
- }
-
-}
+++ /dev/null
-/*
- * 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<String, Object> convertValues(
- ExecutionFlowDescriptor executionFlowDescriptor) {
- Map<String, Object> values = executionFlowDescriptor.getValues();
- Map<String, Object> convertedValues = new HashMap<String, Object>();
- 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<String, ExecutionFlow> executionFlows) {
- SortedSet<ExecutionFlowDescriptor> set = new TreeSet<ExecutionFlowDescriptor>(
- 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);
- }
-
- 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<String, Object> values = new TreeMap<String, Object>();
- 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);
- // Takes description from spring
- BeanFactory bf = getBeanFactory();
- if (bf != null) {
- BeanDefinition bd = getBeanFactory().getBeanDefinition(name);
- efd.setDescription(bd.getDescription());
- }
- return efd;
- }
-
- 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<String, ?> 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<ExecutionFlowDescriptor> {
- @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;
- }
- }
-
- }
-}
+++ /dev/null
-/*
- * 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<String, ExecutionSpecAttribute> attributes = new HashMap<String, ExecutionSpecAttribute>();
-
- private String name = INTERNAL_NAME;
-
- public Map<String, ExecutionSpecAttribute> getAttributes() {
- return attributes;
- }
-
- public void setAttributes(Map<String, ExecutionSpecAttribute> 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<RefValueChoice> 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<RefValueChoice> buildRefValueChoices(RefSpecAttribute rsa) {
- List<RefValueChoice> choices = new ArrayList<RefValueChoice>();
- 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
-
- public synchronized void enterFlow(ExecutionFlow executionFlow) {
- ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
- stack.push(runtime);
-
- Map<String, ExecutionSpecAttribute> 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 <code>null</code> 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 </code>null<code> 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<String, Object> scopedObjects = new HashMap<String, Object>();
- private final Map<String, Object> localVariables = new HashMap<String, Object>();
- private final String uuid = UUID.randomUUID().toString();
-
- public ExecutionFlowRuntime(ExecutionFlow executionFlow) {
- this.executionFlow = executionFlow;
- }
-
- public ExecutionFlow getExecutionFlow() {
- return executionFlow;
- }
-
- public Map<String, Object> getScopedObjects() {
- return scopedObjects;
- }
-
- public String getUuid() {
- return uuid;
- }
-
- public Map<String, Object> getLocalVariables() {
- return localVariables;
- }
-
- @Override
- public String toString() {
- return "Stack Level #" + uuid;
- }
-
- }
-}
+++ /dev/null
-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<ExecutionStep> steps = new ArrayList<ExecutionStep>();
- private List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();
-
- public String getUuid() {
- return uuid;
- }
-
- public String getStatus() {
- return status;
- }
-
- public void setStatus(String status) {
- this.status = status;
- }
-
- public void addSteps(List<ExecutionStep> steps) {
- steps.addAll(steps);
- }
-
- public List<RealizedFlow> getRealizedFlows() {
- return realizedFlows;
- }
-
- public List<ExecutionStep> getSteps() {
- return steps;
- }
-
- public void setSteps(List<ExecutionStep> steps) {
- this.steps = steps;
- }
-
- public void setUuid(String uuid) {
- this.uuid = uuid;
- }
-
- public void setRealizedFlows(List<RealizedFlow> realizedFlows) {
- this.realizedFlows = realizedFlows;
- }
-
-}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution;\r
-\r
-import java.beans.PropertyDescriptor;\r
-import java.util.HashSet;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.execution.ExecutionContext;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.springframework.beans.BeansException;\r
-import org.springframework.beans.MutablePropertyValues;\r
-import org.springframework.beans.PropertyValue;\r
-import org.springframework.beans.PropertyValues;\r
-import org.springframework.beans.factory.BeanDefinitionStoreException;\r
-import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;\r
-import org.springframework.beans.factory.config.TypedStringValue;\r
-import org.springframework.beans.factory.support.ManagedList;\r
-import org.springframework.beans.factory.support.ManagedMap;\r
-import org.springframework.beans.factory.support.ManagedSet;\r
-import org.springframework.util.ObjectUtils;\r
-import org.springframework.util.StringUtils;\r
-\r
-/**\r
- * Spring post processor which ensures that execution parameters are properly\r
- * set. It is used at two levels: first during instantiation for instantiation\r
- * parameters which allow to implement templates, then at runtime in order to\r
- * interpret @{} placeholders when object of scope execution are instantiated.\r
- */\r
-public class ExecutionParameterPostProcessor extends\r
- InstantiationAwareBeanPostProcessorAdapter {\r
-\r
- private final static Log log = LogFactory\r
- .getLog(ExecutionParameterPostProcessor.class);\r
-\r
- private ExecutionContext executionContext;\r
- private InstantiationManager instantiationManager;\r
-\r
- private String placeholderPrefix = "@{";\r
- private String placeholderSuffix = "}";\r
- private String nullValue;\r
-\r
- @Override\r
- public PropertyValues postProcessPropertyValues(PropertyValues pvs,\r
- PropertyDescriptor[] pds, Object bean, String beanName)\r
- throws BeansException {\r
-\r
- // TODO: resolve at execution only if scope is execution\r
- // TODO: deal with placeholders in RuntimeBeanReference and\r
- // RuntimeBeanNameReference\r
-\r
- MutablePropertyValues newPvs = new MutablePropertyValues();\r
-\r
- boolean changesOccured = false;\r
-\r
- for (PropertyValue pv : pvs.getPropertyValues()) {\r
- Object convertedValue = resolveValue(beanName, bean, pv.getValue());\r
- newPvs.addPropertyValue(new PropertyValue(pv, convertedValue));\r
- if (convertedValue != pv.getValue()) {\r
- changesOccured = true;\r
- }\r
- }\r
-\r
- return changesOccured ? newPvs : pvs;\r
- }\r
-\r
- @Override\r
- public boolean postProcessAfterInstantiation(Object bean, String beanName)\r
- throws BeansException {\r
- if (bean instanceof ExecutionFlow)\r
- instantiationManager.flowInitializationStarted(\r
- (ExecutionFlow) bean, beanName);\r
- return true;\r
- }\r
-\r
- @Override\r
- public Object postProcessAfterInitialization(Object bean, String beanName)\r
- throws BeansException {\r
- if (bean instanceof ExecutionFlow)\r
- instantiationManager.flowInitializationFinished(\r
- (ExecutionFlow) bean, beanName);\r
- return bean;\r
- }\r
-\r
- protected String resolvePlaceholder(Object bean, String placeholder) {\r
- if (instantiationManager.isInFlowInitialization())\r
- return instantiationManager.getInitializingFlowParameter(\r
- placeholder).toString();\r
-\r
- else {// execution\r
- // next call fail if no execution context available\r
- Object obj = executionContext.getVariable(placeholder);\r
- if (obj != null) {\r
- return obj.toString();\r
- }\r
- }\r
-\r
- return null;\r
- }\r
-\r
- public Object resolveValue(String beanName, Object bean, Object value) {\r
- if (value instanceof TypedStringValue) {\r
- TypedStringValue tsv = (TypedStringValue) value;\r
- String originalValue = tsv.getValue();\r
-\r
- String convertedValue = resolveString(beanName, bean, originalValue);\r
- if (convertedValue == null)\r
- return null;\r
- return convertedValue.equals(originalValue) ? value\r
- : new TypedStringValue(convertedValue);\r
- } else if (value instanceof String) {\r
- String originalValue = value.toString();\r
- String convertedValue = resolveString(beanName, bean, originalValue);\r
- if (convertedValue == null)\r
- return null;\r
- return convertedValue.equals(originalValue) ? value\r
- : convertedValue;\r
- } else if (value instanceof ManagedMap) {\r
- Map<?, ?> mapVal = (Map<?, ?>) value;\r
-\r
- Map<Object, Object> newContent = new ManagedMap<Object, Object>();\r
- boolean entriesModified = false;\r
- for (Iterator<?> it = mapVal.entrySet().iterator(); it.hasNext();) {\r
- Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();\r
- Object key = entry.getKey();\r
- int keyHash = (key != null ? key.hashCode() : 0);\r
- Object newKey = resolveValue(beanName, bean, key);\r
- int newKeyHash = (newKey != null ? newKey.hashCode() : 0);\r
- Object val = entry.getValue();\r
- Object newVal = resolveValue(beanName, bean, val);\r
- newContent.put(newKey, newVal);\r
- entriesModified = entriesModified\r
- || (newVal != val || newKey != key || newKeyHash != keyHash);\r
- }\r
-\r
- return entriesModified ? newContent : value;\r
- } else if (value instanceof ManagedList) {\r
- List<?> listVal = (List<?>) value;\r
- List<Object> newContent = new ManagedList<Object>();\r
- boolean valueModified = false;\r
-\r
- for (int i = 0; i < listVal.size(); i++) {\r
- Object elem = listVal.get(i);\r
- Object newVal = resolveValue(beanName, bean, elem);\r
- newContent.add(newVal);\r
- if (!ObjectUtils.nullSafeEquals(newVal, elem)) {\r
- valueModified = true;\r
- }\r
- }\r
- return valueModified ? newContent : value;\r
- } else if (value instanceof ManagedSet) {\r
- Set<?> setVal = (Set<?>) value;\r
- Set<Object> newContent = new ManagedSet<Object>();\r
- boolean entriesModified = false;\r
- for (Iterator<?> it = setVal.iterator(); it.hasNext();) {\r
- Object elem = it.next();\r
- int elemHash = (elem != null ? elem.hashCode() : 0);\r
- Object newVal = resolveValue(beanName, bean, elem);\r
- int newValHash = (newVal != null ? newVal.hashCode() : 0);\r
- newContent.add(newVal);\r
- entriesModified = entriesModified\r
- || (newVal != elem || newValHash != elemHash);\r
- }\r
- return entriesModified ? newContent : value;\r
- } else {\r
- // log.debug(beanName + ": " + value.getClass() + " : " + value);\r
- return value;\r
- }\r
-\r
- }\r
-\r
- private String resolveString(String beanName, Object bean, String strVal) {\r
- // in case <null/> is passed\r
- if (strVal == null)\r
- return null;\r
-\r
- String value = parseStringValue(bean, strVal, new HashSet<String>());\r
-\r
- if (value == null)\r
- throw new SlcException("Could not resolve placeholder '" + strVal\r
- + "' in bean '" + beanName + "'");\r
-\r
- return (value.equals(nullValue) ? null : value);\r
- }\r
-\r
- public void setPlaceholderPrefix(String placeholderPrefix) {\r
- this.placeholderPrefix = placeholderPrefix;\r
- }\r
-\r
- public void setPlaceholderSuffix(String placeholderSuffix) {\r
- this.placeholderSuffix = placeholderSuffix;\r
- }\r
-\r
- public void setNullValue(String nullValue) {\r
- this.nullValue = nullValue;\r
- }\r
-\r
- public void setInstantiationManager(\r
- InstantiationManager instantiationManager) {\r
- this.instantiationManager = instantiationManager;\r
- }\r
-\r
- public void setExecutionContext(ExecutionContext executionContext) {\r
- this.executionContext = executionContext;\r
- }\r
-\r
- //\r
- // Following methods hacked from the internals of\r
- // PropertyPlaceholderConfigurer\r
- //\r
-\r
- protected String parseStringValue(Object bean, String strVal,\r
- Set<String> visitedPlaceholders)\r
- throws BeanDefinitionStoreException {\r
-\r
- // in case <null/> is passed\r
- if (strVal == null)\r
- return null;\r
-\r
- StringBuffer buf = new StringBuffer(strVal);\r
-\r
- int startIndex = strVal.indexOf(placeholderPrefix);\r
- while (startIndex != -1) {\r
- int endIndex = findPlaceholderEndIndex(buf, startIndex);\r
- if (endIndex != -1) {\r
- String placeholder = buf.substring(startIndex\r
- + placeholderPrefix.length(), endIndex);\r
- if (!visitedPlaceholders.add(placeholder)) {\r
- throw new BeanDefinitionStoreException(\r
- "Circular placeholder reference '" + placeholder\r
- + "' in property definitions");\r
- }\r
- // Recursive invocation, parsing placeholders contained in\r
- // the placeholder key.\r
- placeholder = parseStringValue(bean, placeholder,\r
- visitedPlaceholders);\r
- // Now obtain the value for the fully resolved key...\r
- String propVal = resolvePlaceholder(bean, placeholder);\r
- if (propVal != null) {\r
- // Recursive invocation, parsing placeholders contained\r
- // in the\r
- // previously resolved placeholder value.\r
- propVal = parseStringValue(bean, propVal,\r
- visitedPlaceholders);\r
- buf.replace(startIndex,\r
- endIndex + placeholderSuffix.length(), propVal);\r
- if (log.isTraceEnabled()) {\r
- log.trace("Resolved placeholder '" + placeholder + "'");\r
- }\r
- startIndex = buf.indexOf(placeholderPrefix, startIndex\r
- + propVal.length());\r
- } else {\r
- throw new BeanDefinitionStoreException(\r
- "Could not resolve placeholder '" + placeholder\r
- + "'");\r
- }\r
- visitedPlaceholders.remove(placeholder);\r
- } else {\r
- startIndex = -1;\r
- }\r
- }\r
-\r
- return buf.toString();\r
- }\r
-\r
- private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {\r
- int index = startIndex + placeholderPrefix.length();\r
- int withinNestedPlaceholder = 0;\r
- while (index < buf.length()) {\r
- if (StringUtils.substringMatch(buf, index, placeholderSuffix)) {\r
- if (withinNestedPlaceholder > 0) {\r
- withinNestedPlaceholder--;\r
- index = index + placeholderSuffix.length();\r
- } else {\r
- return index;\r
- }\r
- } else if (StringUtils\r
- .substringMatch(buf, index, placeholderPrefix)) {\r
- withinNestedPlaceholder++;\r
- index = index + placeholderPrefix.length();\r
- } else {\r
- index++;\r
- }\r
- }\r
- return -1;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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<Resource> {
- private ExecutionResources executionResources;
- private String relativePath;
-
- public Resource getObject() throws Exception {
- Assert.notNull(executionResources, "executionResources is null");
- Assert.notNull(relativePath, "relativePath is null");
- return executionResources.getWritableResource(relativePath);
- }
-
- public Class<? extends Object> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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> executionStack = new ThreadLocal<ExecutionStack>();
- public final ThreadLocal<String> executionStackBeanName = new ThreadLocal<String>();
-
- private final ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
- private final ThreadLocal<String> executionContextBeanName = new ThreadLocal<String>();
-
- 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> T dealWithSpecialScopedObject(String name,
- ThreadLocal<T> threadLocal,
- ThreadLocal<String> 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);
- }
-
-}
+++ /dev/null
-/*
- * 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.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.security.auth.Subject;
-
-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;
-
-/** 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 final AccessControlContext accessControlContext;
-
- private List<Runnable> destructionCallbacks = new ArrayList<Runnable>();
-
- public ExecutionThread(ProcessThreadGroup processThreadGroup, ExecutionModulesManager executionModulesManager,
- RealizedFlow realizedFlow) {
- super(processThreadGroup, "Flow " + realizedFlow.getFlowDescriptor().getName());
- this.realizedFlow = realizedFlow;
- this.executionModulesManager = executionModulesManager;
- accessControlContext = AccessController.getContext();
- }
-
- 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 {
- Subject subject = Subject.getSubject(accessControlContext);
- try {
- Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
-
- @Override
- public Void run() throws Exception {
- 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
- return null;
- }
-
- });
- } catch (PrivilegedActionException privilegedActionException) {
- throw (Exception) privilegedActionException.getCause();
- }
- } 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
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-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);
- }
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution;\r
-\r
-import java.util.Stack;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.argeo.slc.execution.ExecutionSpecAttribute;\r
-\r
-/** Manage parameters that need to be set during the instantiation of a flow */\r
-public class InstantiationManager {\r
-\r
- private final static Log log = LogFactory\r
- .getLog(InstantiationManager.class);\r
-\r
- private ThreadLocal<Stack<ExecutionFlow>> flowStack = new ThreadLocal<Stack<ExecutionFlow>>();\r
-\r
- public Object createRef(String name) {\r
-\r
- if ((flowStack.get() == null) || flowStack.get().empty()) {\r
- throw new SlcException("No flow is currently initializing."\r
- + " Declare ParameterRef as inner beans or prototypes.");\r
- }\r
-\r
- return getInitializingFlowParameter(name);\r
- }\r
-\r
- public void flowInitializationStarted(ExecutionFlow flow, String flowName) {\r
- // set the flow name if it is DefaultExecutionFlow\r
- if (flow instanceof DefaultExecutionFlow) {\r
- ((DefaultExecutionFlow) flow).setBeanName(flowName);\r
- }\r
-\r
- if (log.isTraceEnabled())\r
- log.trace("Start initialization of " + flow.hashCode() + " ("\r
- + flow + " - " + flow.getClass() + ")");\r
-\r
- // log.info("# flowInitializationStarted " + flowName);\r
- // create a stack for this thread if there is none\r
- if (flowStack.get() == null) {\r
- flowStack.set(new Stack<ExecutionFlow>());\r
- }\r
- flowStack.get().push(flow);\r
- }\r
-\r
- public void flowInitializationFinished(ExecutionFlow flow, String flowName) {\r
- if (log.isTraceEnabled())\r
- log.trace("Finish initialization of " + flow.hashCode() + " ("\r
- + flow + " - " + flow.getClass() + ")");\r
-\r
- if (flowStack.get() != null) {\r
- ExecutionFlow registeredFlow = flowStack.get().pop();\r
- if (registeredFlow != null) {\r
- if (!flow.getName().equals(registeredFlow.getName()))\r
- throw new SlcException("Current flow is " + flow);\r
- // log.info("# flowInitializationFinished " + flowName);\r
- // initializingFlow.set(null);\r
- }\r
- } else {\r
- // happens for flows imported as services\r
- log.warn("flowInitializationFinished - Flow Stack is null");\r
- }\r
- }\r
-\r
- protected ExecutionFlow findInitializingFlowWithParameter(String key) {\r
- if ((flowStack.get() == null) || flowStack.get().empty())\r
- throw new SlcException("No initializing flow available.");\r
-\r
- // first look in the outer flow (that may override parameters)\r
- for (int i = 0; i < flowStack.get().size(); i++) {\r
- if (flowStack.get().elementAt(i).isSetAsParameter(key)) {\r
- return flowStack.get().elementAt(i);\r
- }\r
- }\r
- throw new SlcException("Key " + key + " is not set as parameter in "\r
- + flowStack.get().firstElement().toString() + " (stack size="\r
- + flowStack.get().size() + ")");\r
-\r
- }\r
-\r
- public Object getInitializingFlowParameter(String key) {\r
- return findInitializingFlowWithParameter(key).getParameter(key);\r
- }\r
-\r
- public Class<?> getInitializingFlowParameterClass(String key) {\r
- ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key)\r
- .getExecutionSpec().getAttributes().get(key);\r
- if (attr instanceof RefSpecAttribute)\r
- return ((RefSpecAttribute) attr).getTargetClass();\r
- else if (attr instanceof PrimitiveSpecAttribute) {\r
- String type = ((PrimitiveSpecAttribute) attr).getType();\r
- Class<?> clss = PrimitiveUtils.typeAsClass(type);\r
- if (clss == null)\r
- throw new SlcException("Cannot convert type " + type\r
- + " to class.");\r
- return clss;\r
- } else\r
- return null;\r
- }\r
-\r
- public Boolean isInFlowInitialization() {\r
- return (flowStack.get() != null) && !flowStack.get().empty();\r
- }\r
-}\r
+++ /dev/null
-/*
- * 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.argeo.slc.execution.ExecutionFlow;
-import org.argeo.slc.execution.ExecutionStack;
-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<String, Object> variables = Collections
- .synchronizedMap(new HashMap<String, Object>());
-
- private final String uuid;
-
- private ApplicationContext applicationContext;
- private ExecutionStack executionStack;
-
- 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);
-
- // if the variable was not found, look in the stack starting at the
- // upper flows
- if (value == null) {
- value = executionStack.findLocalVariable(key);
- }
- return value;
- }
-
- public String getUuid() {
- return uuid;
- }
-
- @Override
- public void beforeFlow(ExecutionFlow executionFlow) {
- // getUuid();
- executionStack.enterFlow(executionFlow);
- setVariable(ExecutionContext.VAR_FLOW_ID,
- executionStack.getCurrentStackLevelUuid());
- setVariable(ExecutionContext.VAR_FLOW_NAME, executionFlow.getName());
- }
-
- @Override
- public void afterFlow(ExecutionFlow executionFlow) {
- executionStack.leaveFlow(executionFlow);
- }
-
- @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;
- }
-
- public void setExecutionStack(ExecutionStack executionStack) {
- this.executionStack = executionStack;
- }
-
-}
+++ /dev/null
-/*
- * 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<String> {
- private ExecutionResources executionResources;
- private Resource resource;
- private Boolean overwrite = false;
-
- /** Return an existing file on the file system. */
- public String 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<? extends Object> 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
- * <code>false</code>.
- */
- public void setOverwrite(Boolean overwrite) {
- this.overwrite = overwrite;
- }
-
-}
+++ /dev/null
-/*
- * 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<Object> {
- 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;
- }
-
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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 : "");
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-
-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;
-
-/**
- * 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<ExecutionThread> executionThreads = Collections.synchronizedSet(new HashSet<ExecutionThread>());
-
- // private Boolean hadAnError = false;
- private Boolean killed = false;
-
- private final AccessControlContext accessControlContext;
-
- public ProcessThread(ThreadGroup processesThreadGroup, ExecutionModulesManager executionModulesManager,
- ExecutionProcess process) {
- super(processesThreadGroup, "SLC Process #" + process.getUuid());
- this.executionModulesManager = executionModulesManager;
- this.process = process;
- processThreadGroup = new ProcessThreadGroup(process);
- accessControlContext = AccessController.getContext();
- }
-
- 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 {
- Subject subject = Subject.getSubject(accessControlContext);
- try {
- Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
-
- @Override
- public Void run() throws Exception {
- process();
- return null;
- }
-
- });
- } catch (PrivilegedActionException privilegedActionException) {
- Throwable cause = privilegedActionException.getCause();
- if (cause instanceof InterruptedException)
- throw (InterruptedException) cause;
- else
- throw new SlcException("Cannot process", cause);
- }
- // 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<RealizedFlow> flowsToProcess = new ArrayList<RealizedFlow>();
- 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<ExecutionStep> newSteps = new ArrayList<ExecutionStep>();
- 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;
- }
- }
-
- }
-}
+++ /dev/null
-/*
- * 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;
-
-/** The thread group attached to a given {@link SlcExecution}. */
-public class ProcessThreadGroup extends ThreadGroup {
-// private final Authentication authentication;
- private final static Integer STEPS_BUFFER_CAPACITY = 5000;
-
- private BlockingQueue<ExecutionStep> steps = new ArrayBlockingQueue<ExecutionStep>(
- STEPS_BUFFER_CAPACITY);
-
- private Boolean hadAnError = false;
-
- public ProcessThreadGroup(ExecutionProcess executionProcess) {
- super("SLC Process #" + executionProcess.getUuid() + " thread group");
-// this.authentication = SecurityContextHolder.getContext()
-// .getAuthentication();
- }
-
-// public Authentication getAuthentication() {
-// return authentication;
-// }
-
- public void dispatchAddStep(ExecutionStep step) {
- // ExecutionProcess slcProcess = processThread.getProcess();
- // List<ExecutionStep> steps = new ArrayList<ExecutionStep>();
- // 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<ExecutionStep> steps) {
- // ExecutionProcess slcProcess = processThread.getProcess();
- // executionModulesManager.dispatchAddSteps(slcProcess, steps);
- // }
-
- public BlockingQueue<ExecutionStep> getSteps() {
- return steps;
- }
-
- public Boolean hadAnError() {
- return hadAnError;
- }
-}
+++ /dev/null
-/*
- * 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<RefValueChoice> 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<RefValueChoice> getChoices() {
- return choices;
- }
-
- public void setChoices(List<RefValueChoice> 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 : "");
- }
-
-}
+++ /dev/null
-/*
- * 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 + "]";
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<Resource>,
- InitializingBean {
- private Resource source;
-
- private List<String> filters = new ArrayList<String>();
- private Map<Pattern, String> patterns = new HashMap<Pattern, String>();
-
- private String charset = "UTF-8";
- private Charset cs;
- private CharsetDecoder decoder;
-
- // private CharsetEncoder encoder;
-
- public Resource 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<String> tokens = new ArrayList<String>(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<String> filters) {
- this.filters = filters;
- }
-
- public void setCharset(String charset) {
- this.charset = charset;
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <bean id="slcDefault.executionResources" parent="slcTemplate.fileResources"
- scope="execution" lazy-init="true">
- <aop:scoped-proxy proxy-target-class="false" />
- <property name="executionContext" ref="executionContext" />
- </bean>
-
- <bean id="slcDefault.writableResource" parent="slcTemplate.writableResource"
- abstract="true">
- <property name="executionResources" ref="slcDefault.executionResources" />
- </bean>
-
- <bean id="slcDefault.osFile" parent="slcTemplate.osFile" abstract="true">
- <property name="executionResources" ref="slcDefault.executionResources" />
- </bean>
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.Map;\r
-\r
-import org.argeo.slc.SlcException;\r
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
-\r
-/**\r
- * Composite <code>RunnableFactory</code>, redirecting the Runnable \r
- * creation to on of the configured <code>RunnableFactory</code> depending\r
- * on an entry of the data of the <code>RunnableDataNode</code>.\r
- */\r
-public class CompositeRunnableFactory implements RunnableFactory {\r
-\r
- /**\r
- * Key used to access factory ID in the data of the <code>RunnableDataNode</code>\r
- */\r
- private String factoryKey;\r
-\r
- /**\r
- * Maps a factory ID to an ExecutionFlowFactory\r
- */\r
- private Map<String, RunnableFactory> factories;\r
-\r
- public void createAndRegisterRunnable(RunnableDataNode node,\r
- BeanDefinitionRegistry beanDefinitionRegistry) {\r
- findFactory(node).createAndRegisterRunnable(node, beanDefinitionRegistry);\r
- } \r
- \r
- /**\r
- * Finds the <code>RunnableFactory</code> to use for a <code>RunnableDataNode</code>\r
- * @param node\r
- * @return the <code>RunnableFactory</code> to use for the <code>RunnableDataNode</code>\r
- */\r
- private RunnableFactory findFactory(RunnableDataNode node) {\r
- // get the factory ID from the data of the RunnableDescriptor\r
- Map<String, Object> data = node.getData();\r
- if (!data.containsKey(factoryKey)) {\r
- throw new SlcException("No data value for key '" + factoryKey + "'");\r
- }\r
- String factoryId = data.get(factoryKey).toString();\r
- \r
- // see if we have a factory for the factory ID\r
- if ((factories != null) && factories.containsKey(factoryId)) {\r
- return factories.get(factoryId);\r
- }\r
- // if not, look for a bean of name equals to the factory ID\r
- else {\r
- throw new SlcException("Not implemented");\r
- } \r
- }\r
- \r
- public void setFactoryKey(String factoryKey) {\r
- this.factoryKey = factoryKey;\r
- }\r
-\r
- public void setFactories(Map<String, RunnableFactory> factories) {\r
- this.factories = factories;\r
- }\r
-\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-/**\r
- * Default implementation of <code>RunnableDataNode</code>\r
- *\r
- */\r
-public class DefaultRunnableDataNode implements RunnableDataNode {\r
-\r
- private List<RunnableDataNode> children = new ArrayList<RunnableDataNode>();\r
- \r
- private RunnableDataNode parent;\r
- \r
- /**\r
- * Data of the RunnableDataNode. Does not contain\r
- * parent data.\r
- */\r
- private Map<String, Object> properData = new HashMap<String, Object>();\r
- \r
- private String path;\r
- \r
- private String beanName;\r
-\r
- public boolean isLeaf() {\r
- return children.size() == 0;\r
- }\r
- \r
- public List<RunnableDataNode> getChildren() {\r
- return children;\r
- }\r
-\r
- public void addChild(RunnableDataNode child) {\r
- child.setParent(this);\r
- children.add(child);\r
- }\r
- \r
- public Map<String, Object> getData() {\r
- Map<String, Object> data = new HashMap<String, Object>();\r
- if(parent != null) {\r
- Map<String, Object> parentData = parent.getData();\r
- if(parentData != null) {\r
- data.putAll(parentData);\r
- }\r
- }\r
- // entries defined in parentData can be overridden\r
- // in properData\r
- if(properData != null) {\r
- data.putAll(properData);\r
- }\r
- return data;\r
- }\r
-\r
- public Map<String, Object> getProperData() {\r
- return properData;\r
- }\r
-\r
- public void setProperData(Map<String, Object> properData) {\r
- this.properData = properData;\r
- }\r
-\r
- public String getPath() {\r
- return path;\r
- }\r
-\r
- public void setPath(String path) {\r
- this.path = path;\r
- }\r
-\r
- public String getBeanName() {\r
- return beanName;\r
- }\r
-\r
- public void setBeanName(String beanName) {\r
- this.beanName = beanName;\r
- }\r
-\r
- public void setParent(RunnableDataNode parent) {\r
- this.parent = parent;\r
- }\r
-\r
- public RunnableDataNode getParent() {\r
- return parent;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.HashMap;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.springframework.aop.scope.ScopedProxyUtils;\r
-import org.springframework.beans.BeansException;\r
-import org.springframework.beans.MutablePropertyValues;\r
-import org.springframework.beans.factory.config.BeanDefinitionHolder;\r
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;\r
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\r
-import org.springframework.beans.factory.config.RuntimeBeanReference;\r
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
-import org.springframework.beans.factory.support.GenericBeanDefinition;\r
-import org.springframework.core.Ordered;\r
-\r
-/**\r
- * Generates <code>ExecutionFlows</code> and <code>Runnables</code> as\r
- * beans in the Spring Application Context.\r
- * Called by the Application Context as a <code>BeanFactoryPostProcessor</code>.\r
- * Two kinds of beans are generated:\r
- * <code>RunnableCallFlow</code>, calling a list of <code>Runnables</code> from the\r
- * Application Context after configuring the <code>ExecutionContext</code>, \r
- * and outputs of a <code>RunnableFactory</code>.\r
- */\r
-public class ExecutionFlowGenerator implements BeanFactoryPostProcessor,\r
- Ordered {\r
- \r
- private final Log log = LogFactory.getLog(getClass());\r
-\r
- /**\r
- * Source providing a list of <code>RunnableCallFlowDescriptor</code> \r
- * used to create <code>RunnableCallFlow</code> and a list of \r
- * <code>RunnableDataNode</code> used to create any kind of flow via a factory\r
- */\r
- protected ExecutionFlowGeneratorSource source;\r
- \r
- /**\r
- * Factory used to create Runnables in the Application context from\r
- * the <code>RunnableDataNode</code> provided from the source.\r
- */\r
- protected RunnableFactory runnableFactory;\r
- \r
- /**\r
- * Bean name of the <code>ExecutionContext</code>.\r
- * Used to provide the created <code>RunnableCallFlow</code> beans \r
- * with a <code>RuntimeBeanReference</code> to\r
- * the <code>ExecutionContext</code>\r
- */\r
- private String executionContextBeanName = "executionContext";\r
- \r
- /**\r
- * Bean name of the context values Map.\r
- * A bean of class HashMap is created with this name, and a \r
- * <code>RuntimeBeanReference</code> is provided to the created\r
- * <code>RunnableCallFlow</code> beans.\r
- */\r
- private String contextValuesBeanName = "executionFlowGenerator.contextValues";\r
- \r
- /**\r
- * Prefix added to the bean names defined in each \r
- * <code>RunnableCallFlowDescriptor</code>\r
- */\r
- private String flowBeanNamesPrefix = "";\r
- \r
- private int order = Ordered.HIGHEST_PRECEDENCE;\r
- \r
- public void postProcessBeanFactory(\r
- ConfigurableListableBeanFactory beanFactory) throws BeansException {\r
-\r
- // assert that the beanFactory is a BeanDefinitionRegistry\r
- if (!(beanFactory instanceof BeanDefinitionRegistry)) {\r
- throw new SlcException("Can only work on "\r
- + BeanDefinitionRegistry.class);\r
- } \r
- \r
- // add bean for the Context Values Map\r
- createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory);\r
- \r
- // add beans for each RunnableDataNode\r
- for(RunnableDataNode node : source.getRunnableDataNodes()) {\r
- runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory);\r
- }\r
- \r
- // add beans for each RunnableCallFlowDescriptor of the source to the application context\r
- for (RunnableCallFlowDescriptor descriptor : source\r
- .getRunnableCallFlowDescriptors()) {\r
- createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory);\r
- }\r
- }\r
-\r
- /**\r
- * Creates a <code>RunnableCallFlow</code> bean\r
- * for a <code>RunnableCallFlowDescriptor</code> and registers \r
- * it in the <code>BeanDefinitionRegistry</code>\r
- * @param flowDescriptor\r
- * @param registry\r
- */\r
- private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) {\r
- // create the flow bean\r
- GenericBeanDefinition flowBean = new GenericBeanDefinition();\r
- flowBean.setBeanClass(RunnableCallFlow.class);\r
- \r
- String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName();\r
- \r
- MutablePropertyValues mpv = new MutablePropertyValues(); \r
- mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls());\r
- mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName));\r
- \r
- mpv.addPropertyValue("name", beanName);\r
- mpv.addPropertyValue("path", flowDescriptor.getPath());\r
-\r
- mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName));\r
- \r
- flowBean.setPropertyValues(mpv);\r
- \r
- // register it\r
- if(log.isDebugEnabled()) {\r
- log.debug("Registering bean definition for RunnableCallFlow " + beanName);\r
- }\r
- registry.registerBeanDefinition(beanName, flowBean);\r
- }\r
- \r
- /**\r
- * Creates the Context Values bean and register it in the\r
- * <code>BeanDefinitionRegistry</code>\r
- * @param registry\r
- */\r
- private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) {\r
- GenericBeanDefinition contextValuesBean = new GenericBeanDefinition();\r
- contextValuesBean.setBeanClass(HashMap.class);\r
- \r
- BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true); \r
- registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition()); \r
- }\r
- \r
- public int getOrder() {\r
- return order;\r
- }\r
-\r
- public void setOrder(int order) {\r
- this.order = order;\r
- }\r
-\r
- public void setSource(ExecutionFlowGeneratorSource source) {\r
- this.source = source;\r
- }\r
-\r
- public void setRunnableFactory(RunnableFactory runnableFactory) {\r
- this.runnableFactory = runnableFactory;\r
- }\r
-\r
- public void setExecutionContextBeanName(String executionContextBeanName) {\r
- this.executionContextBeanName = executionContextBeanName;\r
- }\r
-\r
- public void setContextValuesBeanName(String contextValuesBeanName) {\r
- this.contextValuesBeanName = contextValuesBeanName;\r
- }\r
-\r
- public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) {\r
- this.flowBeanNamesPrefix = flowBeanNamesPrefix;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.List;\r
-\r
-/**\r
- * Provides 2 types of information required by an <code>ExecutionFlowGenerator</code>: \r
- * a list of <code>RunnableCallFlowDescriptor</code> used to create <code>RunnableCallFlow</code>\r
- * and a list of <code>RunnableDataNode</code> used to create any kind of flow via a factory.\r
- */\r
-public interface ExecutionFlowGeneratorSource {\r
- \r
- /**\r
- * @return a list of <code>RunnableCallFlowDescriptor</code> used \r
- * by a <code>ExecutionFlowGenerator</code> to create <code>RunnableCallFlow</code>\r
- */\r
- public List<RunnableCallFlowDescriptor> getRunnableCallFlowDescriptors();\r
- \r
- /**\r
- * @return a list of <code>RunnableDataNode</code> used \r
- * by a <code>ExecutionFlowGenerator</code> to create any kind of flow via a factory\r
- */\r
- public List<RunnableDataNode> getRunnableDataNodes();\r
- \r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.Map;\r
-\r
-/**\r
- * Storage class for information required to call a flow \r
- * of the Spring execution context: \r
- * bean name of the flow,\r
- * variables to add to the Execution Context before the call \r
- * and variables (context values) to add to a Map \r
- * potentially referenced by the called flow \r
- */\r
-public class RunnableCall {\r
- \r
- /**\r
- * Bean name of the flow to call\r
- */\r
- private String beanName;\r
- \r
- /**\r
- * Variables to add to the execution context before the call\r
- */\r
- private Map<String, Object> executionVariables;\r
- \r
- /**\r
- * Variables to add to the Map potentially referenced by\r
- * the called flow\r
- */\r
- private Map<String, Object> contextValues;\r
-\r
- public String getBeanName() {\r
- return beanName;\r
- }\r
-\r
- public void setBeanName(String beanName) {\r
- this.beanName = beanName;\r
- }\r
-\r
- public Map<String, Object> getExecutionVariables() {\r
- return executionVariables;\r
- }\r
-\r
- public void setExecutionVariables(Map<String, Object> executionVariables) {\r
- this.executionVariables = executionVariables;\r
- }\r
-\r
- public Map<String, Object> getContextValues() {\r
- return contextValues;\r
- }\r
-\r
- public void setContextValues(Map<String, Object> contextValues) {\r
- this.contextValues = contextValues;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.core.execution.DefaultExecutionSpec;\r
-import org.argeo.slc.execution.ExecutionContext;\r
-import org.argeo.slc.execution.ExecutionFlow;\r
-import org.argeo.slc.execution.ExecutionSpec;\r
-import org.springframework.context.ApplicationContext;\r
-import org.springframework.context.ApplicationContextAware;\r
-\r
-/**\r
- * Execution Flow calling a list of <code>Runnable</code> (identified by their\r
- * bean name in the Spring Application Context) after configuring the Execution\r
- * context and a Map potentially shared by the called <code>Runnable</code>\r
- * \r
- */\r
-public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware {\r
-\r
- private final static Log log = LogFactory.getLog(RunnableCallFlow.class);\r
-\r
- /**\r
- * Key in the execution context for the index of the call (e.g. 0 for the\r
- * first runnable called, ...)\r
- */\r
- public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex";\r
-\r
- /**\r
- * Name of the flow. Also bean name\r
- */\r
- private String name;\r
-\r
- /**\r
- * Path of the flow\r
- */\r
- private String path;\r
-\r
- /**\r
- * Whether an exception in a <code>Runnable</code> shall stop the execution\r
- * of the flow\r
- */\r
- private Boolean failOnError = true;\r
-\r
- /**\r
- * List of <code>Runnable</code> to call, with bean name, execution\r
- * variables and context values\r
- */\r
- private List<RunnableCall> runnableCalls;\r
-\r
- /**\r
- * Map potentially referenced by called flows. Updated with the context\r
- * values of a Runnable before calling it.\r
- */\r
- private Map<String, Object> sharedContextValuesMap;\r
-\r
- /**\r
- * ExecutionSpec of the flow. Does not contain any attribute.\r
- */\r
- private ExecutionSpec executionSpec = new DefaultExecutionSpec();\r
-\r
- /**\r
- * Reference to the ExecutionContext\r
- */\r
- private ExecutionContext executionContext;\r
-\r
- /**\r
- * Reference to the Spring <code>ApplicationContext</code>. Set via\r
- * <code>setApplicationContext</code>, the class implementing\r
- * <code>ApplicationContextAware</code>\r
- */\r
- private ApplicationContext applicationContext;\r
-\r
- /**\r
- * Runs a <code>Runnable</code> after configuring the Execution Context and\r
- * <code>sharedContextValuesMap</code>\r
- * \r
- * @param runnable\r
- * the <code>Runnable</code> to call\r
- * @param executionVariables\r
- * the variables to add to the <code>ExecutionContext</code>\r
- * @param contextValues\r
- * the variables to add to <code>sharedContextValuesMap</code>\r
- * @param callIndex\r
- * index of the call (0 for the first called\r
- * <code>Runnable</code>) set as variable of the\r
- * <code>ExecutionContext</code>\r
- */\r
- private void run(Runnable runnable, Map<String, Object> executionVariables,\r
- Map<String, Object> contextValues, int callIndex) {\r
- // add all variables to the Execution Context\r
- for (Map.Entry<String, Object> entry : executionVariables.entrySet()) {\r
- executionContext.setVariable(entry.getKey(), entry.getValue());\r
- }\r
-\r
- // add call Index Variable\r
- executionContext.setVariable(VAR_CALL_INDEX, callIndex);\r
-\r
- // clear sharedContextValues and add all values of contextValues\r
- if (sharedContextValuesMap != null) {\r
- sharedContextValuesMap.clear();\r
- sharedContextValuesMap.putAll(contextValues);\r
- }\r
-\r
- // then run the runnable\r
- doExecuteRunnable(runnable);\r
- }\r
-\r
- public void doExecuteRunnable(Runnable runnable) {\r
- runnable.run();\r
- }\r
-\r
- /**\r
- * Executes the flow. For each <code>RunnableCall</code>, the corresponding\r
- * flow is retrieved from the Spring Application Context, the\r
- * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are\r
- * configured and the <code>Runnable</code> is called.\r
- */\r
- public void run() {\r
- if (applicationContext == null) {\r
- throw new SlcException("No ApplicationContext defined");\r
- }\r
-\r
- try {\r
- for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
- RunnableCall runnableCall = runnableCalls.get(callIndex);\r
- Object bean = applicationContext.getBean(\r
- runnableCall.getBeanName(), Runnable.class);\r
- if (log.isDebugEnabled())\r
- log.debug("Running flow '" + runnableCall.getBeanName()\r
- + "'");\r
- run((Runnable) bean, runnableCall.getExecutionVariables(),\r
- runnableCall.getContextValues(), callIndex);\r
- }\r
- } catch (RuntimeException e) {\r
- if (failOnError)\r
- throw e;\r
- else {\r
- log.error("Execution flow failed,"\r
- + " but process did not fail"\r
- + " because failOnError property"\r
- + " is set to false: " + e);\r
- if (log.isTraceEnabled())\r
- e.printStackTrace();\r
- }\r
- }\r
- }\r
-\r
- public Iterator<Runnable> runnables() {\r
- List<Runnable> runnables = new ArrayList<Runnable>();\r
- for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
- RunnableCall runnableCall = runnableCalls.get(callIndex);\r
- Object bean = applicationContext.getBean(\r
- runnableCall.getBeanName(), Runnable.class);\r
- runnables.add((Runnable) bean);\r
- }\r
- return runnables.iterator();\r
- }\r
-\r
- public Runnable getRunnable() {\r
- if (runnableCalls.size() == 1)\r
- return runnables().next();\r
- else\r
- throw new SlcException("There are " + runnableCalls.size()\r
- + " runnables in flow " + getName());\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return new StringBuffer("RunnableCallFlow ").append(name).toString();\r
- }\r
-\r
- public ExecutionSpec getExecutionSpec() {\r
- return executionSpec;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public Object getParameter(String key) {\r
- throw new SlcException("RunnableCallFlow have no parameters");\r
- }\r
-\r
- public String getPath() {\r
- return path;\r
- }\r
-\r
- public Boolean isSetAsParameter(String key) {\r
- // The ExecutionSpec having no attribute,\r
- // always return false\r
- return false;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public void setPath(String path) {\r
- this.path = path;\r
- }\r
-\r
- public void setExecutionContext(ExecutionContext executionContext) {\r
- this.executionContext = executionContext;\r
- }\r
-\r
- public void setRunnableCalls(List<RunnableCall> runnableCalls) {\r
- this.runnableCalls = runnableCalls;\r
- }\r
-\r
- public void setApplicationContext(ApplicationContext applicationContext) {\r
- this.applicationContext = applicationContext;\r
- }\r
-\r
- public void setSharedContextValuesMap(Map<String, Object> contextValues) {\r
- this.sharedContextValuesMap = contextValues;\r
- }\r
-\r
- public void setFailOnError(Boolean failOnError) {\r
- this.failOnError = failOnError;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-/**\r
- * Storage Class for information required to\r
- * instantiate a <code>RunnableCallFlow</code>:\r
- * bean name of the flow, \r
- * path of the flow \r
- * and list of <code>RunnableCall</code>. \r
- *\r
- */\r
-public class RunnableCallFlowDescriptor {\r
- \r
- /**\r
- * Bean name of the flow to instantiate\r
- */\r
- private String beanName;\r
- \r
- /**\r
- * Path of the flow to instantiate\r
- */\r
- private String path;\r
- \r
- /**\r
- * List of <code>RunnableCall</code> \r
- */\r
- private List<RunnableCall> runnableCalls = new ArrayList<RunnableCall>();\r
-\r
- public String getBeanName() {\r
- return beanName;\r
- }\r
-\r
- public void setBeanName(String beanName) {\r
- this.beanName = beanName;\r
- }\r
-\r
- public String getPath() {\r
- return path;\r
- }\r
-\r
- public void setPath(String path) {\r
- this.path = path;\r
- }\r
-\r
- public List<RunnableCall> getRunnableCalls() {\r
- return runnableCalls;\r
- }\r
-\r
- public void setRunnableCalls(List<RunnableCall> runnableCalls) {\r
- this.runnableCalls = runnableCalls;\r
- }\r
- \r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-/**\r
- * Stores information relative to a Runnable.\r
- * Allows to structure the information as a tree, each node\r
- * storing data as a Map.\r
- */\r
-public interface RunnableDataNode {\r
-\r
- /**\r
- * @return a Map containing the data associated with this node.\r
- * Data associated with parent nodes are expected\r
- * to be contained in the returned Map\r
- */\r
- public Map<String, Object> getData(); \r
-\r
- /**\r
- * @return the name of the bean to create.\r
- * Can be null if no bean shall be created for the \r
- * <code>RunnableDataNode</code> (e.g. is is a sub-node)\r
- */\r
- public String getBeanName();\r
- \r
- /**\r
- * @return the path of the flow bean to create.\r
- * Can be null if the bean to created is not an\r
- * <code>ExecutionFlow</code> or if no bean shall be created for the \r
- * <code>RunnableDataNode</code> (e.g. is is a sub-node)\r
- */\r
- public String getPath();\r
- \r
- /**\r
- * @return whether the <code>RunnableDataNode</code> has\r
- * children or not.\r
- * Expected to be equivalent to <code>getChildren().empty()</code>\r
- */\r
- public boolean isLeaf();\r
-\r
- /**\r
- * @return the list of <code>RunnableDataNode</code> children.\r
- * Can be empty. Shall not be null.\r
- */\r
- public List<RunnableDataNode> getChildren();\r
- \r
- /**\r
- * @return the <code>RunnableDataNode</code> parent.\r
- * Can be null if no parent is defined (top node).\r
- */\r
- public RunnableDataNode getParent();\r
- \r
- /**\r
- * Sets the <code>RunnableDataNode</code> parent\r
- * @param parent\r
- */\r
- public void setParent(RunnableDataNode parent); \r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.generator;\r
-\r
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
-\r
-/**\r
- * Interprets a <code>RunnableDataNode</code> by creating corresponding\r
- * beans and registering them in a <code>BeanDefinitionRegistry</code>\r
- *\r
- */\r
-public interface RunnableFactory {\r
-\r
- public void createAndRegisterRunnable(RunnableDataNode node,\r
- BeanDefinitionRegistry beanDefinitionRegistry);\r
-}\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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. -->
-<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
-
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <description>Bare minimal runtime configuration. In general you will
- want to use simple.xml instead.
- </description>
-
- <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
- <property name="scopes">
- <map>
- <entry key="execution">
- <bean class="org.argeo.slc.core.execution.ExecutionScope" />
- </entry>
- </map>
- </property>
- </bean>
-
-
- <bean id="executionStack" class="org.argeo.slc.core.execution.DefaultExecutionStack"
- scope="execution">
- <aop:scoped-proxy proxy-target-class="false" />
- </bean>
-
- <bean id="instantiationManager" class="org.argeo.slc.core.execution.InstantiationManager" />
-
- <bean class="org.argeo.slc.core.execution.ExecutionParameterPostProcessor">
- <property name="executionContext" ref="executionContext" />
- <property name="instantiationManager" ref="instantiationManager" />
- </bean>
-
- <!-- <bean class="org.argeo.slc.core.execution.ExecutionAspect"> -->
- <!-- <property name="executionStack" ref="executionStack" /> -->
- <!-- <property name="executionContext" ref="executionContext" /> -->
- <!-- </bean> -->
-
- <aop:aspectj-autoproxy />
-
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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. -->
-<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
-
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <description>Default Capabilities</description>
-
- <import resource="runtime.xml" />
-
- <bean id="executionContext" class="org.argeo.slc.core.execution.MapExecutionContext"
- scope="execution">
- <aop:scoped-proxy proxy-target-class="false" />
- <property name="executionStack" ref="executionStack" />
- </bean>
-
- <bean id="executionFlowDescriptorConverter"
- class="org.argeo.slc.core.execution.DefaultExecutionFlowDescriptorConverter"></bean>
-
- <bean
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
- <property name="ignoreUnresolvablePlaceholders" value="true" />
- </bean>
-
- <bean id="parameterRef" class="org.argeo.slc.core.execution.ParameterRef"
- abstract="true">
- <property name="instantiationManager" ref="instantiationManager" />
- </bean>
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <bean id="specAttr.primitive" class="org.argeo.slc.core.execution.PrimitiveSpecAttribute"
- abstract="true" />
- <bean id="specAttr.resource" class="org.argeo.slc.core.execution.ResourceSpecAttribute"
- abstract="true" />
- <bean id="specAttr.ref" class="org.argeo.slc.core.execution.RefSpecAttribute"
- abstract="true" />
-
- <bean id="slcTemplate.simpleFlow" class="org.argeo.slc.core.execution.DefaultExecutionFlow"
- abstract="true" />
- <bean id="slcTemplate.simpleSpec" class="org.argeo.slc.core.execution.DefaultExecutionSpec"
- abstract="true" />
-
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
-
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <description>
- 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.
- </description>
-
- <import resource="simple.xml" />
-
- <import resource="specs.xml" />
- <import resource="templates.xml" />
- <import resource="defaults.xml" />
- <import resource="utils.xml" />
- <import resource="tasks/core.xml" />
-
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<Resource> classpath = new ArrayList<Resource>();
- private List<Resource> pBootClasspath = new ArrayList<Resource>();
- private Resource jvm = null;
- private String mainClass;
- private String mainJar;
- private List<String> jvmArgs = new ArrayList<String>();
- private List<String> args = new ArrayList<String>();
-
- private String systemPropertiesFileProperty = null;
- private String systemPropertiesFileDir = null;
- private String systemPropertiesFileName = null;
-
- public void afterPropertiesSet() throws Exception {
- List<Object> command = new ArrayList<Object>();
- 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<Object, Object> 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<Resource> getClasspath() {
- return classpath;
- }
-
- public void setClasspath(List<Resource> classpath) {
- this.classpath = classpath;
- }
-
- public List<Resource> getPBootClasspath() {
- return pBootClasspath;
- }
-
- public void setPBootClasspath(List<Resource> 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<String> getJvmArgs() {
- return jvmArgs;
- }
-
- public void setJvmArgs(List<String> jvmArgs) {
- this.jvmArgs = jvmArgs;
- }
-
- public List<String> getArgs() {
- return args;
- }
-
- public void setArgs(List<String> 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<List<Object>> {
- private List<List<Object>> lists = new ArrayList<List<Object>>();
-
- public void setLists(List<List<Object>> lists) {
- this.lists = lists;
- }
-
- public List<Object> getObject() throws Exception {
- List<Object> merged = new ArrayList<Object>();
- for (List<Object> lst : lists) {
- merged.addAll(lst);
- }
- return merged;
- }
-
- public Class<?> getObjectType() {
- return List.class;
- }
-
- public boolean isSingleton() {
- return false;
- }
-
-}
+++ /dev/null
-/*
- * 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<Object> args = new ArrayList<Object>();
-
- 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<Object> args) {
- this.args = args;
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.tasks;\r
-\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.core.test.context.SimpleContextAware;\r
-import org.argeo.slc.test.context.ContextAware;\r
-\r
-/**\r
- * Overrides Values and Expected values of a target \r
- * <code>SimpleContextAware</code> with the corresponding\r
- * values and expected values of a source <code>ContextAware</code>\r
- *\r
- */\r
-public class OverrideContextAware implements Runnable {\r
-\r
- private ContextAware source;\r
-\r
- private SimpleContextAware target;\r
- \r
- /**\r
- * Whether an exception shall be thrown if a value\r
- * or expected value of the source is not defined\r
- * in the target\r
- */\r
- private Boolean failIfUndefinedInSource = true;\r
- \r
- public void run() {\r
- // override values\r
- if(source.getValues() != null)\r
- for(String key : source.getValues().keySet()) {\r
- if(failIfUndefinedInSource && !target.getValues().containsKey(key)) {\r
- throw new SlcException("No entry in target values for key '" + key + "'");\r
- }\r
- target.getValues().put(key, source.getValues().get(key));\r
- }\r
- \r
- // override expected values\r
- if(source.getExpectedValues() != null)\r
- for(String key : source.getExpectedValues().keySet()) {\r
- if(failIfUndefinedInSource && !target.getExpectedValues().containsKey(key)) {\r
- throw new SlcException("No entry in target expected values for key '" + key + "'");\r
- }\r
- target.getExpectedValues().put(key, source.getExpectedValues().get(key));\r
- } \r
- } \r
- \r
- public void setSource(ContextAware source) {\r
- this.source = source;\r
- }\r
-\r
- public void setTarget(SimpleContextAware target) {\r
- this.target = target;\r
- }\r
-\r
- public void setFailIfUndefinedInSource(Boolean failIfUndefinedInSource) {\r
- this.failIfUndefinedInSource = failIfUndefinedInSource;\r
- } \r
-}\r
+++ /dev/null
-/*
- * 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;
-
-/** 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<Object> 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<SystemCallOutputListener> outputListeners = Collections
- .synchronizedList(new ArrayList<SystemCallOutputListener>());
-
- private Map<String, List<Object>> osCommands = new HashMap<String, List<Object>>();
- private Map<String, String> osCmds = new HashMap<String, String>();
- private Map<String, String> environmentVariables = new HashMap<String, String>();
-
- 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";
- @SuppressWarnings("unused")
- private boolean firstLine = true;
- @SuppressWarnings("unused")
- 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<Object> 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<Object>();
- 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<String, String> environmentVariablesToUse = null;
- environmentVariablesToUse = new HashMap<String, String>();
- 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<Object> 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<Object>();
- command.add(arg);
- return this;
- }
-
- /** Append the argument (for chaining) */
- public SystemCall arg(String arg, String value) {
- if (command == null)
- command = new ArrayList<Object>();
- 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<Object> 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<String, List<Object>> osCommands) {
- this.osCommands = osCommands;
- }
-
- public void setOsCmds(Map<String, String> osCmds) {
- this.osCmds = osCmds;
- }
-
- public void setEnvironmentVariables(Map<String, String> environmentVariables) {
- this.environmentVariables = environmentVariables;
- }
-
- public Map<String, String> 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<SystemCallOutputListener> 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() {
- }
-
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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<Attachment, Resource> attachments = new HashMap<Attachment, Resource>();
- private List<AttachmentsEnabled> attachTo = new ArrayList<AttachmentsEnabled>();
- 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<Attachment, Resource> attachments) {
- this.attachments = attachments;
- }
-
- public void setAttachTo(List<AttachmentsEnabled> 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;
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <bean id="task.echo" class="org.argeo.slc.core.execution.tasks.Echo"
- abstract="true" />
- <bean id="task.systemCall" class="org.argeo.slc.core.execution.tasks.SystemCall"
- abstract="true" />
- <bean id="task.closeTestResult" class="org.argeo.slc.core.execution.tasks.CloseTestResult"
- abstract="true" />
- <bean id="task.slcManager" class="org.argeo.slc.core.execution.tasks.SlcManager"
- abstract="true" />
- <bean id="task.overrideContextAware" class="org.argeo.slc.core.execution.tasks.OverrideContextAware"
- abstract="true" />
- <bean id="task.uploadAttachments" class="org.argeo.slc.core.execution.tasks.UploadAttachments"
- abstract="true" />
-
- <bean id="taskArg.attachment" class="org.argeo.slc.core.attachment.SimpleAttachment"
- abstract="true" />
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <bean id="slcTemplate.fileResources" class="org.argeo.slc.core.execution.FileExecutionResources"
- abstract="true" />
-
- <bean id="slcTemplate.resourcesFactoryBean" parent="slcTemplate.writableResource"
- abstract="true" />
-
- <bean id="slcTemplate.writableResource"
- class="org.argeo.slc.core.execution.ExecutionResourcesFactoryBean"
- abstract="true" />
-
- <bean id="slcTemplate.osFile" class="org.argeo.slc.core.execution.OsFileFactoryBean"
- abstract="true" />
-
-</beans>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
-
- <bean id="mergedLists" class="org.argeo.slc.core.execution.tasks.MergedLists"
- abstract="true">
- </bean>
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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.BeanMetadataElement;
-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);
-
- 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<BeanMetadataElement> executables = new ManagedList<BeanMetadataElement>(
- 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;
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.execution.xml;\r
-\r
-import org.springframework.aop.scope.ScopedProxyUtils;\r
-import org.springframework.beans.factory.config.BeanDefinitionHolder;\r
-import org.springframework.beans.factory.parsing.BeanComponentDefinition;\r
-import org.springframework.beans.factory.xml.BeanDefinitionDecorator;\r
-import org.springframework.beans.factory.xml.ParserContext;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.Node;\r
-\r
-/**\r
- * Inspired by org.springframework.aop.config.ScopedProxyBeanDefinitionDecorator\r
- */\r
-public class ExecutionScopeDecorator implements BeanDefinitionDecorator { \r
- private static final String PROXY_TARGET_CLASS = "proxy-target-class"; \r
- \r
- public BeanDefinitionHolder decorate(Node node,\r
- BeanDefinitionHolder definition, ParserContext parserContext) {\r
- \r
- definition.getBeanDefinition().setScope("execution");\r
- \r
- // Default: CGLib not used\r
- boolean proxyTargetClass = false;\r
- if (node instanceof Element) {\r
- Element ele = (Element) node;\r
- if (ele.hasAttribute(PROXY_TARGET_CLASS)) {\r
- proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)).booleanValue();\r
- }\r
- }\r
- \r
- // Register the original bean definition as it will be referenced by the scoped proxy and is relevant for tooling (validation, navigation).\r
- String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName());\r
- parserContext.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName));\r
- \r
- return ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass); \r
- }\r
-}\r
+++ /dev/null
-/*
- * 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 <flow:flow> 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;
-
- @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 <flow:flow name=\"/my/path/flowName\">.");
- 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<Element> argsElems = new ArrayList<Element>();
- List<Element> execElems = new ArrayList<Element>();
- List<Element> specElems = new ArrayList<Element>();
- 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<String, Object> args = new ManagedMap<String, Object>(
- 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<Object> executables = new ManagedList<Object>(
- 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<? extends ExecutionFlow> getBeanClass(Element element) {
- String clss = element.getAttribute("class");
- if (StringUtils.hasText(clss))
- // TODO: check that it actually works
- try {
- return (Class<? extends ExecutionFlow>) getClass()
- .getClassLoader().loadClass(clss);
- } catch (ClassNotFoundException e) {
- try {
- return (Class<? extends ExecutionFlow>) 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;
- }
-
-}
+++ /dev/null
-/*
- * 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());
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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<ParameterRef> getBeanClass(Element element) {
- return ParameterRef.class;
- }
-}
+++ /dev/null
-/*
- * 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 <flow:spec> tag */
-public class SpecBeanDefinitionParser extends
- AbstractSingleBeanDefinitionParser {
- private Log log = LogFactory.getLog(SpecBeanDefinitionParser.class);
-
- @Override
- protected void doParse(Element element, ParserContext parserContext,
- BeanDefinitionBuilder builder) {
- builder.getBeanDefinition().setDescription(
- DomUtils.getChildElementValueByTagName(element, "description"));
-
- ManagedMap<String, BeanDefinition> attributes = new ManagedMap<String, BeanDefinition>();
-
- // Primitives
- for (Element child : (List<Element>) 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<Element>) 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<Element> choices = DomUtils.getChildElementsByTagName(
- choicesElem, "choice");
- ManagedList<BeanDefinition> choiceBeans = new ManagedList<BeanDefinition>(
- 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);
-
- }
-
- protected void putInAttributes(
- ManagedMap<String, BeanDefinition> 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<DefaultExecutionSpec> getBeanClass(Element element) {
- return DefaultExecutionSpec.class;
- }
-
- protected boolean shouldGenerateIdAsFallback() {
- return false;
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:beans="http://www.springframework.org/schema/beans"
- targetNamespace="http://www.argeo.org/schema/slc-flow"
- elementFormDefault="qualified" attributeFormDefault="unqualified">
-
- <xsd:import namespace="http://www.springframework.org/schema/beans"
- schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" />
-
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- SLC Flow Schema, version 0.12
- Authors: Mathieu Baudier
-
- This simplifies the definition of SLC flows and their integration with
- regular Spring beans.
- ]]></xsd:documentation>
- </xsd:annotation>
-
- <xsd:element name="flow">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Adds an SLC execution flow, using the default implementation.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="beans:identifiedType">
- <xsd:sequence>
- <xsd:element ref="beans:description" minOccurs="0" />
- <xsd:sequence>
- <xsd:element name="arg" minOccurs="0" maxOccurs="unbounded"
- type="flow:argType">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Parameter for an execution flow which will override at instantiation the
- value of the parameter already defined as default value or in a parent bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:sequence>
- <xsd:sequence>
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="flow:flow" />
- </xsd:choice>
- <!--
- <xsd:any namespace="##other" processContents="strict"
- minOccurs="0" maxOccurs="unbounded" />
- -->
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Name of the flow (alternative to ID).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="class" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Another implementation of execution flow.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="path" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The hierarchical path under which to register this flow.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="spec" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference to the related specification bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="parent" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The parent bean definition (in Spring sense).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="abstract" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether this flow is abstract (in Spring sense).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="spec">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- SLC flow specifications, defining the parameters and variables
- which can be used in related flows, along with their default values and
- various constraints.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="beans:identifiedType">
- <xsd:sequence>
- <xsd:element ref="beans:description" minOccurs="0" />
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="primitive" type="flow:primitiveSpecAttributeType"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A primitive specification attribute, that is, a plain standard value
- and not a reference to an object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- <xsd:element name="ref" type="flow:refSpecAttributeType"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference specification attribute, that is, a reference to another object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:choice>
- </xsd:sequence>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:complexType name="specAttributeType">
- <xsd:choice>
- <xsd:element name="value" minOccurs="0" maxOccurs="1">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute as an inner bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:choice minOccurs="1" maxOccurs="1">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="beans:list" />
- <xsd:element ref="beans:set" />
- <xsd:element ref="beans:map" />
- <xsd:element ref="beans:props" />
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the attribute, under which in can then be referenced.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="value" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="ref" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute as a reference to another bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isParameter" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is a parameter, that is, it has to be set at
- instantiation but can be modified afterwards for objects of scope execution.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isFrozen" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is frozen, that is, it cannot be modified at runtime.
- A frozen attribute has to be a parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isHidden" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is hidden, that is, it should not be displayed in UIs.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:complexType name="primitiveSpecAttributeType">
- <xsd:complexContent>
- <xsd:extension base="flow:specAttributeType">
- <xsd:attribute name="type" default="string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The type of the primitive specification attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="string" />
- <xsd:enumeration value="integer" />
- <xsd:enumeration value="long" />
- <xsd:enumeration value="float" />
- <xsd:enumeration value="double" />
- <xsd:enumeration value="boolean" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="refSpecAttributeType">
- <xsd:complexContent>
- <xsd:extension base="flow:specAttributeType">
- <xsd:choice>
- <xsd:element name="choices" minOccurs="0" maxOccurs="1">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Possible values to chose from, if ommitted, all the beans in the
- application context which implement the provided targetClass will
- be considered.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:choice>
- <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded"
- type="flow:refChoiceType">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A choice for a reference specification attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- <xsd:attribute name="targetClass" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The class that has to be implemented by the underlying object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="refChoiceType">
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="description" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A human readable description of this choice.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:complexType name="argType">
- <xsd:choice minOccurs="0" maxOccurs="1">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="flow:param" />
- <xsd:element ref="beans:list" />
- <xsd:element ref="beans:set" />
- <xsd:element ref="beans:map" />
- <xsd:element ref="beans:props" />
- </xsd:choice>
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="value" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The plain value of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="ref" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The value of the related parameter as a reference to a bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:attribute name="as-flow" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- If decorating an executable bean, it will generate an implicit SLC
- execution flow with the provided value as name.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <!--
- <xsd:attribute name="var" type="xsd:boolean"> <xsd:annotation>
- <xsd:documentation><![CDATA[ If true, the decorated bean is set to
- scope execution and proxied. ]]></xsd:documentation> </xsd:annotation>
- </xsd:attribute>
- -->
-
- <xsd:element name="variable">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Marks a bean definition as being variable, i.e. a scoped proxy of scope execution
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:attribute name="proxy-target-class" type="xsd:boolean"
- default="true">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Are class-based (CGLIB) proxies to be created?
- This is the default;
- in order to switch to standard Java
- interface-based proxies, turn this flag to
- "false".
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="param">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- If within a property tag of a bean, it will set the value of this property
- with a reference to a parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:attribute name="name" type="xsd:string" use="required">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="instantiationManager" type="xsd:string"
- use="optional" default="instantiationManager">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference to the instantiation manager to use instead of the default one
- (expert usage).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:beans="http://www.springframework.org/schema/beans"
- targetNamespace="http://www.argeo.org/schema/slc-flow"
- elementFormDefault="qualified" attributeFormDefault="unqualified">
-
- <xsd:import namespace="http://www.springframework.org/schema/beans"
- schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" />
-
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- SLC Flow Schema, version 1.2
- Authors: Mathieu Baudier
-
- This simplifies the definition of SLC flows and their integration with
- regular Spring beans.
- ]]></xsd:documentation>
- </xsd:annotation>
-
- <xsd:element name="flow">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Adds an SLC execution flow, using the default implementation.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="beans:identifiedType">
- <xsd:sequence>
- <xsd:element ref="beans:description" minOccurs="0" />
- <xsd:sequence>
- <xsd:element name="arg" minOccurs="0" maxOccurs="unbounded"
- type="flow:argType">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Parameter for an execution flow which will override at instantiation the
- value of the parameter already defined as default value or in a parent bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:sequence>
- <xsd:sequence>
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="flow:flow" />
- <xsd:element ref="flow:spec" />
- </xsd:choice>
- <!-- <xsd:any namespace="##other" processContents="strict" minOccurs="0"
- maxOccurs="unbounded" /> -->
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Name of the flow (alternative to ID).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="class" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Another implementation of execution flow.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="path" type="xsd:string">
- <!-- DEPRECATED: not used anymore -->
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The hierarchical path under which to register this flow.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="spec" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference to the related specification bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="parent" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The parent bean definition (in Spring sense).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="abstract" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether this flow is abstract (in Spring sense).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="spec">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- SLC flow specifications, defining the parameters and variables
- which can be used in related flows, along with their default values and
- various constraints.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:complexContent>
- <xsd:extension base="beans:identifiedType">
- <xsd:sequence>
- <xsd:element ref="beans:description" minOccurs="0" />
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="primitive" type="flow:primitiveSpecAttributeType"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A primitive specification attribute, that is, a plain standard value
- and not a reference to an object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- <xsd:element name="ref" type="flow:refSpecAttributeType"
- minOccurs="0" maxOccurs="unbounded">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference specification attribute, that is, a reference to another object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:choice>
- </xsd:sequence>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:complexType name="specAttributeType">
- <xsd:choice>
- <xsd:element name="value" minOccurs="0" maxOccurs="1">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute as an inner bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:choice minOccurs="1" maxOccurs="1">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="beans:list" />
- <xsd:element ref="beans:set" />
- <xsd:element ref="beans:map" />
- <xsd:element ref="beans:props" />
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the attribute, under which in can then be referenced.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="value" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="ref" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The default value of the attribute as a reference to another bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isImmutable" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is a parameter, that is, it has to be set at
- instantiation but can be modified afterwards for objects of scope execution.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isParameter" use="optional" type="xsd:boolean"
- default="false">
- <!-- DEPRECATED: old name of isImmutable -->
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is a parameter, that is, it has to be set at
- instantiation but can be modified afterwards for objects of scope execution.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isConstant" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is frozen, that is, it cannot be modified at runtime.
- A frozen attribute has to be a parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isFrozen" use="optional" type="xsd:boolean"
- default="false">
- <!-- DEPRECATED: old name of isConstant -->
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is frozen, that is, it cannot be modified at runtime.
- A frozen attribute has to be a parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="isHidden" use="optional" type="xsd:boolean"
- default="false">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Whether the attribute is hidden, that is, it should not be displayed in UIs.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:complexType name="primitiveSpecAttributeType">
- <xsd:complexContent>
- <xsd:extension base="flow:specAttributeType">
- <xsd:attribute name="type" default="string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The type of the primitive specification attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="string" />
- <xsd:enumeration value="password" />
- <xsd:enumeration value="integer" />
- <xsd:enumeration value="long" />
- <xsd:enumeration value="float" />
- <xsd:enumeration value="double" />
- <xsd:enumeration value="boolean" />
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="refSpecAttributeType">
- <xsd:complexContent>
- <xsd:extension base="flow:specAttributeType">
- <xsd:choice>
- <xsd:element name="choices" minOccurs="0" maxOccurs="1">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Possible values to chose from, if ommitted, all the beans in the
- application context which implement the provided targetClass will
- be considered.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:choice>
- <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded"
- type="flow:refChoiceType">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A choice for a reference specification attribute.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:element>
- </xsd:choice>
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- <xsd:attribute name="targetClass" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The class that has to be implemented by the underlying object.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="refChoiceType">
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="description" use="optional" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A human readable description of this choice.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:complexType name="argType">
- <xsd:choice minOccurs="0" maxOccurs="1">
- <xsd:element ref="beans:bean" />
- <xsd:element ref="beans:ref" />
- <xsd:element ref="flow:param" />
- <xsd:element ref="beans:list" />
- <xsd:element ref="beans:set" />
- <xsd:element ref="beans:map" />
- <xsd:element ref="beans:props" />
- </xsd:choice>
- <xsd:attribute name="name" use="required" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="value" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The plain value of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="ref" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The value of the related parameter as a reference to a bean.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
-
- <xsd:attribute name="as-flow" type="xsd:string">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- If decorating an executable bean, it will generate an implicit SLC
- execution flow with the provided value as name.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <!-- <xsd:attribute name="var" type="xsd:boolean"> <xsd:annotation> <xsd:documentation><![CDATA[
- If true, the decorated bean is set to scope execution and proxied. ]]></xsd:documentation>
- </xsd:annotation> </xsd:attribute> -->
-
- <xsd:element name="variable">
- <xsd:complexType>
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Marks a bean definition as being variable, i.e. a scoped proxy of scope execution
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:attribute name="proxy-target-class" type="xsd:boolean"
- default="true">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- Are class-based (CGLIB) proxies to be created?
- This is the default;
- in order to switch to standard Java
- interface-based proxies, turn this flag to
- "false".
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="param">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- If within a property tag of a bean, it will set the value of this property
- with a reference to a parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:attribute name="name" type="xsd:string" use="required">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- The name of the related parameter.
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- <xsd:attribute name="instantiationManager" type="xsd:string"
- use="optional" default="instantiationManager">
- <xsd:annotation>
- <xsd:documentation><![CDATA[
- A reference to the instantiation manager to use instead of the default one
- (expert usage).
- ]]></xsd:documentation>
- </xsd:annotation>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
-
-</xsd:schema>
\ No newline at end of file
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import org.argeo.slc.test.TestData;\r
-\r
-public class BasicTestData implements TestData {\r
- private Object expected;\r
- private Object reached;\r
-\r
- public Object getExpected() {\r
- return expected;\r
- }\r
-\r
- public void setExpected(Object expected) {\r
- this.expected = expected;\r
- }\r
-\r
- public Object getReached() {\r
- return reached;\r
- }\r
-\r
- public void setReached(Object reached) {\r
- this.reached = reached;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.core.test.context.ContextUtils;\r
-import org.argeo.slc.test.IncompatibleTestDataException;\r
-import org.argeo.slc.test.TestData;\r
-import org.argeo.slc.test.TestDefinition;\r
-import org.argeo.slc.test.TestResult;\r
-import org.argeo.slc.test.TestRun;\r
-import org.argeo.slc.test.TestStatus;\r
-import org.argeo.slc.test.context.ContextAware;\r
-\r
-/** Understands basic test data and context aware test data. */\r
-public class BasicTestDefinition implements TestDefinition {\r
-\r
- public void execute(TestRun testRun) {\r
- if (testRun.<TestData> getTestData() instanceof BasicTestData) {\r
- BasicTestData testData = testRun.getTestData();\r
- TestResult result = testRun.getTestResult();\r
-\r
- if (result == null)\r
- throw new SlcException("No test result defined.");\r
-\r
- try {\r
- if (testData.getExpected().equals(testData.getReached())) {\r
- result.addResultPart(new SimpleResultPart(\r
- TestStatus.PASSED, "Reached and expected equals"));\r
- } else {\r
- result.addResultPart(new SimpleResultPart(\r
- TestStatus.FAILED, "Expected "\r
- + testData.getExpected() + " but reached "\r
- + testData.getReached()));\r
- }\r
- } catch (Exception e) {\r
- result.addResultPart(new SimpleResultPart(TestStatus.ERROR,\r
- "Could not compare", e));\r
- }\r
- } else if (testRun.<TestData> getTestData() instanceof ContextAware) {\r
- TestData testData = testRun.getTestData();\r
- ContextUtils.compareReachedExpected((ContextAware) testData,\r
- testRun.getTestResult());\r
- } else {\r
- throw new IncompatibleTestDataException(testRun);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import java.io.Serializable;\r
-\r
-import org.argeo.slc.test.TestResultPart;\r
-import org.argeo.slc.test.TestRun;\r
-import org.argeo.slc.test.TestRunAware;\r
-import org.argeo.slc.test.TestStatus;\r
-\r
-/**\r
- * <p>\r
- * Basic implementation of a result part, implementing the standard three status\r
- * approach for test results.\r
- * </p>\r
- * \r
- * @see TestStatus\r
- */\r
-public class SimpleResultPart implements TestResultPart, TestStatus,\r
- TestRunAware, Serializable {\r
- private static final long serialVersionUID = 6669675957685071901L;\r
-\r
- private Long tid;\r
-\r
- private String testRunUuid;\r
-\r
- /** The status. Default to ERROR since it should always be explicitely set. */\r
- private Integer status = ERROR;\r
- private String message;\r
- private String exceptionMessage;\r
-\r
- public SimpleResultPart() {\r
- }\r
-\r
- public SimpleResultPart(Integer status, String message) {\r
- this(status, message, null);\r
- }\r
-\r
- public SimpleResultPart(Integer status, String message, Exception exception) {\r
- this.status = status;\r
- this.message = message;\r
- setException(exception);\r
- }\r
-\r
- public String getMessage() {\r
- return message;\r
- }\r
-\r
- public void setMessage(String message) {\r
- this.message = message;\r
- }\r
-\r
- public void setStatus(Integer status) {\r
- this.status = status;\r
- }\r
-\r
- public Integer getStatus() {\r
- return status;\r
- }\r
-\r
- public String getExceptionMessage() {\r
- return exceptionMessage;\r
- }\r
-\r
- public void setException(Exception exception) {\r
- if (exception == null)\r
- return;\r
-\r
- StringBuffer buf = new StringBuffer("");\r
- buf.append(exception.toString());\r
- buf.append('\n');\r
- for (StackTraceElement elem : exception.getStackTrace()) {\r
- buf.append('\t').append(elem.toString()).append('\n');\r
- }\r
-\r
- if (exception.getCause() != null)\r
- addRootCause(buf, exception.getCause());\r
-\r
- this.exceptionMessage = buf.toString();\r
- }\r
-\r
- protected void addRootCause(StringBuffer buf, Throwable cause) {\r
- if (cause == null)\r
- return;\r
-\r
- buf.append("Caused by: " + cause.getMessage());\r
- for (StackTraceElement elem : cause.getStackTrace()) {\r
- buf.append('\t').append(elem.toString()).append('\n');\r
- }\r
-\r
- if (cause.getCause() != null) {\r
- addRootCause(buf, cause.getCause());\r
- }\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- StringBuffer buf = new StringBuffer("");\r
- buf.append(SlcTestUtils.statusToString(status));\r
- if (status == PASSED || status == FAILED) {\r
- buf.append(' ');\r
- } else if (status == ERROR) {\r
- buf.append(" ");\r
- }\r
- buf.append(message);\r
- return buf.toString();\r
- }\r
-\r
- /** @deprecated */\r
- Long getTid() {\r
- return tid;\r
- }\r
-\r
- /** @deprecated */\r
- void setTid(Long tid) {\r
- this.tid = tid;\r
- }\r
-\r
- public String getTestRunUuid() {\r
- return testRunUuid;\r
- }\r
-\r
- /** For ORM */\r
- public void setTestRunUuid(String testRunUuid) {\r
- this.testRunUuid = testRunUuid;\r
- }\r
-\r
- public void notifyTestRun(TestRun testRun) {\r
- testRunUuid = testRun.getUuid();\r
- }\r
-\r
- public void setExceptionMessage(String exceptionMessage) {\r
- this.exceptionMessage = exceptionMessage;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-import java.util.UUID;\r
-import java.util.Vector;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.test.TestResult;\r
-import org.argeo.slc.test.TestResultPart;\r
-import org.argeo.slc.test.TestRun;\r
-\r
-/**\r
- * Basic implementation of a test result containing only a list of result parts.\r
- */\r
-public class SimpleTestResult implements TestResult {\r
- private static Log log = LogFactory.getLog(SimpleTestResult.class);\r
-\r
- private String uuid;\r
- private String currentTestRunUuid;\r
-\r
- private Boolean throwError = true;\r
-\r
- private Date closeDate;\r
- private List<TestResultPart> parts = new Vector<TestResultPart>();\r
-\r
- private Map<String, String> attributes = new TreeMap<String, String>();\r
-\r
- public void addResultPart(TestResultPart part) {\r
- if (throwError && part.getStatus() == ERROR) {\r
- throw new SlcException(\r
- "There was an error in the underlying test: "\r
- + part.getExceptionMessage());\r
- }\r
- parts.add(part);\r
- if (log.isDebugEnabled())\r
- log.debug(part);\r
- }\r
-\r
- public void close() {\r
- parts.clear();\r
- closeDate = new Date();\r
- }\r
-\r
- public List<TestResultPart> getParts() {\r
- return parts;\r
- }\r
-\r
- public Date getCloseDate() {\r
- return closeDate;\r
- }\r
-\r
- public void setThrowError(Boolean throwError) {\r
- this.throwError = throwError;\r
- }\r
-\r
- public void notifyTestRun(TestRun testRun) {\r
- currentTestRunUuid = testRun.getUuid();\r
- }\r
-\r
- public String getUuid() {\r
- if (uuid == null) {\r
- uuid = UUID.randomUUID().toString();\r
- }\r
- return uuid;\r
- }\r
-\r
- public void setUuid(String uuid) {\r
- this.uuid = uuid;\r
- }\r
-\r
- public String getCurrentTestRunUuid() {\r
- return currentTestRunUuid;\r
- }\r
-\r
- public Map<String, String> getAttributes() {\r
- return attributes;\r
- }\r
-\r
- public void setAttributes(Map<String, String> attributes) {\r
- this.attributes = attributes;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import java.util.UUID;\r
-\r
-import org.argeo.slc.deploy.DeployedSystem;\r
-import org.argeo.slc.test.ExecutableTestRun;\r
-import org.argeo.slc.test.TestData;\r
-import org.argeo.slc.test.TestDefinition;\r
-import org.argeo.slc.test.TestResult;\r
-import org.argeo.slc.test.WritableTestRun;\r
-\r
-/**\r
- * A basic bean implementation of a <code>WritableTestRun</code>, holding\r
- * references to the various parts of a test run.\r
- */\r
-public class SimpleTestRun implements WritableTestRun, ExecutableTestRun {\r
- private String uuid;\r
-\r
- // private String slcExecutionUuid;\r
- // private String slcExecutionStepUuid;\r
-\r
- private DeployedSystem deployedSystem;\r
- private TestData testData;\r
- private TestDefinition testDefinition;\r
- private TestResult testResult;\r
-\r
- /** Executes the underlying test definition. */\r
- public void run() {\r
- uuid = UUID.randomUUID().toString();\r
- if (testResult != null)\r
- testResult.notifyTestRun(this);\r
-\r
- testDefinition.execute(this);\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- public <T extends DeployedSystem> T getDeployedSystem() {\r
- return (T) deployedSystem;\r
- }\r
-\r
- public void setDeployedSystem(DeployedSystem deployedSystem) {\r
- this.deployedSystem = deployedSystem;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- public <T extends TestData> T getTestData() {\r
- return (T) testData;\r
- }\r
-\r
- public void setTestData(TestData testData) {\r
- this.testData = testData;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- public <T extends TestDefinition> T getTestDefinition() {\r
- return (T) testDefinition;\r
- }\r
-\r
- public void setTestDefinition(TestDefinition testDefinition) {\r
- this.testDefinition = testDefinition;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- public <T extends TestResult> T getTestResult() {\r
- return (T) testResult;\r
- }\r
-\r
- public void setTestResult(TestResult testResult) {\r
- this.testResult = testResult;\r
- }\r
-\r
- public String getUuid() {\r
- return uuid;\r
- }\r
-\r
- public void setUuid(String uuid) {\r
- this.uuid = uuid;\r
- }\r
-\r
- // public String getSlcExecutionUuid() {\r
- // return slcExecutionUuid;\r
- // }\r
- //\r
- // public void setSlcExecutionUuid(String slcExecutionUuid) {\r
- // this.slcExecutionUuid = slcExecutionUuid;\r
- // }\r
- //\r
- // public String getSlcExecutionStepUuid() {\r
- // return slcExecutionStepUuid;\r
- // }\r
- //\r
- // public void setSlcExecutionStepUuid(String slcExecutionStepUuid) {\r
- // this.slcExecutionStepUuid = slcExecutionStepUuid;\r
- // }\r
-}\r
+++ /dev/null
-/*
- * 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() {
-
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test;\r
-\r
-import org.argeo.slc.UnsupportedException;\r
-import org.argeo.slc.test.TestData;\r
-import org.argeo.slc.test.TestDataProvider;\r
-\r
-/** Utilities for dealing with test datas. */\r
-public class TestDataUtils {\r
- /** Extracts the test data from the given provider. */\r
- public static <T extends TestData> T getFromProvider(Object obj,\r
- Class<T> clss, String key) {\r
- if (obj instanceof TestDataProvider) {\r
- TestDataProvider testDataProvider = (TestDataProvider) obj;\r
- return testDataProvider.getTestData(clss, key);\r
- } else {\r
- throw new UnsupportedException("test data provider", obj);\r
- }\r
- }\r
-\r
- /**\r
- * Extracts the test data from the given provider using <code>null</code>\r
- * as key.\r
- */\r
- public static <T extends TestData> T getFromProvider(Object obj,\r
- Class<T> clss) {\r
- return getFromProvider(obj, clss, null);\r
- }\r
-\r
- /**\r
- * Returns it self after making the proper checks. Used for test data being\r
- * their own data providers.\r
- */\r
- @SuppressWarnings("unchecked")\r
- public static <T extends TestData> T getItSelf(Class<T> clss,\r
- TestData testDataObject) {\r
- if (clss.isAssignableFrom(testDataObject.getClass())) {\r
- return (T) testDataObject;\r
- } else {\r
- throw new UnsupportedException("test data", testDataObject);\r
- }\r
-\r
- }\r
-\r
- /** Makes sure this is an utility class. */\r
- private TestDataUtils() {\r
-\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.argeo.slc.core.test.SimpleResultPart;\r
-import org.argeo.slc.test.TestResult;\r
-import org.argeo.slc.test.TestStatus;\r
-import org.argeo.slc.test.context.ContextAware;\r
-import org.argeo.slc.test.context.ParentContextAware;\r
-\r
-/** Utilities for comparing and synchronising contexts. */\r
-public class ContextUtils {\r
- private final static Log log = LogFactory.getLog(ContextUtils.class);\r
-\r
- public static void compareReachedExpected(ContextAware contextAware,\r
- TestResult testResult) {\r
- for (String key : contextAware.getExpectedValues().keySet()) {\r
-\r
- // Compare expected values with reached ones\r
- Object expectedValue = contextAware.getExpectedValues().get(key);\r
-\r
- if (expectedValue.toString().equals(\r
- contextAware.getContextSkipFlag())) {\r
- if (log.isDebugEnabled())\r
- log.debug("Skipped check for key '" + key + "'");\r
- continue;\r
- }\r
-\r
- if (contextAware.getValues().containsKey(key)) {\r
- Object reachedValue = contextAware.getValues().get(key);\r
-\r
- if (expectedValue.equals(contextAware.getContextAnyFlag())) {\r
- testResult.addResultPart(new SimpleResultPart(\r
- TestStatus.PASSED, "Expected any value for key '"\r
- + key + "'"));\r
- } else if (expectedValue.equals(reachedValue)) {\r
- testResult.addResultPart(new SimpleResultPart(\r
- TestStatus.PASSED, "Values matched for key '" + key\r
- + "'"));\r
- } else {\r
- testResult.addResultPart(new SimpleResultPart(\r
- TestStatus.FAILED, "Mismatch for key '" + key\r
- + "': expected '" + expectedValue\r
- + "' but reached '" + reachedValue + "'"));\r
- }\r
- } else {\r
- testResult.addResultPart(new SimpleResultPart(\r
- TestStatus.FAILED, "No value reached for key '" + key\r
- + "'"));\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Makes sure that all children and sub-children of parent share the same\r
- * maps for values and expected values.\r
- */\r
- public static void synchronize(ParentContextAware parent) {\r
- Map<String, Object> expectedValuesCommon = new TreeMap<String, Object>(\r
- parent.getExpectedValues());\r
- synchronize(parent, expectedValuesCommon);\r
- if (log.isDebugEnabled())\r
- log.debug("Synchronized context " + parent);\r
-\r
- }\r
-\r
- private static void synchronize(ParentContextAware parent,\r
- Map<String, Object> expectedValuesCommon) {\r
- for (ContextAware child : parent.getChildContexts()) {\r
- // Values\r
- putNotContained(parent.getValues(), child.getValues());\r
- child.setValues(parent.getValues());\r
-\r
- // Expected Values\r
- // Expected values reference is not overridden: each child has its\r
- // own expected values map.\r
- overrideContained(expectedValuesCommon, child.getExpectedValues());\r
-\r
- // Creates a new Map in order not to disturb other context using the\r
- // same keys\r
- Map<String, Object> expectedValuesCommonChild = new TreeMap<String, Object>(\r
- expectedValuesCommon);\r
- putNotContained(expectedValuesCommonChild,\r
- child.getExpectedValues());\r
-\r
- if (child instanceof ParentContextAware) {\r
- // Recursive sync\r
- synchronize((ParentContextAware) child,\r
- expectedValuesCommonChild);\r
- }\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Put into common map the values from child map which are not already\r
- * defined in common map.\r
- */\r
- public static void putNotContained(Map<String, Object> commonMap,\r
- Map<String, Object> childMap) {\r
- for (String key : childMap.keySet()) {\r
- if (!commonMap.containsKey(key)) {\r
- commonMap.put(key, childMap.get(key));\r
- }\r
- }\r
- }\r
-\r
- /** Overrides child map values with the values already set in common map */\r
- public static void overrideContained(Map<String, Object> commonMap,\r
- Map<String, Object> childMap) {\r
- for (String key : childMap.keySet()) {\r
- if (commonMap.containsKey(key)) {\r
- childMap.put(key, commonMap.get(key));\r
- }\r
- }\r
- }\r
-\r
- /** Makes sure this cannot be instantiated. */\r
- private ContextUtils() {\r
-\r
- }\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import org.argeo.slc.core.test.TestDataUtils;\r
-import org.argeo.slc.test.TestData;\r
-import org.argeo.slc.test.TestDataProvider;\r
-\r
-public class DefaultContextTestData extends SimpleContextAware implements\r
- TestData, TestDataProvider {\r
-\r
- public <T extends TestData> T getTestData(Class<T> clss, String key) {\r
- return TestDataUtils.getItSelf(clss, this);\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-\r
-import org.argeo.slc.SlcException;\r
-import org.argeo.slc.test.context.ContextAware;\r
-import org.argeo.slc.test.context.ParentContextAware;\r
-import org.springframework.beans.factory.InitializingBean;\r
-\r
-public class SimpleContextAware implements ContextAware, InitializingBean {\r
- private ParentContextAware parentContext;\r
-\r
- private Map<String, Object> values = new TreeMap<String, Object>();\r
- private Map<String, Object> expectedValues = new TreeMap<String, Object>();\r
-\r
- private String contextSkipFlag = DEFAULT_SKIP_FLAG;\r
- private String contextAnyFlag = DEFAULT_ANY_FLAG;\r
-\r
- public Map<String, Object> getValues() {\r
- return values;\r
- }\r
-\r
- public void setValues(Map<String, Object> values) {\r
- this.values = values;\r
- }\r
-\r
- public Map<String, Object> getExpectedValues() {\r
- return expectedValues;\r
- }\r
-\r
- public void setExpectedValues(Map<String, Object> expectedValues) {\r
- this.expectedValues = expectedValues;\r
- }\r
-\r
- /** Used to add this context as a child by setting a property. */\r
- public void setParentContext(ParentContextAware parentContextAware) {\r
- if (parentContext != null)\r
- throw new SlcException("Parent context already set");\r
- this.parentContext = parentContextAware;\r
- this.parentContext.addChildContext(this);\r
- }\r
-\r
- protected ParentContextAware getParentContext() {\r
- return parentContext;\r
- }\r
-\r
- public void afterPropertiesSet() throws Exception {\r
- if (parentContext != null) {\r
- ContextUtils.synchronize(parentContext);\r
- }\r
- }\r
-\r
- public String getContextSkipFlag() {\r
- return contextSkipFlag;\r
- }\r
-\r
- public void setContextSkipFlag(String contextSkipFlag) {\r
- this.contextSkipFlag = contextSkipFlag;\r
- }\r
-\r
- public String getContextAnyFlag() {\r
- return contextAnyFlag;\r
- }\r
-\r
- public void setContextAnyFlag(String contextAnyFlag) {\r
- this.contextAnyFlag = contextAnyFlag;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.slc.core.test.context;\r
-\r
-import java.util.Collection;\r
-import java.util.List;\r
-import java.util.Vector;\r
-\r
-import org.argeo.slc.test.context.ContextAware;\r
-import org.argeo.slc.test.context.ParentContextAware;\r
-import org.springframework.beans.factory.InitializingBean;\r
-\r
-public class SimpleParentContextAware extends SimpleContextAware implements\r
- ParentContextAware, InitializingBean {\r
- private List<ContextAware> children = new Vector<ContextAware>();\r
-\r
- public Collection<ContextAware> getChildContexts() {\r
- return children;\r
- }\r
-\r
- public void addChildContext(ContextAware contextAware) {\r
- children.add(contextAware);\r
- }\r
-\r
- @Override\r
- public void afterPropertiesSet() throws Exception {\r
- if (getParentContext() != null) {\r
- // If has a parent, sync it.\r
- super.afterPropertiesSet();\r
- } else {\r
- if (children.size() > 0) {\r
- // No need to synchronize if no children\r
- ContextUtils.synchronize(this);\r
- }\r
- }\r
- }\r
-}\r
+++ /dev/null
-<html>\r
-<head></head>\r
-<body>\r
-Context variables to be passed between parts of tests.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-<html>\r
-<head></head>\r
-<body>\r
-SLC Test: test of software systems.\r
-</body>\r
-</html>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
- default-lazy-init="true">
-
- <bean name="slcDefault.test.testRun"
- class="org.argeo.slc.core.test.SimpleTestRun"
- scope="prototype">
- </bean>
-
- <bean name="slcDefault.test.uuid" class="java.util.UUID"
- factory-method="randomUUID" scope="prototype">
- </bean>
-
- <bean id="slcDefault.test.basicSimpleTestResult"
- class="org.argeo.slc.core.test.SimpleTestResult"
- abstract="true">
- <property name="uuid">
- <bean factory-bean="slcDefault.test.uuid"
- factory-method="toString">
- </bean>
- </property>
- </bean>
-
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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.jcr;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-
-/**
- * Writes arbitrary metadata into a child node of a given node (or the node
- * itself if metadata node name is set to null)
- */
-public class JcrMetadataWriter implements Runnable {
- private final static Log log = LogFactory.getLog(JcrMetadataWriter.class);
-
- private Node baseNode;
- private String metadataNodeName = SlcNames.SLC_METADATA;
-
- private Map<String, String> metadata = new HashMap<String, String>();
-
- public void run() {
- try {
- Node metadataNode;
- if (metadataNodeName != null)
- metadataNode = baseNode.hasNode(metadataNodeName) ? baseNode
- .getNode(metadataNodeName) : baseNode
- .addNode(metadataNodeName);
- else
- metadataNode = baseNode;
-
- for (String key : metadata.keySet())
- metadataNode.setProperty(key, metadata.get(key));
-
- baseNode.getSession().save();
-
- if (log.isDebugEnabled())
- log.debug("Wrote " + metadata.size() + " metadata entries to "
- + metadataNode);
- } catch (RepositoryException e) {
- throw new SlcException("Cannot write metadata to " + baseNode, e);
- } finally {
- JcrUtils.discardUnderlyingSessionQuietly(baseNode);
- }
-
- }
-
- public void setBaseNode(Node baseNode) {
- this.baseNode = baseNode;
- }
-
- public void setMetadataNodeName(String metadataNodeName) {
- this.metadataNodeName = metadataNodeName;
- }
-
- public void setMetadata(Map<String, String> metadata) {
- this.metadata = metadata;
- }
-
-}
+++ /dev/null
-/*
- * 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.jcr;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.jcr.Credentials;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.attachment.Attachment;
-import org.argeo.slc.core.attachment.AttachmentsEnabled;
-import org.argeo.slc.test.TestResult;
-import org.argeo.slc.test.TestResultPart;
-import org.argeo.slc.test.TestRun;
-import org.argeo.slc.test.TestStatus;
-
-/**
- * {@link TestResult} wrapping a JCR node of type
- * {@link SlcTypes#SLC_TEST_RESULT}.
- */
-public class JcrTestResult implements TestResult, SlcNames, AttachmentsEnabled {
- private final static Log log = LogFactory.getLog(JcrTestResult.class);
-
- /** Should only be set for an already existing result. */
- private String uuid;
- private Repository repository;
- private Session session;
- /**
- * For testing purposes, best practice is to not set them explicitely but
- * via other mechanisms such as JAAS or SPring Security.
- */
- private Credentials credentials = null;
- private String resultType = SlcTypes.SLC_TEST_RESULT;
-
- /** cached for performance purposes */
- private String nodeIdentifier = null;
-
- private Map<String, String> attributes = new HashMap<String, String>();
-
- public void init() {
- try {
- session = repository.login(credentials);
- if (uuid == null) {
- // create new result
- uuid = UUID.randomUUID().toString();
- String path = SlcJcrUtils.createResultPath(session, uuid);
- Node resultNode = JcrUtils.mkdirs(session, path, resultType);
- resultNode.setProperty(SLC_UUID, uuid);
- for (String attr : attributes.keySet()) {
- String property = attr;
- // compatibility with legacy applications
- if ("testCase".equals(attr))
- property = SLC_TEST_CASE;
- else if ("testCaseType".equals(attr))
- property = SLC_TEST_CASE_TYPE;
- resultNode.setProperty(property, attributes.get(attr));
- }
- session.save();
- if (log.isDebugEnabled())
- log.debug("Created test result " + uuid);
- }
- } catch (Exception e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot initialize JCR result", e);
- }
- }
-
- public void destroy() {
- JcrUtils.logoutQuietly(session);
- if (log.isTraceEnabled())
- log.trace("Logged out session for result " + uuid);
- }
-
- public Node getNode() {
- try {
- Node resultNode;
- if (nodeIdentifier != null) {
- return session.getNodeByIdentifier(nodeIdentifier);
- } else {
- QueryManager qm = session.getWorkspace().getQueryManager();
- Query q = qm.createQuery("select * from ["
- + SlcTypes.SLC_TEST_RESULT + "] where [slc:uuid]='"
- + uuid + "'", Query.JCR_SQL2);
- resultNode = JcrUtils.querySingleNode(q);
- if (resultNode != null)
- nodeIdentifier = resultNode.getIdentifier();
- }
- return resultNode;
- } catch (Exception e) {
- throw new SlcException("Cannot get result node", e);
- }
- }
-
- public void notifyTestRun(TestRun testRun) {
- // TODO store meta data about the test running
- // if (log.isDebugEnabled())
- // log.debug("Running test "
- // + testRun.getTestDefinition().getClass().getName() + "...");
- }
-
- public void addResultPart(TestResultPart testResultPart) {
- Node node = getNode();
-
- try {
- // error : revert all unsaved changes on the resultNode to be sure
- // it is in a consistant state
- if (testResultPart.getExceptionMessage() != null)
- JcrUtils.discardQuietly(node.getSession());
- node.getSession().save();
-
- // add the new result part, retrieving status information
- Node resultPartNode = node.addNode(SlcNames.SLC_RESULT_PART,
- SlcTypes.SLC_CHECK);
- resultPartNode.setProperty(SLC_SUCCESS, testResultPart.getStatus()
- .equals(TestStatus.PASSED));
- if (testResultPart.getMessage() != null)
- resultPartNode.setProperty(SLC_MESSAGE,
- testResultPart.getMessage());
- if (testResultPart.getStatus().equals(TestStatus.ERROR)) {
- resultPartNode.setProperty(SLC_ERROR_MESSAGE,
- (testResultPart.getExceptionMessage() == null) ? ""
- : testResultPart.getExceptionMessage());
- }
-
- // helper update aggregate status node
- Node mainStatus;
- if (!node.hasNode(SLC_AGGREGATED_STATUS)) {
-
- mainStatus = node.addNode(SLC_AGGREGATED_STATUS,
- SlcTypes.SLC_CHECK);
- mainStatus.setProperty(SLC_SUCCESS,
- resultPartNode.getProperty(SLC_SUCCESS).getBoolean());
- if (resultPartNode.hasProperty(SLC_MESSAGE))
- mainStatus.setProperty(SLC_MESSAGE, resultPartNode
- .getProperty(SLC_MESSAGE).getString());
- if (resultPartNode.hasProperty(SLC_ERROR_MESSAGE))
- mainStatus.setProperty(SLC_ERROR_MESSAGE, resultPartNode
- .getProperty(SLC_ERROR_MESSAGE).getString());
- } else {
- mainStatus = node.getNode(SLC_AGGREGATED_STATUS);
- if (mainStatus.hasProperty(SLC_ERROR_MESSAGE)) {
- // main status already in error we do nothing
- } else if (resultPartNode.hasProperty(SLC_ERROR_MESSAGE)) {
- // main status was not in error and new result part is in
- // error; we update main status
- mainStatus.setProperty(SLC_SUCCESS, false);
- mainStatus.setProperty(SLC_ERROR_MESSAGE, resultPartNode
- .getProperty(SLC_ERROR_MESSAGE).getString());
- if (resultPartNode.hasProperty(SLC_MESSAGE))
- mainStatus.setProperty(SLC_MESSAGE, resultPartNode
- .getProperty(SLC_MESSAGE).getString());
- else
- // remove old message to remain consistent
- mainStatus.setProperty(SLC_MESSAGE, "");
- } else if (!mainStatus.getProperty(SLC_SUCCESS).getBoolean()) {
- // main status was already failed and new result part is not
- // in error, we do nothing
- } else if (!resultPartNode.getProperty(SLC_SUCCESS)
- .getBoolean()) {
- // new resultPart that is failed
- mainStatus.setProperty(SLC_SUCCESS, false);
- if (resultPartNode.hasProperty(SLC_MESSAGE))
- mainStatus.setProperty(SLC_MESSAGE, resultPartNode
- .getProperty(SLC_MESSAGE).getString());
- else
- // remove old message to remain consistent
- mainStatus.setProperty(SLC_MESSAGE, "");
- } else if (resultPartNode.hasProperty(SLC_MESSAGE)
- && (!mainStatus.hasProperty(SLC_MESSAGE) || (""
- .equals(mainStatus.getProperty(SLC_MESSAGE)
- .getString().trim())))) {
- mainStatus.setProperty(SLC_MESSAGE, resultPartNode
- .getProperty(SLC_MESSAGE).getString());
- }
- }
- JcrUtils.updateLastModified(node);
- node.getSession().save();
- } catch (Exception e) {
- JcrUtils.discardUnderlyingSessionQuietly(node);
- throw new SlcException("Cannot add ResultPart to node " + node, e);
- }
- }
-
- public String getUuid() {
- Node node = getNode();
- try {
- return node.getProperty(SLC_UUID).getString();
- } catch (Exception e) {
- throw new SlcException("Cannot get UUID from " + node, e);
- }
- }
-
- /** JCR session is NOT logged out */
- public void close() {
- Node node = getNode();
- try {
- if (node.hasNode(SLC_COMPLETED))
- return;
- node.setProperty(SLC_COMPLETED, new GregorianCalendar());
- JcrUtils.updateLastModified(node);
- node.getSession().save();
- } catch (Exception e) {
- JcrUtils.discardUnderlyingSessionQuietly(node);
- throw new SlcException("Cannot get close date from " + node, e);
- }
- }
-
- public Date getCloseDate() {
- Node node = getNode();
- try {
- if (!node.hasNode(SLC_COMPLETED))
- return null;
- return node.getProperty(SLC_COMPLETED).getDate().getTime();
- } catch (Exception e) {
- throw new SlcException("Cannot get close date from " + node, e);
- }
- }
-
- public Map<String, String> getAttributes() {
- Node node = getNode();
- try {
- Map<String, String> map = new HashMap<String, String>();
- PropertyIterator pit = node.getProperties();
- while (pit.hasNext()) {
- Property p = pit.nextProperty();
- if (!p.isMultiple())
- map.put(p.getName(), p.getValue().getString());
- }
- return map;
- } catch (Exception e) {
- throw new SlcException("Cannot get close date from " + node, e);
- }
- }
-
- public void addAttachment(Attachment attachment) {
- // TODO implement it
- }
-
- public void setUuid(String uuid) {
- this.uuid = uuid;
- }
-
- public void setRepository(Repository repository) {
- this.repository = repository;
- }
-
- public void setResultType(String resultType) {
- this.resultType = resultType;
- }
-
- public void setAttributes(Map<String, String> attributes) {
- if (uuid != null)
- throw new SlcException(
- "Attributes cannot be set on an already initialized test result."
- + " Update the related JCR node directly instead.");
- this.attributes = attributes;
- }
-
- public void setCredentials(Credentials credentials) {
- this.credentials = credentials;
- }
-}
+++ /dev/null
-/*
- * 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.jcr;
-
-import org.argeo.slc.SlcNames;
-
-/** JCR related constants used across SLC */
-public interface SlcJcrConstants {
- public final static String PROPERTY_PATH = "argeo.slc.jcr.path";
-
- public final static String SLC_BASE_PATH = "/" + SlcNames.SLC_SYSTEM;
- public final static String AGENTS_BASE_PATH = SLC_BASE_PATH + "/"
- + SlcNames.SLC_AGENTS;
- public final static String VM_AGENT_FACTORY_PATH = AGENTS_BASE_PATH + "/"
- + SlcNames.SLC_VM;
-}
+++ /dev/null
-/*
- * 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.jcr;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.node.NodeUtils;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-
-/**
- * Utilities around the SLC JCR Result model. Note that it relies on fixed base
- * paths (convention over configuration) for optimization purposes.
- */
-public class SlcJcrResultUtils {
-
- /**
- * Returns the path to the current slc:result node
- */
- public static String getSlcResultsBasePath(Session session) {
- try {
- Node userHome = NodeUtils.getUserHome(session);
- if (userHome == null)
- throw new SlcException("No user home available for "
- + session.getUserID());
- return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
- + SlcNames.SLC_RESULTS;
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while getting Slc Results Base Path.", re);
- }
- }
-
- /**
- * Returns the base node to store SlcResults. If it does not exists, it is
- * created. If a node already exists at the given path with the wrong type,
- * it throws an exception.
- *
- * @param session
- * @return
- */
- public static Node getSlcResultsParentNode(Session session) {
- try {
- String absPath = getSlcResultsBasePath(session);
- if (session.nodeExists(absPath)) {
- Node currNode = session.getNode(absPath);
- if (currNode.isNodeType(NodeType.NT_UNSTRUCTURED))
- return currNode;
- else
- throw new SlcException(
- "A node already exists at this path : " + absPath
- + " that has the wrong type. ");
- } else {
- Node slcResParNode = JcrUtils.mkdirs(session, absPath);
- slcResParNode.setPrimaryType(NodeType.NT_UNSTRUCTURED);
- session.save();
- return slcResParNode;
- }
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while creating slcResult root parent node.",
- re);
- }
- }
-
- /**
- * Returns the path to the current Result UI specific node, depending the
- * current user
- */
- public static String getMyResultsBasePath(Session session) {
- try {
- Node userHome = NodeUtils.getUserHome(session);
- if (userHome == null)
- throw new SlcException("No user home available for "
- + session.getUserID());
- return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
- + SlcNames.SLC_MY_RESULTS;
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while getting Slc Results Base Path.", re);
- }
- }
-
- /**
- * Creates a new node with type SlcTypes.SLC_MY_RESULT_ROOT_FOLDER at the
- * given absolute path. If a node already exists at the given path, returns
- * that node if it has the correct type and throws an exception otherwise.
- *
- * @param session
- * @return
- */
- public static Node getMyResultParentNode(Session session) {
- try {
- String absPath = getMyResultsBasePath(session);
- if (session.nodeExists(absPath)) {
- Node currNode = session.getNode(absPath);
- if (currNode.isNodeType(SlcTypes.SLC_MY_RESULT_ROOT_FOLDER))
- return currNode;
- else
- throw new SlcException(
- "A node already exists at this path : " + absPath
- + " that has the wrong type. ");
- } else {
- Node myResParNode = JcrUtils.mkdirs(session, absPath);
- myResParNode.setPrimaryType(SlcTypes.SLC_MY_RESULT_ROOT_FOLDER);
- session.save();
- return myResParNode;
- }
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while creating user MyResult base node.",
- re);
- }
- }
-
- /**
- * Creates a new node with type SlcTypes.SLC_RESULT_FOLDER at the given
- * absolute path. If a node already exists at the given path, returns that
- * node if it has the correct type and throws an exception otherwise.
- *
- * @param session
- * @param absPath
- * @return
- */
- public static synchronized Node createResultFolderNode(Session session,
- String absPath) {
- try {
- if (session.nodeExists(absPath)) {
- // Sanity check
- Node currNode = session.getNode(absPath);
- if (currNode.isNodeType(SlcTypes.SLC_RESULT_FOLDER))
- return currNode;
- else
- throw new SlcException(
- "A node already exists at this path : " + absPath
- + " that has the wrong type. ");
- }
- Node rfNode = JcrUtils.mkdirs(session, absPath);
- rfNode.setPrimaryType(SlcTypes.SLC_RESULT_FOLDER);
- Node statusNode = rfNode.addNode(SlcNames.SLC_AGGREGATED_STATUS,
- SlcTypes.SLC_CHECK);
- statusNode.setProperty(SlcNames.SLC_SUCCESS, true);
- session.save();
- return rfNode;
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while creating Result Folder node.", re);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.jcr;
-
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.node.NodeUtils;
-import org.argeo.slc.DefaultNameVersion;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.execution.PrimitiveAccessor;
-import org.argeo.slc.core.execution.PrimitiveUtils;
-import org.argeo.slc.deploy.ModuleDescriptor;
-import org.argeo.slc.test.TestStatus;
-
-/**
- * Utilities around the SLC JCR model. Note that it relies on fixed base paths
- * (convention over configuration) for optimization purposes.
- */
-public class SlcJcrUtils implements SlcNames {
- public final static Integer AGENT_FACTORY_DEPTH = 3;
-
- /** Extracts the path of a flow relative to its execution module */
- public static String flowRelativePath(String fullFlowPath) {
- String[] tokens = fullFlowPath.split("/");
- StringBuffer buf = new StringBuffer(fullFlowPath.length());
- for (int i = AGENT_FACTORY_DEPTH + 3; i < tokens.length; i++) {
- buf.append('/').append(tokens[i]);
- }
- return buf.toString();
- }
-
- /** Extracts the path to the related execution module */
- public static String modulePath(String fullFlowPath) {
- String[] tokens = fullFlowPath.split("/");
- StringBuffer buf = new StringBuffer(fullFlowPath.length());
- for (int i = 0; i < AGENT_FACTORY_DEPTH + 3; i++) {
- if (!tokens[i].equals(""))
- buf.append('/').append(tokens[i]);
- }
- return buf.toString();
- }
-
- /** Extracts the module name from a flow path */
- public static String moduleName(String fullFlowPath) {
- String[] tokens = fullFlowPath.split("/");
- String moduleName = tokens[AGENT_FACTORY_DEPTH + 2];
- moduleName = moduleName.substring(0, moduleName.indexOf('_'));
- return moduleName;
- }
-
- /** Extracts the module name and version from a flow path */
- public static NameVersion moduleNameVersion(String fullFlowPath) {
- String[] tokens = fullFlowPath.split("/");
- String module = tokens[AGENT_FACTORY_DEPTH + 2];
- String moduleName = module.substring(0, module.indexOf('_'));
- String moduleVersion = module.substring(module.indexOf('_') + 1);
- return new DefaultNameVersion(moduleName, moduleVersion);
- }
-
- /** Module node name based on module name and version */
- public static String getModuleNodeName(ModuleDescriptor moduleDescriptor) {
- return moduleDescriptor.getName() + "_" + moduleDescriptor.getVersion();
- }
-
- /** Extracts the agent factory of a flow */
- public static String flowAgentFactoryPath(String fullFlowPath) {
- String[] tokens = fullFlowPath.split("/");
- StringBuffer buf = new StringBuffer(fullFlowPath.length());
- // first token is always empty
- for (int i = 1; i < AGENT_FACTORY_DEPTH + 1; i++) {
- buf.append('/').append(tokens[i]);
- }
- return buf.toString();
- }
-
- /** Create a new execution process path based on the current time */
- public static String createExecutionProcessPath(Session session, String uuid) {
- Calendar now = new GregorianCalendar();
- return getSlcProcessesBasePath(session) + '/'
- + JcrUtils.dateAsPath(now, true) + uuid;
- }
-
- /** Get the base for the user processi. */
- public static String getSlcProcessesBasePath(Session session) {
- try {
- Node userHome = NodeUtils.getUserHome(session);
- if (userHome == null)
- throw new SlcException("No user home available for "
- + session.getUserID());
- return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
- + SlcNames.SLC_PROCESSES;
- } catch (RepositoryException re) {
- throw new SlcException(
- "Unexpected error while getting Slc Results Base Path.", re);
- }
- }
-
- /**
- * Create a new execution result path in the user home based on the current
- * time
- */
- public static String createResultPath(Session session, String uuid)
- throws RepositoryException {
- Calendar now = new GregorianCalendar();
- StringBuffer absPath = new StringBuffer(
- SlcJcrResultUtils.getSlcResultsBasePath(session) + '/');
- // Remove hours and add title property to the result process path on
- // request of O. Capillon
- // return getSlcProcessesBasePath(session) + '/'
- // + JcrUtils.dateAsPath(now, true) + uuid;
- String relPath = JcrUtils.dateAsPath(now, false);
- List<String> names = JcrUtils.tokenize(relPath);
- for (String name : names) {
- absPath.append(name + "/");
- Node node = JcrUtils.mkdirs(session, absPath.toString());
- try {
- node.addMixin(NodeType.MIX_TITLE);
- node.setProperty(Property.JCR_TITLE, name.substring(1));
- } catch (RepositoryException e) {
- throw new SlcException(
- "unable to create execution process path", e);
- }
- }
- return absPath.toString() + uuid;
- }
-
- /**
- * Set the value of the primitive accessor as a JCR property. Does nothing
- * if the value is null.
- */
- public static void setPrimitiveAsProperty(Node node, String propertyName,
- PrimitiveAccessor primitiveAccessor) {
- String type = primitiveAccessor.getType();
- Object value = primitiveAccessor.getValue();
- setPrimitiveAsProperty(node, propertyName, type, value);
- }
-
- /** Map a primitive value to JCR property value. */
- public static void setPrimitiveAsProperty(Node node, String propertyName,
- String type, Object value) {
- if (value == null)
- return;
- if (value instanceof CharSequence)
- value = PrimitiveUtils.convert(type,
- ((CharSequence) value).toString());
- if (value instanceof char[])
- value = new String((char[]) value);
-
- try {
- if (type.equals(PrimitiveAccessor.TYPE_STRING))
- node.setProperty(propertyName, value.toString());
- else if (type.equals(PrimitiveAccessor.TYPE_PASSWORD))
- node.setProperty(propertyName, value.toString());
- else if (type.equals(PrimitiveAccessor.TYPE_INTEGER))
- node.setProperty(propertyName, (long) ((Integer) value));
- else if (type.equals(PrimitiveAccessor.TYPE_LONG))
- node.setProperty(propertyName, ((Long) value));
- else if (type.equals(PrimitiveAccessor.TYPE_FLOAT))
- node.setProperty(propertyName, (double) ((Float) value));
- else if (type.equals(PrimitiveAccessor.TYPE_DOUBLE))
- node.setProperty(propertyName, ((Double) value));
- else if (type.equals(PrimitiveAccessor.TYPE_BOOLEAN))
- node.setProperty(propertyName, ((Boolean) value));
- else
- throw new SlcException("Unsupported type " + type);
- } catch (RepositoryException e) {
- throw new SlcException("Cannot set primitive of " + type
- + " as property " + propertyName + " on " + node, e);
- }
- }
-
- /** Aggregates the {@link TestStatus} of this sub-tree. */
- public static Integer aggregateTestStatus(Node node) {
- try {
- Integer status = TestStatus.PASSED;
- if (node.isNodeType(SlcTypes.SLC_CHECK))
- if (node.getProperty(SLC_SUCCESS).getBoolean())
- status = TestStatus.PASSED;
- else if (node.hasProperty(SLC_ERROR_MESSAGE))
- status = TestStatus.ERROR;
- else
- status = TestStatus.FAILED;
-
- NodeIterator it = node.getNodes();
- while (it.hasNext()) {
- Node curr = it.nextNode();
-
- // Manually skip aggregated status
- if (!SlcNames.SLC_AGGREGATED_STATUS.equals(curr.getName())) {
- Integer childStatus = aggregateTestStatus(curr);
- if (childStatus > status)
- status = childStatus;
- }
- }
- return status;
- } catch (Exception e) {
- throw new SlcException("Could not aggregate test status from "
- + node, e);
- }
- }
-
- /**
- * Aggregates the {@link TestStatus} of this sub-tree.
- *
- * @return the same {@link StringBuffer}, for convenience (typically calling
- * toString() on it)
- */
- public static StringBuffer aggregateTestMessages(Node node,
- StringBuffer messages) {
- try {
- if (node.isNodeType(SlcTypes.SLC_CHECK)) {
- if (node.hasProperty(SLC_MESSAGE)) {
- if (messages.length() > 0)
- messages.append('\n');
- messages.append(node.getProperty(SLC_MESSAGE).getString());
- }
- if (node.hasProperty(SLC_ERROR_MESSAGE)) {
- if (messages.length() > 0)
- messages.append('\n');
- messages.append(node.getProperty(SLC_ERROR_MESSAGE)
- .getString());
- }
- }
- NodeIterator it = node.getNodes();
- while (it.hasNext()) {
- Node child = it.nextNode();
- // Manually skip aggregated status
- if (!SlcNames.SLC_AGGREGATED_STATUS.equals(child.getName())) {
- aggregateTestMessages(child, messages);
- }
- }
- return messages;
- } catch (Exception e) {
- throw new SlcException("Could not aggregate test messages from "
- + node, e);
- }
- }
-
- /** Prevents instantiation */
- private SlcJcrUtils() {
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.jcr.execution;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.UUID;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.security.Privilege;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcConstants;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.execution.DefaultAgent;
-import org.argeo.slc.core.execution.ProcessThread;
-import org.argeo.slc.execution.ExecutionModulesManager;
-import org.argeo.slc.execution.ExecutionProcess;
-import org.argeo.slc.jcr.SlcJcrConstants;
-
-/** SLC VM agent synchronizing with a JCR repository. */
-public class JcrAgent extends DefaultAgent implements SlcNames {
- // final static String ROLE_REMOTE = "ROLE_REMOTE";
- final static String NODE_REPO_URI = "argeo.node.repo.uri";
-
- private Repository repository;
-
- private String agentNodeName = "default";
-
- /*
- * LIFECYCLE
- */
- protected String initAgentUuid() {
- Session session = null;
- try {
- session = repository.login();
-
- String agentFactoryPath = getAgentFactoryPath();
- Node vmAgentFactoryNode = JcrUtils.mkdirsSafe(session, agentFactoryPath, SlcTypes.SLC_AGENT_FACTORY);
- JcrUtils.addPrivilege(session, SlcJcrConstants.SLC_BASE_PATH, SlcConstants.ROLE_SLC, Privilege.JCR_ALL);
- if (!vmAgentFactoryNode.hasNode(agentNodeName)) {
- String uuid = UUID.randomUUID().toString();
- Node agentNode = vmAgentFactoryNode.addNode(agentNodeName, SlcTypes.SLC_AGENT);
- agentNode.setProperty(SLC_UUID, uuid);
- }
- session.save();
- return vmAgentFactoryNode.getNode(agentNodeName).getProperty(SLC_UUID).getString();
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot find JCR agent UUID", e);
- } finally {
- JcrUtils.logoutQuietly(session);
- }
- }
-
- @Override
- public void destroy() {
- super.destroy();
- }
-
- /*
- * SLC AGENT
- */
- @Override
- protected ProcessThread createProcessThread(ThreadGroup processesThreadGroup,
- ExecutionModulesManager modulesManager, ExecutionProcess process) {
- if (process instanceof JcrExecutionProcess)
- return new JcrProcessThread(processesThreadGroup, modulesManager, (JcrExecutionProcess) process);
- else
- return super.createProcessThread(processesThreadGroup, modulesManager, process);
- }
-
- /*
- * UTILITIES
- */
- public String getNodePath() {
- return getAgentFactoryPath() + '/' + getAgentNodeName();
- }
-
- public String getAgentFactoryPath() {
- try {
- Boolean isRemote = System.getProperty(NODE_REPO_URI) != null;
- String agentFactoryPath;
- if (isRemote) {
- InetAddress localhost = InetAddress.getLocalHost();
- agentFactoryPath = SlcJcrConstants.AGENTS_BASE_PATH + "/" + localhost.getCanonicalHostName();
-
- if (agentFactoryPath.equals(SlcJcrConstants.VM_AGENT_FACTORY_PATH))
- throw new SlcException("Unsupported hostname " + localhost.getCanonicalHostName());
- } else {// local
- agentFactoryPath = SlcJcrConstants.VM_AGENT_FACTORY_PATH;
- }
- return agentFactoryPath;
- } catch (UnknownHostException e) {
- throw new SlcException("Cannot find agent factory base path", e);
- }
- }
-
- /*
- * BEAN
- */
- public String getAgentNodeName() {
- return agentNodeName;
- }
-
- public void setRepository(Repository repository) {
- this.repository = repository;
- }
-
- public void setAgentNodeName(String agentNodeName) {
- this.agentNodeName = agentNodeName;
- }
-}
+++ /dev/null
-/*
- * 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.jcr.execution;
-
-import javax.jcr.Session;
-
-import org.argeo.slc.core.attachment.Attachment;
-import org.argeo.slc.core.attachment.AttachmentUploader;
-import org.springframework.core.io.Resource;
-
-/** JCR based attachment uploader */
-public class JcrAttachmentUploader implements AttachmentUploader {
- private Session session;
-
- public void upload(Attachment attachment, Resource resource) {
- session.toString();
- // not yet implemented, need to review the interface
- }
-
- public void setSession(Session session) {
- this.session = session;
- }
-
-}
+++ /dev/null
-/*
- * 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.jcr.execution;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
-import org.argeo.slc.core.execution.PrimitiveValue;
-import org.argeo.slc.core.execution.RefSpecAttribute;
-import org.argeo.slc.core.execution.RefValueChoice;
-import org.argeo.slc.deploy.ModuleDescriptor;
-import org.argeo.slc.execution.ExecutionFlowDescriptor;
-import org.argeo.slc.execution.ExecutionModuleDescriptor;
-import org.argeo.slc.execution.ExecutionModulesListener;
-import org.argeo.slc.execution.ExecutionModulesManager;
-import org.argeo.slc.execution.ExecutionSpec;
-import org.argeo.slc.execution.ExecutionSpecAttribute;
-import org.argeo.slc.jcr.SlcJcrUtils;
-
-/**
- * Synchronizes the local execution runtime with a JCR repository. For the time
- * being the state is completely reset from one start to another.
- */
-public class JcrExecutionModulesListener implements ExecutionModulesListener,
- SlcNames {
- private final static String SLC_EXECUTION_MODULES_PROPERTY = "slc.executionModules";
-
- private final static Log log = LogFactory
- .getLog(JcrExecutionModulesListener.class);
- private JcrAgent agent;
-
- private ExecutionModulesManager modulesManager;
-
- private Repository repository;
- /**
- * We don't use a thread bound session because many different threads will
- * call this critical component and we don't want to login each time. We
- * therefore rather protect access to this session via synchronized.
- */
- private Session session;
-
- /*
- * LIFECYCLE
- */
- public void init() {
- try {
- session = repository.login();
- clearAgent();
- if (modulesManager != null) {
- Node agentNode = session.getNode(agent.getNodePath());
-
- List<ModuleDescriptor> moduleDescriptors = modulesManager
- .listModules();
-
- // scan SLC-ExecutionModule metadata
- for (ModuleDescriptor md : moduleDescriptors) {
- if (md.getMetadata().containsKey(
- ExecutionModuleDescriptor.SLC_EXECUTION_MODULE)) {
- String moduleNodeName = SlcJcrUtils
- .getModuleNodeName(md);
- Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
- .getNode(moduleNodeName) : agentNode
- .addNode(moduleNodeName);
- moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
- moduleNode.setProperty(SLC_NAME, md.getName());
- moduleNode.setProperty(SLC_VERSION, md.getVersion());
- moduleNode.setProperty(Property.JCR_TITLE,
- md.getTitle());
- moduleNode.setProperty(Property.JCR_DESCRIPTION,
- md.getDescription());
- moduleNode.setProperty(SLC_STARTED, md.getStarted());
- }
- }
-
- // scan execution modules property
- String executionModules = System
- .getProperty(SLC_EXECUTION_MODULES_PROPERTY);
- if (executionModules != null) {
- for (String executionModule : executionModules.split(",")) {
- allModules: for (ModuleDescriptor md : moduleDescriptors) {
- String moduleNodeName = SlcJcrUtils
- .getModuleNodeName(md);
- if (md.getName().equals(executionModule)) {
- Node moduleNode = agentNode
- .hasNode(moduleNodeName) ? agentNode
- .getNode(moduleNodeName) : agentNode
- .addNode(moduleNodeName);
- moduleNode
- .addMixin(SlcTypes.SLC_EXECUTION_MODULE);
- moduleNode.setProperty(SLC_NAME, md.getName());
- moduleNode.setProperty(SLC_VERSION,
- md.getVersion());
- moduleNode.setProperty(Property.JCR_TITLE,
- md.getTitle());
- moduleNode.setProperty(
- Property.JCR_DESCRIPTION,
- md.getDescription());
- moduleNode.setProperty(SLC_STARTED,
- md.getStarted());
- break allModules;
- }
- }
- }
-
- // save if needed
- if (session.hasPendingChanges())
- session.save();
- }
- }
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- JcrUtils.logoutQuietly(session);
- throw new SlcException("Cannot initialize modules", e);
- }
- }
-
- public void destroy() {
- clearAgent();
- JcrUtils.logoutQuietly(session);
- }
-
- protected synchronized void clearAgent() {
- try {
- Node agentNode = session.getNode(agent.getNodePath());
- for (NodeIterator nit = agentNode.getNodes(); nit.hasNext();)
- nit.nextNode().remove();
- session.save();
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot clear agent " + agent, e);
- }
- }
-
- /*
- * EXECUTION MODULES LISTENER
- */
-
- public synchronized void executionModuleAdded(
- ModuleDescriptor moduleDescriptor) {
- syncExecutionModule(moduleDescriptor);
- }
-
- protected void syncExecutionModule(ModuleDescriptor moduleDescriptor) {
- try {
- Node agentNode = session.getNode(agent.getNodePath());
- String moduleNodeName = SlcJcrUtils
- .getModuleNodeName(moduleDescriptor);
- Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
- .getNode(moduleNodeName) : agentNode
- .addNode(moduleNodeName);
- moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
- moduleNode.setProperty(SLC_NAME, moduleDescriptor.getName());
- moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
- moduleNode.setProperty(Property.JCR_TITLE,
- moduleDescriptor.getTitle());
- moduleNode.setProperty(Property.JCR_DESCRIPTION,
- moduleDescriptor.getDescription());
- moduleNode.setProperty(SLC_STARTED, moduleDescriptor.getStarted());
- session.save();
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot sync module " + moduleDescriptor, e);
- }
- }
-
- public synchronized void executionModuleRemoved(
- ModuleDescriptor moduleDescriptor) {
- try {
- String moduleName = SlcJcrUtils.getModuleNodeName(moduleDescriptor);
- Node agentNode = session.getNode(agent.getNodePath());
- if (agentNode.hasNode(moduleName)) {
- Node moduleNode = agentNode.getNode(moduleName);
- for (NodeIterator nit = moduleNode.getNodes(); nit.hasNext();) {
- nit.nextNode().remove();
- }
- moduleNode.setProperty(SLC_STARTED, false);
- }
- session.save();
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot remove module " + moduleDescriptor,
- e);
- }
- }
-
- public synchronized void executionFlowAdded(ModuleDescriptor module,
- ExecutionFlowDescriptor efd) {
- try {
- Node agentNode = session.getNode(agent.getNodePath());
- Node moduleNode = agentNode.getNode(SlcJcrUtils
- .getModuleNodeName(module));
- String relativePath = getExecutionFlowRelativePath(efd);
- @SuppressWarnings("unused")
- Node flowNode = null;
- if (!moduleNode.hasNode(relativePath)) {
- flowNode = createExecutionFlowNode(moduleNode, relativePath,
- efd);
- session.save();
- } else {
- flowNode = moduleNode.getNode(relativePath);
- }
-
- if (log.isTraceEnabled())
- log.trace("Flow " + efd + " added to JCR");
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new SlcException("Cannot add flow " + efd + " from module "
- + module, e);
- }
-
- }
-
- protected Node createExecutionFlowNode(Node moduleNode,
- String relativePath, ExecutionFlowDescriptor efd)
- throws RepositoryException {
- Node flowNode = null;
- List<String> pathTokens = Arrays.asList(relativePath.split("/"));
-
- Iterator<String> names = pathTokens.iterator();
- // create intermediary paths
- Node currNode = moduleNode;
- while (names.hasNext()) {
- String name = names.next();
- if (currNode.hasNode(name))
- currNode = currNode.getNode(name);
- else {
- if (names.hasNext())
- currNode = currNode.addNode(name);
- else
- flowNode = currNode.addNode(name,
- SlcTypes.SLC_EXECUTION_FLOW);
- }
- }
-
- // name, description
- flowNode.setProperty(SLC_NAME, efd.getName());
- String endName = pathTokens.get(pathTokens.size() - 1);
- flowNode.setProperty(Property.JCR_TITLE, endName);
- if (efd.getDescription() != null
- && !efd.getDescription().trim().equals("")) {
- flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
- } else {
- flowNode.setProperty(Property.JCR_DESCRIPTION, endName);
- }
-
- // execution spec
- ExecutionSpec executionSpec = efd.getExecutionSpec();
- String esName = executionSpec.getName();
- if (esName == null || esName.equals(ExecutionSpec.INTERNAL_NAME)
- || esName.contains("#")/* automatically generated bean name */) {
- // internal spec node
- mapExecutionSpec(flowNode, executionSpec);
- } else {
- // reference spec node
- Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
- .getNode(SLC_EXECUTION_SPECS) : moduleNode
- .addNode(SLC_EXECUTION_SPECS);
- Node executionSpecNode = executionSpecsNode.addNode(esName,
- SlcTypes.SLC_EXECUTION_SPEC);
- executionSpecNode.setProperty(SLC_NAME, esName);
- executionSpecNode.setProperty(Property.JCR_TITLE, esName);
- if (executionSpec.getDescription() != null
- && !executionSpec.getDescription().trim().equals(""))
- executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
- executionSpec.getDescription());
- mapExecutionSpec(executionSpecNode, executionSpec);
- flowNode.setProperty(SLC_SPEC, executionSpecNode);
- }
-
- // flow values
- for (String attr : efd.getValues().keySet()) {
- ExecutionSpecAttribute esa = executionSpec.getAttributes()
- .get(attr);
- if (esa instanceof PrimitiveSpecAttribute) {
- PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
- // if spec reference there will be no node at this stage
- Node valueNode = JcrUtils.getOrAdd(flowNode, attr);
- valueNode.setProperty(SLC_TYPE, psa.getType());
- SlcJcrUtils.setPrimitiveAsProperty(valueNode, SLC_VALUE,
- (PrimitiveValue) efd.getValues().get(attr));
- }
- }
-
- return flowNode;
- }
-
- /**
- * Base can be either an execution spec node, or an execution flow node (in
- * case the execution spec is internal)
- */
- protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
- throws RepositoryException {
- for (String attrName : executionSpec.getAttributes().keySet()) {
- ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
- attrName);
- Node attrNode = baseNode.addNode(attrName);
- // booleans
- attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
- attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
- attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
- attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
-
- if (esa instanceof PrimitiveSpecAttribute) {
- attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
- PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
- SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
- attrNode.setProperty(SLC_TYPE, psa.getType());
- } else if (esa instanceof RefSpecAttribute) {
- attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
- RefSpecAttribute rsa = (RefSpecAttribute) esa;
- attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
- Object value = rsa.getValue();
- if (rsa.getChoices() != null) {
- Integer index = null;
- int count = 0;
- for (RefValueChoice choice : rsa.getChoices()) {
- String name = choice.getName();
- if (value != null && name.equals(value.toString()))
- index = count;
- Node choiceNode = attrNode.addNode(choice.getName());
- choiceNode.addMixin(NodeType.MIX_TITLE);
- choiceNode.setProperty(Property.JCR_TITLE,
- choice.getName());
- if (choice.getDescription() != null
- && !choice.getDescription().trim().equals(""))
- choiceNode.setProperty(Property.JCR_DESCRIPTION,
- choice.getDescription());
- count++;
- }
-
- if (index != null)
- attrNode.setProperty(SLC_VALUE, index);
- }
- }
- }
- }
-
- public synchronized void executionFlowRemoved(ModuleDescriptor module,
- ExecutionFlowDescriptor executionFlow) {
- try {
- Node agentNode = session.getNode(agent.getNodePath());
- Node moduleNode = agentNode.getNode(SlcJcrUtils
- .getModuleNodeName(module));
- String relativePath = getExecutionFlowRelativePath(executionFlow);
- if (moduleNode.hasNode(relativePath))
- moduleNode.getNode(relativePath).remove();
- agentNode.getSession().save();
- } catch (RepositoryException e) {
- throw new SlcException("Cannot remove flow " + executionFlow
- + " from module " + module, e);
- }
- }
-
- /*
- * UTILITIES
- */
- /** @return the relative path, never starts with '/' */
- @SuppressWarnings("deprecation")
- protected String getExecutionFlowRelativePath(
- ExecutionFlowDescriptor executionFlow) {
- String relativePath = executionFlow.getPath() == null ? executionFlow
- .getName() : executionFlow.getPath() + '/'
- + executionFlow.getName();
- // we assume that it is more than one char long
- if (relativePath.charAt(0) == '/')
- relativePath = relativePath.substring(1);
- // FIXME quick hack to avoid duplicate '/'
- relativePath = relativePath.replaceAll("//", "/");
- return relativePath;
- }
-
- /*
- * BEAN
- */
- public void setAgent(JcrAgent agent) {
- this.agent = agent;
- }
-
- public void setRepository(Repository repository) {
- this.repository = repository;
- }
-
- public void setModulesManager(ExecutionModulesManager modulesManager) {
- this.modulesManager = modulesManager;
- }
-
-}
+++ /dev/null
-/*
- * 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.jcr.execution;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.execution.ProcessThread;
-import org.argeo.slc.execution.ExecutionProcess;
-import org.argeo.slc.execution.ExecutionStep;
-import org.argeo.slc.execution.RealizedFlow;
-import org.argeo.slc.jcr.SlcJcrUtils;
-
-/** Execution process implementation based on a JCR node. */
-public class JcrExecutionProcess implements ExecutionProcess, SlcNames {
- private final static Log log = LogFactory.getLog(JcrExecutionProcess.class);
- private final Node node;
-
- private Long nextLogLine = 1l;
-
- public JcrExecutionProcess(Node node) {
- this.node = node;
- }
-
- public synchronized String getUuid() {
- try {
- return node.getProperty(SLC_UUID).getString();
- } catch (RepositoryException e) {
- throw new SlcException("Cannot get uuid for " + node, e);
- }
- }
-
- public synchronized String getStatus() {
- try {
- return node.getProperty(SLC_STATUS).getString();
- } catch (RepositoryException e) {
- log.error("Cannot get status: " + e);
- // we should re-throw exception because this information can
- // probably used for monitoring in case there are already unexpected
- // exceptions
- return UNKOWN;
- }
- }
-
- public synchronized void setStatus(String status) {
- try {
- node.setProperty(SLC_STATUS, status);
- // last modified properties needs to be manually updated
- // see https://issues.apache.org/jira/browse/JCR-2233
- JcrUtils.updateLastModified(node);
- node.getSession().save();
- } catch (RepositoryException e) {
- JcrUtils.discardUnderlyingSessionQuietly(node);
- // we should re-throw exception because this information can
- // probably used for monitoring in case there are already unexpected
- // exceptions
- log.error("Cannot set status " + status + ": " + e);
- }
- }
-
- /**
- * Synchronized in order to make sure that there is no concurrent
- * modification of {@link #nextLogLine}.
- */
- public synchronized void addSteps(List<ExecutionStep> steps) {
- try {
- steps: for (ExecutionStep step : steps) {
- String type;
- if (step.getType().equals(ExecutionStep.TRACE))
- type = SlcTypes.SLC_LOG_TRACE;
- else if (step.getType().equals(ExecutionStep.DEBUG))
- type = SlcTypes.SLC_LOG_DEBUG;
- else if (step.getType().equals(ExecutionStep.INFO))
- type = SlcTypes.SLC_LOG_INFO;
- else if (step.getType().equals(ExecutionStep.WARNING))
- type = SlcTypes.SLC_LOG_WARNING;
- else if (step.getType().equals(ExecutionStep.ERROR))
- type = SlcTypes.SLC_LOG_ERROR;
- else
- // skip
- continue steps;
-
- String relPath = SLC_LOG + '/'
- + step.getThread().replace('/', '_') + '/'
- + step.getLocation().replace('.', '/');
- String path = node.getPath() + '/' + relPath;
- // clean special character
- // TODO factorize in JcrUtils
- path = path.replace('@', '_');
-
- Node location = JcrUtils.mkdirs(node.getSession(), path);
- Node logEntry = location.addNode(Long.toString(nextLogLine),
- type);
- logEntry.setProperty(SLC_MESSAGE, step.getLog());
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(step.getTimestamp());
- logEntry.setProperty(SLC_TIMESTAMP, calendar);
-
- // System.out.println("Logged " + logEntry.getPath());
-
- nextLogLine++;
- }
-
- // last modified properties needs to be manually updated
- // see https://issues.apache.org/jira/browse/JCR-2233
- JcrUtils.updateLastModified(node);
-
- node.getSession().save();
- } catch (Exception e) {
- JcrUtils.discardUnderlyingSessionQuietly(node);
- e.printStackTrace();
- }
- }
-
- // public Node getNode() {
- // return node;
- // }
-
- public List<RealizedFlow> getRealizedFlows() {
- try {
- List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();
- Node rootRealizedFlowNode = node.getNode(SLC_FLOW);
- // we just manage one level for the time being
- NodeIterator nit = rootRealizedFlowNode.getNodes(SLC_FLOW);
- while (nit.hasNext()) {
- Node realizedFlowNode = nit.nextNode();
-
- if (realizedFlowNode.hasNode(SLC_ADDRESS)) {
- String flowPath = realizedFlowNode.getNode(SLC_ADDRESS)
- .getProperty(Property.JCR_PATH).getString();
- NameVersion moduleNameVersion = SlcJcrUtils
- .moduleNameVersion(flowPath);
- ((ProcessThread) Thread.currentThread())
- .getExecutionModulesManager().start(
- moduleNameVersion);
- }
-
- RealizedFlow realizedFlow = new JcrRealizedFlow(
- realizedFlowNode);
- if (realizedFlow != null)
- realizedFlows.add(realizedFlow);
- }
- return realizedFlows;
- } catch (RepositoryException e) {
- throw new SlcException("Cannot get realized flows", e);
- }
- }
-
- public String getNodePath() {
- try {
- return node.getPath();
- } catch (RepositoryException e) {
- throw new SlcException("Cannot get process node path for " + node,
- e);
- }
- }
-
- public Repository getRepository() {
- try {
- return node.getSession().getRepository();
- } catch (RepositoryException e) {
- throw new SlcException("Cannot get process JCR repository for "
- + node, e);
- }
- }
-}
+++ /dev/null
-/*
-
- * 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.jcr.execution;
-
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.core.execution.ProcessThread;
-import org.argeo.slc.execution.ExecutionModulesManager;
-import org.argeo.slc.execution.ExecutionProcess;
-import org.argeo.slc.execution.RealizedFlow;
-
-/** Where the actual execution takes place */
-public class JcrProcessThread extends ProcessThread implements SlcNames {
-
- public JcrProcessThread(ThreadGroup processesThreadGroup,
- ExecutionModulesManager executionModulesManager,
- JcrExecutionProcess process) {
- super(processesThreadGroup, executionModulesManager, process);
- }
-
- /** Overridden in order to set progress status on realized flow nodes. */
- @Override
- protected void process() throws InterruptedException {
- Session session = null;
- if (getProcess() instanceof JcrExecutionProcess)
- try {
- session = ((JcrExecutionProcess) getProcess()).getRepository()
- .login();
-
- List<RealizedFlow> realizedFlows = getProcess()
- .getRealizedFlows();
- for (RealizedFlow realizedFlow : realizedFlows) {
- Node realizedFlowNode = session
- .getNode(((JcrRealizedFlow) realizedFlow).getPath());
- setFlowStatus(realizedFlowNode, ExecutionProcess.RUNNING);
-
- try {
- //
- // EXECUTE THE FLOW
- //
- execute(realizedFlow, true);
-
- setFlowStatus(realizedFlowNode,
- ExecutionProcess.COMPLETED);
- } catch (RepositoryException e) {
- throw e;
- } catch (InterruptedException e) {
- setFlowStatus(realizedFlowNode, ExecutionProcess.KILLED);
- throw e;
- } catch (RuntimeException e) {
- setFlowStatus(realizedFlowNode, ExecutionProcess.ERROR);
- throw e;
- }
- }
- } catch (RepositoryException e) {
- throw new SlcException("Cannot process "
- + getJcrExecutionProcess().getNodePath(), e);
- } finally {
- JcrUtils.logoutQuietly(session);
- }
- else
- super.process();
- }
-
- protected void setFlowStatus(Node realizedFlowNode, String status)
- throws RepositoryException {
- realizedFlowNode.setProperty(SLC_STATUS, status);
- realizedFlowNode.getSession().save();
- }
-
- protected JcrExecutionProcess getJcrExecutionProcess() {
- return (JcrExecutionProcess) getProcess();
- }
-}
+++ /dev/null
-package org.argeo.slc.jcr.execution;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-
-import org.argeo.slc.SlcException;
-import org.argeo.slc.SlcNames;
-import org.argeo.slc.SlcTypes;
-import org.argeo.slc.core.execution.DefaultExecutionSpec;
-import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
-import org.argeo.slc.core.execution.PrimitiveUtils;
-import org.argeo.slc.core.execution.RefSpecAttribute;
-import org.argeo.slc.execution.ExecutionFlowDescriptor;
-import org.argeo.slc.execution.ExecutionSpecAttribute;
-import org.argeo.slc.execution.RealizedFlow;
-import org.argeo.slc.jcr.SlcJcrUtils;
-
-public class JcrRealizedFlow extends RealizedFlow implements SlcNames {
- private static final long serialVersionUID = -3709453850260712001L;
- private String path;
-
- public JcrRealizedFlow(Node node) {
- try {
- this.path = node.getPath();
- loadFromNode(node);
- } catch (RepositoryException e) {
- throw new SlcException("Cannot initialize from " + node, e);
- }
- }
-
- protected void loadFromNode(Node realizedFlowNode)
- throws RepositoryException {
- if (realizedFlowNode.hasNode(SLC_ADDRESS)) {
- String flowPath = realizedFlowNode.getNode(SLC_ADDRESS)
- .getProperty(Property.JCR_PATH).getString();
- // TODO: convert to local path if remote
- // FIXME start related module
- Node flowNode = realizedFlowNode.getSession().getNode(flowPath);
- String flowName = flowNode.getProperty(SLC_NAME).getString();
- String description = null;
- if (flowNode.hasProperty(Property.JCR_DESCRIPTION))
- description = flowNode.getProperty(Property.JCR_DESCRIPTION)
- .getString();
-
- Node executionModuleNode = flowNode.getSession().getNode(
- SlcJcrUtils.modulePath(flowPath));
- String executionModuleName = executionModuleNode.getProperty(
- SLC_NAME).getString();
- String executionModuleVersion = executionModuleNode.getProperty(
- SLC_VERSION).getString();
-
- RealizedFlow realizedFlow = this;
- realizedFlow.setModuleName(executionModuleName);
- realizedFlow.setModuleVersion(executionModuleVersion);
-
- // retrieve execution spec
- DefaultExecutionSpec executionSpec = new DefaultExecutionSpec();
- Map<String, ExecutionSpecAttribute> attrs = readExecutionSpecAttributes(realizedFlowNode);
- executionSpec.setAttributes(attrs);
-
- // set execution spec name
- if (flowNode.hasProperty(SlcNames.SLC_SPEC)) {
- Node executionSpecNode = flowNode.getProperty(SLC_SPEC)
- .getNode();
- executionSpec.setBeanName(executionSpecNode.getProperty(
- SLC_NAME).getString());
- }
-
- // explicitly retrieve values
- Map<String, Object> values = new HashMap<String, Object>();
- for (String attrName : attrs.keySet()) {
- ExecutionSpecAttribute attr = attrs.get(attrName);
- Object value = attr.getValue();
- values.put(attrName, value);
- }
-
- ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(flowName,
- description, values, executionSpec);
- realizedFlow.setFlowDescriptor(efd);
- } else {
- throw new SlcException("Unsupported realized flow "
- + realizedFlowNode);
- }
- }
-
- protected Map<String, ExecutionSpecAttribute> readExecutionSpecAttributes(
- Node node) {
- try {
- Map<String, ExecutionSpecAttribute> attrs = new HashMap<String, ExecutionSpecAttribute>();
- for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
- Node specAttrNode = nit.nextNode();
- if (specAttrNode
- .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
- String type = specAttrNode.getProperty(SLC_TYPE)
- .getString();
- Object value = null;
- if (specAttrNode.hasProperty(SLC_VALUE)) {
- String valueStr = specAttrNode.getProperty(SLC_VALUE)
- .getString();
- value = PrimitiveUtils.convert(type, valueStr);
- }
- PrimitiveSpecAttribute specAttr = new PrimitiveSpecAttribute(
- type, value);
- attrs.put(specAttrNode.getName(), specAttr);
- } else if (specAttrNode
- .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
- if (!specAttrNode.hasProperty(SLC_VALUE)) {
- continue;
- }
- Integer value = (int) specAttrNode.getProperty(SLC_VALUE)
- .getLong();
- RefSpecAttribute specAttr = new RefSpecAttribute();
- NodeIterator children = specAttrNode.getNodes();
- int index = 0;
- String id = null;
- while (children.hasNext()) {
- Node child = children.nextNode();
- if (index == value)
- id = child.getName();
- index++;
- }
- specAttr.setValue(id);
- attrs.put(specAttrNode.getName(), specAttr);
- }
- // throw new SlcException("Unsupported spec attribute "
- // + specAttrNode);
- }
- return attrs;
- } catch (RepositoryException e) {
- throw new SlcException("Cannot read spec attributes from " + node,
- e);
- }
- }
-
- public String getPath() {
- return path;
- }
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-/** <b>Experimental</b> A structured set of OSGi bundles. */
-public interface BundleRegister {
- /**
- * @param pkg
- * the Java package
- * @param version
- * the version, can be only major.minor or null
- * @return the bundle providing this package or null if none was found
- */
- public String bundleProvidingPackage(String pkg, String version);
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.SlcException;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
-import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
-import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent;
-import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;
-import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent;
-import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
-import org.eclipse.gemini.blueprint.util.OsgiFilterUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.util.Assert;
-
-/** Wraps low-level access to a {@link BundleContext} */
-@SuppressWarnings("deprecation")
-public class BundlesManager implements BundleContextAware, FrameworkListener,
- InitializingBean, DisposableBean,
- OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {
- private final static Log log = LogFactory.getLog(BundlesManager.class);
-
- private BundleContext bundleContext;
-
- private Long defaultTimeout = 60 * 1000l;
- private Long pollingPeriod = 200l;
-
- // Refresh sync objects
- private final Object refreshedPackageSem = new Object();
- private Boolean packagesRefreshed = false;
-
- public BundlesManager() {
- }
-
- public BundlesManager(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- /**
- * Stop the module, update it, refresh it and restart it. All synchronously.
- */
- public void upgradeSynchronous(OsgiBundle osgiBundle) {
- try {
- Bundle bundle = findRelatedBundle(osgiBundle);
-
- long begin = System.currentTimeMillis();
-
- long bStop = begin;
- stopSynchronous(bundle);
-
- long bUpdate = System.currentTimeMillis();
- updateSynchronous(bundle);
-
- // Refresh in case there are fragments
- long bRefresh = System.currentTimeMillis();
- refreshSynchronous(bundle);
-
- long bStart = System.currentTimeMillis();
- startSynchronous(bundle);
-
- long aStart = System.currentTimeMillis();
- if (log.isTraceEnabled()) {
- log.debug("OSGi upgrade performed in " + (aStart - begin)
- + "ms for bundle " + osgiBundle);
- log.debug(" stop \t: " + (bUpdate - bStop) + "ms");
- log.debug(" update\t: " + (bRefresh - bUpdate) + "ms");
- log.debug(" refresh\t: " + (bStart - bRefresh) + "ms");
- log.debug(" start\t: " + (aStart - bStart) + "ms");
- log.debug(" TOTAL\t: " + (aStart - begin) + "ms");
- }
-
- long bAppContext = System.currentTimeMillis();
- String filter = "(Bundle-SymbolicName=" + bundle.getSymbolicName()
- + ")";
- // Wait for application context to be ready
- // TODO: use service tracker
- Collection<ServiceReference<ApplicationContext>> srs = getServiceRefSynchronous(
- ApplicationContext.class, filter);
- ServiceReference<ApplicationContext> sr = srs.iterator().next();
- long aAppContext = System.currentTimeMillis();
- long end = aAppContext;
-
- if (log.isTraceEnabled()) {
- log.debug("Application context refresh performed in "
- + (aAppContext - bAppContext) + "ms for bundle "
- + osgiBundle);
- }
-
- if (log.isDebugEnabled())
- log.debug("Bundle '" + bundle.getSymbolicName()
- + "' upgraded and ready " + " (upgrade performed in "
- + (end - begin) + "ms).");
-
- if (log.isTraceEnabled()) {
- ApplicationContext applicationContext = (ApplicationContext) bundleContext
- .getService(sr);
- int beanDefCount = applicationContext.getBeanDefinitionCount();
- log.debug(" " + beanDefCount + " beans in app context of "
- + bundle.getSymbolicName()
- + ", average init time per bean=" + (end - begin)
- / beanDefCount + "ms");
- }
-
- bundleContext.ungetService(sr);
-
- } catch (Exception e) {
- throw new SlcException("Cannot update bundle " + osgiBundle, e);
- }
- }
-
- /** Updates bundle synchronously. */
- protected void updateSynchronous(Bundle bundle) throws BundleException {
- bundle.update();
- boolean waiting = true;
-
- long begin = System.currentTimeMillis();
- do {
- int state = bundle.getState();
- if (state == Bundle.INSTALLED || state == Bundle.ACTIVE
- || state == Bundle.RESOLVED)
- waiting = false;
-
- sleepWhenPolling();
- checkTimeout(begin, "Update of bundle " + bundle.getSymbolicName()
- + " timed out. Bundle state = " + bundle.getState());
- } while (waiting);
-
- if (log.isTraceEnabled())
- log.debug("Bundle " + bundle.getSymbolicName() + " updated.");
- }
-
- /** Starts bundle synchronously. Does nothing if already started. */
- protected void startSynchronous(Bundle bundle) throws BundleException {
- int originalState = bundle.getState();
- if (originalState == Bundle.ACTIVE)
- return;
-
- bundle.start();
- boolean waiting = true;
-
- long begin = System.currentTimeMillis();
- do {
- if (bundle.getState() == Bundle.ACTIVE)
- waiting = false;
-
- sleepWhenPolling();
- checkTimeout(begin, "Start of bundle " + bundle.getSymbolicName()
- + " timed out. Bundle state = " + bundle.getState());
- } while (waiting);
-
- if (log.isTraceEnabled())
- log.debug("Bundle " + bundle.getSymbolicName() + " started.");
- }
-
- /** Stops bundle synchronously. Does nothing if already started. */
- protected void stopSynchronous(Bundle bundle) throws BundleException {
- int originalState = bundle.getState();
- if (originalState != Bundle.ACTIVE)
- return;
-
- bundle.stop();
- boolean waiting = true;
-
- long begin = System.currentTimeMillis();
- do {
- if (bundle.getState() != Bundle.ACTIVE
- && bundle.getState() != Bundle.STOPPING)
- waiting = false;
-
- sleepWhenPolling();
- checkTimeout(begin, "Stop of bundle " + bundle.getSymbolicName()
- + " timed out. Bundle state = " + bundle.getState());
- } while (waiting);
-
- if (log.isTraceEnabled())
- log.debug("Bundle " + bundle.getSymbolicName() + " stopped.");
- }
-
- /** Refresh bundle synchronously. Does nothing if already started. */
- protected void refreshSynchronous(Bundle bundle) throws BundleException {
- ServiceReference<PackageAdmin> packageAdminRef = bundleContext
- .getServiceReference(PackageAdmin.class);
- PackageAdmin packageAdmin = (PackageAdmin) bundleContext
- .getService(packageAdminRef);
- Bundle[] bundles = { bundle };
-
- long begin = System.currentTimeMillis();
- synchronized (refreshedPackageSem) {
- packagesRefreshed = false;
- packageAdmin.refreshPackages(bundles);
- try {
- refreshedPackageSem.wait(defaultTimeout);
- } catch (InterruptedException e) {
- // silent
- }
- if (!packagesRefreshed) {
- long now = System.currentTimeMillis();
- throw new SlcException("Packages not refreshed after "
- + (now - begin) + "ms");
- } else {
- packagesRefreshed = false;
- }
- }
-
- if (log.isTraceEnabled())
- log.debug("Bundle " + bundle.getSymbolicName() + " refreshed.");
- }
-
- public void frameworkEvent(FrameworkEvent event) {
- if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
- synchronized (refreshedPackageSem) {
- packagesRefreshed = true;
- refreshedPackageSem.notifyAll();
- }
- }
- }
-
- public <S> Collection<ServiceReference<S>> getServiceRefSynchronous(
- Class<S> clss, String filter) throws InvalidSyntaxException {
- if (log.isTraceEnabled())
- log.debug("Filter: '" + filter + "'");
- Collection<ServiceReference<S>> sfs = null;
- boolean waiting = true;
- long begin = System.currentTimeMillis();
- do {
- sfs = bundleContext.getServiceReferences(clss, filter);
-
- if (sfs != null)
- waiting = false;
-
- sleepWhenPolling();
- checkTimeout(begin, "Search of services " + clss + " with filter "
- + filter + " timed out.");
- } while (waiting);
-
- return sfs;
- }
-
- protected void checkTimeout(long begin, String msg) {
- long now = System.currentTimeMillis();
- if (now - begin > defaultTimeout)
- throw new SlcException(msg + " (timeout after " + (now - begin)
- + "ms)");
-
- }
-
- protected void sleepWhenPolling() {
- try {
- Thread.sleep(pollingPeriod);
- } catch (InterruptedException e) {
- throw new SlcException("Polling interrupted");
- }
- }
-
- /** Creates and open a new service tracker. */
- public <S> ServiceTracker<S, S> newTracker(Class<S> clss) {
- ServiceTracker<S, S> st = new ServiceTracker<S, S>(bundleContext, clss,
- null);
- st.open();
- return st;
- }
-
- public <T> T getSingleService(Class<T> clss, String filter,
- Boolean synchronous) {
- if (filter != null)
- Assert.isTrue(OsgiFilterUtils.isValidFilter(filter), "valid filter");
- Collection<ServiceReference<T>> sfs;
- try {
- if (synchronous)
- sfs = getServiceRefSynchronous(clss, filter);
- else
- sfs = bundleContext.getServiceReferences(clss, filter);
- } catch (InvalidSyntaxException e) {
- throw new SlcException("Cannot retrieve service reference for "
- + filter, e);
- }
-
- if (sfs == null || sfs.size() == 0)
- return null;
- else if (sfs.size() > 1)
- throw new SlcException("More than one execution flow found for "
- + filter);
- return (T) bundleContext.getService(sfs.iterator().next());
- }
-
- public <T> T getSingleServiceStrict(Class<T> clss, String filter,
- Boolean synchronous) {
- T service = getSingleService(clss, filter, synchronous);
- if (service == null)
- throw new SlcException("No execution flow found for " + filter);
- else
- return service;
- }
-
- public OsgiBundle findRelatedBundle(String moduleName, String moduleVersion) {
- OsgiBundle osgiBundle = new OsgiBundle(moduleName, moduleVersion);
- if (osgiBundle.getVersion() == null) {
- Bundle bundle = findRelatedBundle(osgiBundle);
- osgiBundle = new OsgiBundle(bundle);
- }
- return osgiBundle;
- }
-
- /**
- * @param osgiBundle
- * cannot be null
- * @return the related bundle or null if not found
- * @throws SlcException
- * if osgiBundle argument is null
- */
- public Bundle findRelatedBundle(OsgiBundle osgiBundle) {
- if (osgiBundle == null)
- throw new SlcException("OSGi bundle cannot be null");
-
- Bundle bundle = null;
- if (osgiBundle.getInternalBundleId() != null) {
- bundle = bundleContext.getBundle(osgiBundle.getInternalBundleId());
- Assert.isTrue(
- osgiBundle.getName().equals(bundle.getSymbolicName()),
- "symbolic name consistent");
- if (osgiBundle.getVersion() != null)
- Assert.isTrue(
- osgiBundle.getVersion().equals(
- bundle.getHeaders().get(
- Constants.BUNDLE_VERSION)),
- "version consistent");
- } else if (osgiBundle.getVersion() == null
- || osgiBundle.getVersion().equals("0.0.0")) {
- bundle = OsgiBundleUtils.findBundleBySymbolicName(bundleContext,
- osgiBundle.getName());
- } else {// scan all bundles
- bundles: for (Bundle b : bundleContext.getBundles()) {
- if (b.getSymbolicName() == null) {
- log.warn("Bundle " + b + " has no symbolic name defined.");
- continue bundles;
- }
-
- if (b.getSymbolicName().equals(osgiBundle.getName())) {
- if (osgiBundle.getVersion() == null) {
- bundle = b;
- break bundles;
- }
-
- if (b.getHeaders().get(Constants.BUNDLE_VERSION)
- .equals(osgiBundle.getVersion())) {
- bundle = b;
- osgiBundle.setInternalBundleId(b.getBundleId());
- break bundles;
- }
- }
- }
- }
- return bundle;
- }
-
- /** Find a single bundle based on a symbolic name pattern. */
- public OsgiBundle findFromPattern(String pattern) {
- OsgiBundle osgiBundle = null;
- for (Bundle b : bundleContext.getBundles()) {
- if (b.getSymbolicName().contains(pattern)) {
- osgiBundle = new OsgiBundle(b);
- break;
- }
- }
- return osgiBundle;
- }
-
- public OsgiBundle getBundle(Long bundleId) {
- Bundle bundle = bundleContext.getBundle(bundleId);
- return new OsgiBundle(bundle);
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- public void afterPropertiesSet() throws Exception {
- bundleContext.addFrameworkListener(this);
- }
-
- public void destroy() throws Exception {
- bundleContext.removeFrameworkListener(this);
- }
-
- public void setDefaultTimeout(Long defaultTimeout) {
- this.defaultTimeout = defaultTimeout;
- }
-
- /**
- * Use with caution since it may interfer with some cached information
- * within this object
- */
- public BundleContext getBundleContext() {
- return bundleContext;
- }
-
- public void setPollingPeriod(Long pollingPeriod) {
- this.pollingPeriod = pollingPeriod;
- }
-
- public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
- if (event instanceof OsgiBundleContextRefreshedEvent) {
- log.debug("App context refreshed: " + event);
- } else if (event instanceof OsgiBundleContextFailedEvent) {
- log.debug("App context failed: " + event);
- }
- if (event instanceof OsgiBundleContextClosedEvent) {
- log.debug("App context closed: " + event);
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.osgi.framework.Constants;
-
-/** <b>Experimental</b> */
-public class FileSystemBundleRegister implements BundleRegister {
- private final static Log log = LogFactory
- .getLog(FileSystemBundleRegister.class);
- private Properties packagesBundles = null;
-
- public String bundleProvidingPackage(String pkg, String version) {
- if (packagesBundles == null)
- return null;
- return packagesBundles.getProperty(pkg);
- }
-
- protected void scan(File baseDirectory) {
- long begin = System.currentTimeMillis();
- int bundleCount = 0;
- int packageCount = 0;
-
- packagesBundles = new Properties();
-
- File[] files = baseDirectory.listFiles();
- for (File file : files) {
- if (file.isDirectory()) {
-
- } else {
- JarFile jarFile = null;
- try {
- jarFile = new JarFile(file);
- Manifest manifest = jarFile.getManifest();
- String symbolicName = manifest.getMainAttributes()
- .getValue(Constants.BUNDLE_SYMBOLICNAME);
- String exportPackage = manifest.getMainAttributes()
- .getValue(Constants.EXPORT_PACKAGE);
-
- // List exported packages
- Set<String> exportedPackages = exportPackageToPackageNames(exportPackage);
-
- for (String exportedPackage : exportedPackages) {
- packagesBundles.put(exportedPackage, symbolicName);
- packageCount++;
- if (log.isTraceEnabled())
- log.trace("Register " + exportedPackage + "="
- + symbolicName);
- }
- bundleCount++;
- } catch (Exception e) {
- log.warn("Cannot scan " + file, e);
- if (log.isTraceEnabled())
- e.printStackTrace();
- } finally {
- IOUtils.closeQuietly(jarFile);
- }
- }
- }
- if (log.isDebugEnabled())
- log.debug("Scanned " + bundleCount + " bundles with "
- + packageCount + " packages in "
- + (System.currentTimeMillis() - begin) + " ms");
- }
-
- protected Set<String> exportPackageToPackageNames(String exportPackage) {
- Set<String> exportedPackages = new HashSet<String>();
- if (exportPackage == null)
- return exportedPackages;
- char[] arr = exportPackage.toCharArray();
-
- StringBuffer currentPkg = new StringBuffer("");
- boolean skip = false;
- boolean inQuote = false;
- for (char c : arr) {
- if (c == ' ' || c == '\n') {
- // ignore
- } else if (c == ';') {
- if (!skip)
- skip = true;
- } else if (c == ',') {
- if (skip && !inQuote) {
- skip = false;
- // add new package
- exportedPackages.add(currentPkg.toString());
- currentPkg = new StringBuffer("");
- }
- } else if (c == '\"') {
- inQuote = inQuote ? false : true;
- } else {
- if (!skip)
- currentPkg.append(c);
- }
- }
-
- return exportedPackages;
- }
-
- public static void main(String[] args) {
- FileSystemBundleRegister fsbr = new FileSystemBundleRegister();
- fsbr.scan(new File(
- "/home/mbaudier/dev/src/slc/dist/org.argeo.slc.sdk/target/lib"));
-
- }
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.core.Ordered;
-
-/** Publishes beans of the application context as OSGi services. */
-@SuppressWarnings(value = { "unchecked", "rawtypes" })
-public class MultipleServiceExporterPostProcessor implements
- ApplicationListener, Ordered {
- private final static Log log = LogFactory
- .getLog(MultipleServiceExporterPostProcessor.class);
-
- private List<Class> interfaces = new ArrayList<Class>();
-
- private int order = Ordered.LOWEST_PRECEDENCE;
-
- private BundleContext bundleContext = null;
-
- // private Class osgiServiceFactoryClass = OsgiServiceFactoryBean.class;
- // private Boolean useServiceProviderContextClassLoader = false;
-
- public void onApplicationEvent(ApplicationEvent event) {
- Map<String, Object> beans = new HashMap<String, Object>();
- if (event instanceof ContextRefreshedEvent) {
- if (bundleContext != null) {
- for (Class clss : interfaces) {
- ApplicationContext ac = ((ContextRefreshedEvent) event)
- .getApplicationContext();
- beans.putAll(ac.getBeansOfType(clss, false, false));
- }
-
- int count = 0;
- for (String beanName : beans.keySet()) {
- Object bean = beans.get(beanName);
- List<String> classes = new ArrayList<String>();
- for (Class clss : interfaces) {
- if (clss.isAssignableFrom(bean.getClass())) {
- classes.add(clss.getName());
- }
- }
- Properties props = new Properties();
- Bundle bundle = bundleContext.getBundle();
- props.put(Constants.BUNDLE_SYMBOLICNAME,
- bundle.getSymbolicName());
- props.put(Constants.BUNDLE_VERSION, bundle.getVersion());
- // retrocompatibility with pre-1.0:
- props.put("org.eclipse.gemini.blueprint.bean.name", beanName);
- bundleContext.registerService(
- classes.toArray(new String[classes.size()]), bean,
- new Hashtable(props));
- count++;
- }
- if (log.isTraceEnabled())
- log.trace("Published " + count + " " + interfaces
- + " as OSGi services from bundle "
- + bundleContext.getBundle().getSymbolicName() + " "
- + bundleContext.getBundle().getVersion());
- // note: the services will be automatically unregistered when
- // the bundle will be stopped
- }
- }
- }
-
- // public void postProcessBeanFactory(
- // ConfigurableListableBeanFactory beanFactory) throws BeansException {
- // if (!(beanFactory instanceof BeanDefinitionRegistry)) {
- // throw new SlcException("Can only work on "
- // + BeanDefinitionRegistry.class);
- // }
- //
- // long begin = System.currentTimeMillis();
- //
- // // Merge all beans implementing these interfaces
- // Set<String> beanNames = new HashSet<String>();
- // for (Class clss : interfaces) {
- // String[] strs = beanFactory.getBeanNamesForType(clss, true, false);
- // beanNames.addAll(Arrays.asList(strs));
- // }
- //
- // // Register service factory beans for them
- // for (String beanName : beanNames) {
- // MutablePropertyValues mpv = new MutablePropertyValues();
- // mpv.addPropertyValue("interfaces", interfaces.toArray());
- // mpv.addPropertyValue("targetBeanName", beanName);
- // if (useServiceProviderContextClassLoader)
- // mpv.addPropertyValue("contextClassLoader",
- // ExportContextClassLoader.SERVICE_PROVIDER);
- // RootBeanDefinition bd = new RootBeanDefinition(
- // osgiServiceFactoryClass, mpv);
- //
- // String exporterBeanName = "osgiService." + beanName;
- // if (log.isTraceEnabled())
- // log.debug("Registering OSGi service exporter "
- // + exporterBeanName);
- // ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(
- // exporterBeanName, bd);
- // }
- //
- // long end = System.currentTimeMillis();
- // if (log.isTraceEnabled())
- // log.debug("Multiple services exported in " + (end - begin)
- // + " ms in bundle.");
- //
- // }
-
- public void setInterfaces(List<Class> interfaces) {
- this.interfaces = interfaces;
- }
-
- // public void setOsgiServiceFactoryClass(Class osgiServiceFactoryClass) {
- // this.osgiServiceFactoryClass = osgiServiceFactoryClass;
- // }
-
- public int getOrder() {
- return order;
- }
-
- public void setOrder(int order) {
- this.order = order;
- }
-
- // public void setUseServiceProviderContextClassLoader(
- // Boolean useServiceProviderContextClassLoader) {
- // this.useServiceProviderContextClassLoader =
- // useServiceProviderContextClassLoader;
- // }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import org.argeo.slc.DefaultNameVersion;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.build.Distribution;
-import org.argeo.slc.core.build.ResourceDistribution;
-import org.argeo.slc.deploy.DeploymentData;
-import org.argeo.slc.deploy.Module;
-import org.argeo.slc.deploy.ModuleDescriptor;
-import org.argeo.slc.deploy.TargetData;
-import org.argeo.slc.execution.RealizedFlow;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.springframework.core.io.Resource;
-
-/** A deployed OSGi bundle. */
-public class OsgiBundle extends DefaultNameVersion implements Module {
- private ResourceDistribution distribution;
-
- private Long internalBundleId;
-
- private String title;
- private String description;
-
- public OsgiBundle() {
-
- }
-
- public OsgiBundle(String name, String version) {
- super(name, version);
- }
-
- public OsgiBundle(NameVersion nameVersion) {
- super(nameVersion);
- }
-
- public OsgiBundle(Bundle bundle) {
- super(bundle.getSymbolicName(), getVersionSafe(bundle));
- internalBundleId = bundle.getBundleId();
- }
-
- /**
- * Initialize from a {@link RealizedFlow}.
- *
- * @deprecated introduce an unnecessary dependency. TODO: create a separate
- * helper.
- */
- public OsgiBundle(RealizedFlow realizedFlow) {
- super(realizedFlow.getModuleName(), realizedFlow.getModuleVersion());
- }
-
- /** Utility to avoid NPE. */
- private static String getVersionSafe(Bundle bundle) {
- Object versionObj = bundle.getHeaders().get(Constants.BUNDLE_VERSION);
- if (versionObj != null)
- return versionObj.toString();
- else
- return null;
- }
-
- /** Unique deployed system id. TODO: use internal bundle id when available? */
- public String getDeployedSystemId() {
- return getName() + ":" + getVersion();
- }
-
- /**
- * OSGi bundle are self-contained and do not require additional deployment
- * data.
- *
- * @return always null
- */
- public DeploymentData getDeploymentData() {
- return null;
- }
-
- /** The related distribution. */
- public Distribution getDistribution() {
- return distribution;
- }
-
- /**
- * The related distribution, a jar file with OSGi metadata referenced by a
- * {@link Resource}.
- */
- public ResourceDistribution getResourceDistribution() {
- return distribution;
- }
-
- /** TODO: reference the {@link OsgiRuntime} as target data? */
- public TargetData getTargetData() {
- throw new UnsupportedOperationException();
- }
-
- public void setResourceDistribution(ResourceDistribution distribution) {
- this.distribution = distribution;
- }
-
- /**
- * Bundle ID used by the OSGi runtime. To be used for optimization when
- * looking in the bundle context. Can therefore be null.
- */
- public Long getInternalBundleId() {
- return internalBundleId;
- }
-
- /** Only package access for the time being. e.g. from {@link BundlesManager} */
- void setInternalBundleId(Long internalBundleId) {
- this.internalBundleId = internalBundleId;
- }
-
- /** Value of the <code>Bundle-Name</code> directive. */
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String label) {
- this.title = label;
- }
-
- /** Value of the <code>Bundle-Description</code> directive. */
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public ModuleDescriptor getModuleDescriptor() {
- ModuleDescriptor moduleDescriptor = new ModuleDescriptor();
- moduleDescriptor.setName(getName());
- moduleDescriptor.setVersion(getVersion());
- moduleDescriptor.setDescription(description);
- moduleDescriptor.setTitle(title);
- return moduleDescriptor;
- }
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.core.execution.AbstractSpringExecutionModule;
-import org.argeo.slc.execution.ExecutionContext;
-
-@Deprecated
-public class OsgiExecutionModule extends AbstractSpringExecutionModule {
- private final static Log log = LogFactory.getLog(OsgiExecutionModule.class);
-
- public OsgiExecutionModule() {
- log.error("######## ERROR - DEPRECATED APPROACH USED ########");
- log.error(OsgiExecutionModule.class.getName() + " is deprecated. ");
- log
- .error("It will be removed in the next release. Remove its bean definition.");
- log
- .error("And replace: <service interface=\"org.argeo.slc.execution.ExecutionModule\" ref=\"executionModule\" />");
- log
- .error("by: <beans:import resource=\"classpath:org/argeo/slc/osgi/execution/spring.xml\" /> ");
- log.error("in osgi.xml.\n\n");
- }
-
- public void setExecutionContext(ExecutionContext executionContext) {
- // do nothing, just for compatibility
- }
-
- /*
- * private BundleContext bundleContext;
- *
- * @Override public void execute(ExecutionFlowDescriptor
- * executionFlowDescriptor) { if (descriptorConverter != null)
- * executionContext.addVariables(descriptorConverter
- * .convertValues(executionFlowDescriptor));
- *
- * ExecutionFlow flow = findExecutionFlow(getName(), getVersion(),
- * executionFlowDescriptor.getName()); flow.run(); }
- *
- * @Override protected Map<String, ExecutionFlow> listFlows() { String
- * filter = "(org.argeo.slc.execution.module.name=" + getName() + ")";
- * ServiceReference[] sfs; try { sfs =
- * bundleContext.getServiceReferences(ExecutionFlow.class .getName(),
- * filter); } catch (InvalidSyntaxException e) { throw new SlcException(
- * "Cannot retrieve service reference for flow " + filter, e); }
- *
- * Map<String, ExecutionFlow> flows = new HashMap<String, ExecutionFlow>();
- * for (ServiceReference sf : sfs) { ExecutionFlow flow = (ExecutionFlow)
- * bundleContext.getService(sf); flows.put(flow.getName(), flow); } return
- * flows; }
- *
- * public String getName() { return
- * bundleContext.getBundle().getSymbolicName(); }
- *
- * public String getVersion() { return
- * bundleContext.getBundle().getHeaders().get("Bundle-Version") .toString();
- * }
- *
- * public void setBundleContext(BundleContext bundleContext) {
- * this.bundleContext = bundleContext; }
- *
- * protected ExecutionFlow findExecutionFlow(String moduleName, String
- * moduleVersion, String flowName) { String filter =
- * "(&(org.argeo.slc.execution.module.name=" + moduleName +
- * ")(org.argeo.slc.execution.flow.name=" + flowName + "))";
- * log.debug("OSGi filter: " + filter);
- *
- * Assert.isTrue(OsgiFilterUtils.isValidFilter(filter), "valid filter");
- * ServiceReference[] sfs; try { sfs =
- * bundleContext.getServiceReferences(ExecutionFlow.class .getName(),
- * filter); } catch (InvalidSyntaxException e) { throw new
- * SlcException("Cannot retrieve service reference for " + filter, e); }
- *
- * if (sfs == null || sfs.length == 0) throw new
- * SlcException("No execution flow found for " + filter); else if
- * (sfs.length > 1) throw new
- * SlcException("More than one execution flow found for " + filter); return
- * (ExecutionFlow) bundleContext.getService(sfs[0]); }
- */
-
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.lang.management.ManagementFactory;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.management.StandardMBean;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.DefaultNameVersion;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.core.execution.AbstractExecutionModulesManager;
-import org.argeo.slc.core.execution.DefaultExecutionFlowDescriptorConverter;
-import org.argeo.slc.deploy.Module;
-import org.argeo.slc.deploy.ModuleDescriptor;
-import org.argeo.slc.execution.ExecutionContext;
-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.ExecutionModulesListener;
-import org.argeo.slc.execution.RealizedFlow;
-import org.eclipse.gemini.blueprint.service.importer.OsgiServiceLifecycleListener;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.Constants;
-import org.osgi.framework.launch.Framework;
-import org.springframework.context.ApplicationContext;
-
-/** Execution modules manager implementation based on an OSGi runtime. */
-public class OsgiExecutionModulesManager extends
- AbstractExecutionModulesManager implements
- OsgiServiceLifecycleListener, BundleListener {
-
- private final static Log log = LogFactory
- .getLog(OsgiExecutionModulesManager.class);
-
- private BundlesManager bundlesManager;
- private Map<OsgiBundle, ExecutionContext> executionContexts = new HashMap<OsgiBundle, ExecutionContext>();
- private Map<OsgiBundle, ExecutionFlowDescriptorConverter> executionFlowDescriptorConverters = new HashMap<OsgiBundle, ExecutionFlowDescriptorConverter>();
- private Map<OsgiBundle, Set<ExecutionFlow>> executionFlows = new HashMap<OsgiBundle, Set<ExecutionFlow>>();
- private ExecutionFlowDescriptorConverter defaultDescriptorConverter = new DefaultExecutionFlowDescriptorConverter();
-
- private List<ExecutionModulesListener> executionModulesListeners = new ArrayList<ExecutionModulesListener>();
-
- private Boolean registerFlowsToJmx = false;
-
- public void init() throws Exception {
- bundlesManager.getBundleContext().addBundleListener(this);
-
- final String module = System.getProperty(UNIQUE_LAUNCH_MODULE_PROPERTY);
- final String flow = System.getProperty(UNIQUE_LAUNCH_FLOW_PROPERTY);
- if (module != null) {
- // launch a flow and stops
- new Thread("Unique Flow") {
- @Override
- public void run() {
- executeFlowAndExit(module, null, flow);
- }
- }.start();
- }
- }
-
- public void destroy() {
- bundlesManager.getBundleContext().removeBundleListener(this);
- }
-
- /** Executes a single flow and <b>stops the JVM</b> */
- protected void executeFlowAndExit(final String module,
- final String version, final String flow) {
- if (log.isDebugEnabled())
- log.debug("Launch unique flow " + flow + " from module " + module);
- try {
- OsgiBundle osgiBundle = bundlesManager.findFromPattern(module);
- if (osgiBundle == null)
- throw new SlcException("No OSGi bundle found for " + module);
- // Bundle moduleBundle =
- // bundlesManager.findRelatedBundle(osgiBundle);
- start(osgiBundle);
-
- RealizedFlow lastLaunch = findRealizedFlow(module, flow);
- if (lastLaunch == null)
- throw new SlcException("Cannot find launch for " + module + " "
- + flow);
- execute(lastLaunch);
- } catch (Exception e) {
- log.error(
- "Error in unique flow " + flow + " from module " + module,
- e);
- } finally {
- if (log.isDebugEnabled())
- log.debug("Shutdown OSGi runtime...");
- Framework framework = (Framework) bundlesManager.getBundleContext()
- .getBundle(0);
- try {
- // shutdown framework
- framework.stop();
- // wait 1 min for shutdown
- framework.waitForStop(60 * 1000);
- // close VM
- System.exit(0);
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
- }
- }
-
- // public void startExectionModule(String moduleName, String moduleVersion)
- // {
- // try {
- // ServiceReference[] sr = bundlesManager.getServiceRefSynchronous(
- // ApplicationContext.class.getName(),
- // "org.springframework.context.service.name=" + moduleName);
- // // bundlesManager.startSynchronous(moduleBundle);
- // if (sr == null || sr.length == 0)
- // throw new SlcException(
- // "Cannot find execution module application context "
- // + moduleName);
- // } catch (InvalidSyntaxException e) {
- // throw new SlcException("Cannot start exeuction module "
- // + moduleName, e);
- // }
- // }
-
- public synchronized ExecutionModuleDescriptor getExecutionModuleDescriptor(
- String moduleName, String version) {
- ExecutionModuleDescriptor md = new ExecutionModuleDescriptor();
- OsgiBundle osgiBundle = null;
- DefaultNameVersion nameVersion = new DefaultNameVersion(moduleName,
- version);
- bundles: for (Iterator<OsgiBundle> iterator = executionContexts
- .keySet().iterator(); iterator.hasNext();) {
- OsgiBundle ob = iterator.next();
- if (nameVersion.getVersion() != null) {
- if (ob.equals(nameVersion)) {
- osgiBundle = ob;
- break bundles;
- }
- } else {
- if (ob.getName().equals(nameVersion.getName())) {
- osgiBundle = ob;
- break bundles;
- }
- }
- }
- if (osgiBundle == null)
- throw new SlcException("No execution module registered for "
- + nameVersion);
- md.setName(osgiBundle.getName());
- md.setVersion(osgiBundle.getVersion());
- md.setTitle(osgiBundle.getTitle());
- md.setDescription(osgiBundle.getDescription());
-
- ExecutionFlowDescriptorConverter executionFlowDescriptorConverter = getExecutionFlowDescriptorConverter(
- moduleName, version);
- if (executionFlowDescriptorConverter == null)
- throw new SlcException("No flow converter found.");
- executionFlowDescriptorConverter.addFlowsToDescriptor(md,
- listFlows(moduleName, version));
- return md;
- }
-
- public synchronized List<ExecutionModuleDescriptor> listExecutionModules() {
- List<ExecutionModuleDescriptor> descriptors = new ArrayList<ExecutionModuleDescriptor>();
-
- for (Iterator<OsgiBundle> iterator = executionContexts.keySet()
- .iterator(); iterator.hasNext();) {
- OsgiBundle osgiBundle = iterator.next();
- ExecutionModuleDescriptor md = new ExecutionModuleDescriptor();
- setMetadataFromBundle(md,
- bundlesManager.findRelatedBundle(osgiBundle));
- descriptors.add(md);
- }
- return descriptors;
- }
-
- protected synchronized Map<String, ExecutionFlow> listFlows(
- String moduleName, String moduleVersion) {
-
- Map<String, ExecutionFlow> flows = new HashMap<String, ExecutionFlow>();
- OsgiBundle key = bundlesManager.findRelatedBundle(moduleName,
- moduleVersion);
- if (!executionFlows.containsKey(key))
- return flows;
- Set<ExecutionFlow> flowsT = executionFlows.get(key);
- for (ExecutionFlow flow : flowsT)
- flows.put(flow.getName(), flow);
- return flows;
- }
-
- protected ExecutionFlow findExecutionFlow(String moduleName,
- String moduleVersion, String flowName) {
- String filter = moduleVersion == null || moduleVersion.equals("0.0.0") ? "(&(Bundle-SymbolicName="
- + moduleName
- + ")(org.eclipse.gemini.blueprint.bean.name="
- + flowName + "))"
- : "(&(Bundle-SymbolicName=" + moduleName + ")(Bundle-Version="
- + moduleVersion
- + ")(org.eclipse.gemini.blueprint.bean.name="
- + flowName + "))";
- return bundlesManager.getSingleServiceStrict(ExecutionFlow.class,
- filter, true);
- }
-
- protected ExecutionContext findExecutionContext(String moduleName,
- String moduleVersion) {
- String filter = moduleFilter(moduleName, moduleVersion);
- return bundlesManager.getSingleServiceStrict(ExecutionContext.class,
- filter, true);
- }
-
- protected ExecutionFlowDescriptorConverter findExecutionFlowDescriptorConverter(
- String moduleName, String moduleVersion) {
- String filter = moduleFilter(moduleName, moduleVersion);
- return bundlesManager.getSingleService(
- ExecutionFlowDescriptorConverter.class, filter, false);
- }
-
- /** Only based on symbolic name if version is null or "0.0.0" */
- protected String moduleFilter(String moduleName, String moduleVersion) {
- return moduleVersion == null || moduleVersion.equals("0.0.0") ? "(Bundle-SymbolicName="
- + moduleName + ")"
- : "(&(Bundle-SymbolicName=" + moduleName + ")(Bundle-Version="
- + moduleVersion + "))";
-
- }
-
- /**
- * Builds a minimal realized flow, based on the provided information
- * (typically from the command line).
- *
- * @param module
- * a bundle id, or a pattern contained in a bundle symbolic name
- * @param module
- * the execution flow name
- * @return a minimal realized flow, to be used in an execution
- */
- public RealizedFlow findRealizedFlow(String module, String executionName) {
- // First check whether we have a bundleId
- Long bundleId = null;
- try {
- bundleId = Long.parseLong(module);
- } catch (NumberFormatException e) {
- // silent
- }
-
- // Look for bundle names containing pattern
- OsgiBundle bundle = null;
- if (bundleId != null) {
- bundle = bundlesManager.getBundle(bundleId);
- } else {
- bundle = bundlesManager.findFromPattern(module);
- }
-
- if (bundle != null) {
- RealizedFlow launch = new RealizedFlow();
- launch.setModuleName(bundle.getName());
- launch.setModuleVersion(bundle.getVersion());
- ExecutionFlowDescriptor descriptor = new ExecutionFlowDescriptor();
- descriptor.setName(executionName);
- launch.setFlowDescriptor(descriptor);
- return launch;
- } else {
- log.warn("Could not find any execution module matching these requirements.");
- return null;
- }
- }
-
- public void upgrade(NameVersion nameVersion) {
- OsgiBundle osgiBundle = new OsgiBundle(nameVersion);
- bundlesManager.upgradeSynchronous(osgiBundle);
- }
-
- protected synchronized ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter(
- String moduleName, String moduleVersion) {
- return findExecutionFlowDescriptorConverter(moduleName, moduleVersion);
- // OsgiBundle osgiBundle = new OsgiBundle(moduleName, moduleVersion);
- // return getExecutionFlowDescriptorConverter(osgiBundle);
- }
-
- protected synchronized ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter(
- OsgiBundle osgiBundle) {
- if (executionFlowDescriptorConverters.containsKey(osgiBundle))
- return executionFlowDescriptorConverters.get(osgiBundle);
- else
- return defaultDescriptorConverter;
- }
-
- public ModuleDescriptor getModuleDescriptor(String moduleName,
- String version) {
- return getExecutionModuleDescriptor(moduleName, version);
- }
-
- public List<ModuleDescriptor> listModules() {
- Bundle[] bundles = bundlesManager.getBundleContext().getBundles();
- List<ModuleDescriptor> lst = new ArrayList<ModuleDescriptor>();
- for (Bundle bundle : bundles) {
- ModuleDescriptor moduleDescriptor = new ModuleDescriptor();
- setMetadataFromBundle(moduleDescriptor, bundle);
- lst.add(moduleDescriptor);
- }
- return lst;
- }
-
- public void start(NameVersion nameVersion) {
- try {
- Bundle bundle = bundlesManager.findRelatedBundle(new OsgiBundle(
- nameVersion));
- if (bundle == null)
- throw new SlcException("Could not find bundle for "
- + nameVersion);
-
- bundlesManager.startSynchronous(bundle);
- if (isSpringInstrumented(bundle)) {
- // Wait for Spring application context to be ready
- String filter = "(Bundle-SymbolicName="
- + bundle.getSymbolicName() + ")";
- try {
- bundlesManager.getServiceRefSynchronous(
- ApplicationContext.class, filter);
- } catch (Exception e) {
- // stop if application context not found
- bundle.stop();
- throw e;
- }
- }
- } catch (Exception e) {
- throw new SlcException("Cannot start " + nameVersion, e);
- }
- }
-
- /** Do it calmly in order to avoid NPE */
- private Boolean isSpringInstrumented(Bundle bundle) {
- Dictionary<?, ?> headers = bundle.getHeaders();
- if (headers != null && headers.get("Spring-Context") != null)
- return true;
- Enumeration<?> springEntryPaths = bundle
- .getEntryPaths("/META-INF/spring");
- if (springEntryPaths != null && springEntryPaths.hasMoreElements())
- return true;
- return false;
- }
-
- public void stop(NameVersion nameVersion) {
- try {
- Bundle bundle = bundlesManager.findRelatedBundle(new OsgiBundle(
- nameVersion));
- bundlesManager.stopSynchronous(bundle);
- } catch (BundleException e) {
- throw new SlcException("Cannot stop " + nameVersion, e);
- }
- }
-
- protected void setMetadataFromBundle(ModuleDescriptor md, Bundle bundle) {
- Bundle bdl = bundle;
- if (bdl == null) {
- if (md.getName() == null || md.getVersion() == null)
- throw new SlcException("Name and version not available.");
-
- Bundle[] bundles = bundlesManager.getBundleContext().getBundles();
- for (Bundle b : bundles) {
- if (b.getSymbolicName().equals(md.getName())
- && md.getVersion().equals(
- getHeaderSafe(b, Constants.BUNDLE_VERSION))) {
- bdl = b;
- break;
- }
- }
-
- }
-
- if (bdl == null)
- throw new SlcException("Cannot find bundle.");
-
- md.setName(bdl.getSymbolicName());
- md.setVersion(getHeaderSafe(bdl, Constants.BUNDLE_VERSION));
- md.setTitle(getHeaderSafe(bdl, Constants.BUNDLE_NAME));
- md.setDescription(getHeaderSafe(bdl, Constants.BUNDLE_DESCRIPTION));
-
- // copy manifets header to meta data
- Dictionary<?, ?> headers = bundle.getHeaders();
- Enumeration<?> keys = headers.keys();
- while (keys.hasMoreElements()) {
- Object key = keys.nextElement();
- Object value = headers.get(key);
- if (value != null)
- md.getMetadata().put(key.toString(), value.toString());
- }
-
- // check if started
- if (bundle.getState() == Bundle.ACTIVE
- || bundle.getState() == Bundle.STARTING)
- md.setStarted(true);
- else
- md.setStarted(false);
- }
-
- private String getHeaderSafe(Bundle bundle, Object key) {
- Object obj = bundle.getHeaders().get(key);
- if (obj == null)
- return null;
- else
- return obj.toString();
- }
-
- /*
- * REGISTRATION
- */
-
- /** Registers an execution context. */
- public synchronized void register(ExecutionContext executionContext,
- Map<String, String> properties) {
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- Bundle bundle = bundlesManager.findRelatedBundle(osgiBundle);
- osgiBundle.setTitle(getHeaderSafe(bundle, Constants.BUNDLE_NAME));
- osgiBundle.setDescription(getHeaderSafe(bundle,
- Constants.BUNDLE_DESCRIPTION));
- executionContexts.put(osgiBundle, executionContext);
- if (log.isTraceEnabled())
- log.trace("Registered execution context from " + osgiBundle);
- // Notify
- ModuleDescriptor md = osgiBundle.getModuleDescriptor();
- md.setStarted(true);
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionModuleAdded(md);
- }
-
- /** Unregisters an execution context. */
- public synchronized void unregister(ExecutionContext executionContext,
- Map<String, String> properties) {
- // FIXME why are properties null?
- if (properties == null)
- return;
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- if (executionContexts.containsKey(osgiBundle)) {
- executionContexts.remove(osgiBundle);
- if (log.isTraceEnabled())
- log.trace("Removed execution context from " + osgiBundle);
- // Notify
- ModuleDescriptor md = osgiBundle.getModuleDescriptor();
- md.setStarted(false);
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionModuleRemoved(md);
- }
- }
-
- /** Registers an execution flow. */
- public synchronized void register(ExecutionFlow executionFlow,
- Map<String, String> properties) {
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- if (!executionFlows.containsKey(osgiBundle)) {
- executionFlows.put(osgiBundle, new HashSet<ExecutionFlow>());
- }
- executionFlows.get(osgiBundle).add(executionFlow);
- if (log.isTraceEnabled())
- log.trace("Registered " + executionFlow + " from " + osgiBundle);
-
- // notifications
- if (registerFlowsToJmx)
- registerMBean(osgiBundle, executionFlow);
- ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionFlowAdded(osgiBundle.getModuleDescriptor(),
- efdc.getExecutionFlowDescriptor(executionFlow));
- }
-
- /** Unregisters an execution flow. */
- public synchronized void unregister(ExecutionFlow executionFlow,
- Map<String, String> properties) {
- // FIXME why are properties null?
- if (properties == null)
- return;
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- if (executionFlows.containsKey(osgiBundle)) {
- Set<ExecutionFlow> flows = executionFlows.get(osgiBundle);
- flows.remove(executionFlow);
- if (log.isTraceEnabled())
- log.trace("Removed " + executionFlow + " from " + osgiBundle);
- if (flows.size() == 0) {
- executionFlows.remove(osgiBundle);
- if (log.isTraceEnabled())
- log.trace("Removed flows set from " + osgiBundle);
- }
-
- // notifications
- if (registerFlowsToJmx)
- unregisterMBean(osgiBundle, executionFlow);
- ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionFlowRemoved(osgiBundle.getModuleDescriptor(),
- efdc.getExecutionFlowDescriptor(executionFlow));
- }
- }
-
- /** Registers an execution module listener. */
- public synchronized void register(
- ExecutionModulesListener executionModulesListener,
- Map<String, String> properties) {
- // sync with current state
- for (OsgiBundle osgiBundle : executionContexts.keySet()) {
- executionModulesListener.executionModuleAdded(osgiBundle
- .getModuleDescriptor());
- }
- for (OsgiBundle osgiBundle : executionFlows.keySet()) {
- ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
- for (ExecutionFlow executionFlow : executionFlows.get(osgiBundle))
- executionModulesListener.executionFlowAdded(
- osgiBundle.getModuleDescriptor(),
- efdc.getExecutionFlowDescriptor(executionFlow));
- }
- executionModulesListeners.add(executionModulesListener);
- }
-
- /** Unregisters an execution module listener. */
- public synchronized void unregister(
- ExecutionModulesListener executionModulesListener,
- Map<String, String> properties) {
- executionModulesListeners.remove(executionModulesListener);
- }
-
- /*
- * INTERFACE IMPLEMENTATIONS
- */
-
- public void bundleChanged(BundleEvent evt) {
- Bundle bundle = evt.getBundle();
- if (bundle.getHeaders().get(
- ExecutionModuleDescriptor.SLC_EXECUTION_MODULE) != null) {
- OsgiBundle osgiBundle = new OsgiBundle(bundle);
- if (evt.getType() == BundleEvent.INSTALLED)
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionModuleAdded(osgiBundle
- .getModuleDescriptor());
- else if (evt.getType() == BundleEvent.UNINSTALLED)
- for (ExecutionModulesListener listener : executionModulesListeners)
- listener.executionModuleRemoved(osgiBundle
- .getModuleDescriptor());
- }
-
- }
-
- @SuppressWarnings({ "rawtypes" })
- public synchronized void bind(Object service, Map properties)
- throws Exception {
- if (service instanceof ExecutionFlowDescriptorConverter) {
- ExecutionFlowDescriptorConverter executionFlowDescriptorConverter = (ExecutionFlowDescriptorConverter) service;
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- executionFlowDescriptorConverters.put(osgiBundle,
- executionFlowDescriptorConverter);
- if (log.isTraceEnabled())
- log.debug("Registered execution flow descriptor converter from "
- + osgiBundle);
- } else {
- // ignore
- }
- }
-
- @SuppressWarnings("rawtypes")
- public synchronized void unbind(Object service, Map properties)
- throws Exception {
- if (service instanceof ExecutionFlowDescriptorConverter) {
- OsgiBundle osgiBundle = asOsgiBundle(properties);
- if (executionFlowDescriptorConverters.containsKey(osgiBundle)) {
- executionFlowDescriptorConverters.remove(osgiBundle);
- if (log.isTraceEnabled())
- log.debug("Removed execution flow descriptor converter from "
- + osgiBundle);
- }
- } else {
- // ignore
- }
- }
-
- /*
- * JMX
- */
- protected MBeanServer getMBeanServer() {
- return ManagementFactory.getPlatformMBeanServer();
- }
-
- public void registerMBean(Module module, ExecutionFlow executionFlow) {
- try {
- StandardMBean mbean = new StandardMBean(executionFlow,
- ExecutionFlow.class);
- getMBeanServer().registerMBean(mbean,
- flowMBeanName(module, executionFlow));
- } catch (Exception e) {
- String msg = "Cannot register execution flow " + executionFlow
- + " as mbean";
- throw new SlcException(msg, e);
- }
- }
-
- public void unregisterMBean(Module module, ExecutionFlow executionFlow) {
- try {
- getMBeanServer().unregisterMBean(
- flowMBeanName(module, executionFlow));
- } catch (Exception e) {
- String msg = "Cannot unregister execution flow " + executionFlow
- + " as mbean";
- throw new SlcException(msg, e);
- }
- }
-
- protected ObjectName flowMBeanName(Module module,
- ExecutionFlow executionFlow) {
- String executionModulesPrefix = "SLCExecutionModules";
- // String path = executionFlow.getPath();
- String name = executionFlow.getName();
- // if (path == null && name.indexOf('/') >= 0) {
- // path = name.substring(0, name.lastIndexOf('/'));
- // name = name.substring(name.lastIndexOf('/'));
- // }
-
- StringBuffer buf = new StringBuffer(executionModulesPrefix + ":"
- + "module=" + module.getName() + " [" + module.getVersion()
- + "],");
-
- // if (path != null && !path.equals("")) {
- // int depth = 0;
- // for (String token : path.split("/")) {
- // if (!token.equals("")) {
- // buf.append("path").append(depth).append('=');
- // // in order to have directories first
- // buf.append('/');
- // buf.append(token).append(',');
- // depth++;
- // }
- // }
- // }
- buf.append("name=").append(name);
- try {
- return new ObjectName(buf.toString());
- } catch (Exception e) {
- throw new SlcException("Cannot generate object name based on "
- + buf, e);
- }
- }
-
- /*
- * UTILITIES
- */
- @SuppressWarnings("rawtypes")
- private OsgiBundle asOsgiBundle(Map properties) {
- String bundleSymbolicName = checkAndGet(Constants.BUNDLE_SYMBOLICNAME,
- properties);
- String bundleVersion = checkAndGet(Constants.BUNDLE_VERSION, properties);
- return new OsgiBundle(bundleSymbolicName, bundleVersion);
- }
-
- @SuppressWarnings("rawtypes")
- private String checkAndGet(Object key, Map properties) {
- if (!properties.containsKey(key) || properties.get(key) == null)
- throw new SlcException(key + " not set in " + properties);
- else
- return properties.get(key).toString();
- }
-
- public void setBundlesManager(BundlesManager bundlesManager) {
- this.bundlesManager = bundlesManager;
- }
-
- public void setDefaultDescriptorConverter(
- ExecutionFlowDescriptorConverter defaultDescriptorConverter) {
- this.defaultDescriptorConverter = defaultDescriptorConverter;
- }
-
- public void setRegisterFlowsToJmx(Boolean registerFlowsToJmx) {
- this.registerFlowsToJmx = registerFlowsToJmx;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.core.execution.FileExecutionResources;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.eclipse.gemini.blueprint.io.OsgiBundleResource;
-import org.osgi.framework.BundleContext;
-import org.springframework.core.io.Resource;
-
-/** Write access to resources in an OSGi context */
-public class OsgiExecutionResources extends FileExecutionResources implements
- BundleContextAware {
- private final static Log log = LogFactory
- .getLog(OsgiExecutionResources.class);
-
- private BundleContext bundleContext;
-
- @Override
- protected File fileFromResource(Resource resource) {
- File file = super.fileFromResource(resource);
- if (file != null)
- return file;
-
- if (!(resource instanceof OsgiBundleResource))
- return null;
-
- OsgiBundleResource osgiBundleResource = (OsgiBundleResource) resource;
- try {
- return osgiBundleResource.getFile();
- } catch (IOException e) {
- if (log.isTraceEnabled())
- log.trace("Resource " + resource
- + " is not available on the file system: " + e);
- }
-
- // TODO: ability to access resources in other bundles
- String location = bundleContext.getBundle().getLocation();
- String base = null;
- if (location.startsWith("reference:file:"))
- base = location.substring("reference:file:".length());
- else if (location.startsWith("initial@reference:file:")) {
- // TODO: Equinox specific?
- String relPath = location.substring("initial@reference:file:"
- .length());
- // if (relPath.startsWith("../"))// relative to the framework jar
- // relPath = relPath.substring("../".length());
- // String framework =
- // System.getProperty("osgi.framework").substring(
- // "file:".length());
- // log.debug(framework);
- String installArea = System.getProperty("osgi.install.area")
- .substring("file:".length());
- // log.debug(installArea);
- base = installArea + '/' + relPath;
- // int sepIndex = framework.lastIndexOf(File.separatorChar);
- // framework = framework.substring(0, sepIndex);
- // base = framework + '/' + relPath;
- } else {
- return null;
- }
-
- String path = base + '/' + osgiBundleResource.getPathWithinContext();
- try {
- file = new File(path).getCanonicalFile();
- } catch (IOException e) {
- throw new SlcException("Cannot determine canonical path for "
- + path, e);
- }
-
- if (!file.exists())
- throw new SlcException(file
- + " was retrieved in bundle located at '" + location
- + "' for resource " + resource + " but it does not exist");
-
- if (log.isTraceEnabled())
- log.debug("OSGi local resource: " + file + " from " + resource);
- return file;
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.StreamReadable;
-import org.argeo.slc.UnsupportedException;
-import org.argeo.slc.build.Distribution;
-import org.argeo.slc.core.build.VersionedResourceDistribution;
-import org.argeo.slc.deploy.DeploymentData;
-import org.argeo.slc.deploy.DynamicRuntime;
-import org.argeo.slc.deploy.TargetData;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
-
-public class OsgiRuntime implements BundleContextAware, ResourceLoaderAware,
- DynamicRuntime<OsgiBundle> {
- private String uuid = UUID.randomUUID().toString();
- private BundleContext bundleContext;
- private ResourceLoader resourceLoader;
-
- public List<OsgiBundle> listModules() {
- List<OsgiBundle> modules = new ArrayList<OsgiBundle>();
- Bundle[] bundles = bundleContext.getBundles();
- for (Bundle bundle : bundles) {
- OsgiBundle osgiBundle = new OsgiBundle(bundle);
- modules.add(osgiBundle);
- String location = bundle.getLocation();
- if (location != null) {
- Resource resource = resourceLoader.getResource(location);
- osgiBundle
- .setResourceDistribution(new VersionedResourceDistribution(
- osgiBundle.getName(), osgiBundle.getVersion(),
- resource));
- }
- }
- return modules;
- }
-
- public OsgiBundle installModule(Distribution distribution) {
- if (!(distribution instanceof StreamReadable))
- throw new UnsupportedException("distribution", distribution);
-
- StreamReadable sr = (StreamReadable) distribution;
- Bundle bundle;
- try {
- bundle = bundleContext.installBundle(sr.toString(), sr
- .getInputStream());
- } catch (BundleException e) {
- throw new SlcException(
- "Cannot install OSGi bundle " + distribution, e);
- }
- return new OsgiBundle(bundle);
- }
-
- public void updateModule(NameVersion nameVersion) {
- Bundle bundle = findBundle(nameVersion);
- try {
- bundle.update();
- } catch (BundleException e) {
- throw new SlcException("Cannot update " + bundle, e);
- }
- }
-
- public void uninstallModule(NameVersion nameVersion) {
- Bundle bundle = findBundle(nameVersion);
- try {
- bundle.uninstall();
- } catch (BundleException e) {
- throw new SlcException("Cannot uninstall " + bundle, e);
- }
- }
-
- public void startModule(NameVersion nameVersion) {
- Bundle bundle = findBundle(nameVersion);
- try {
- bundle.start();
- // TODO: use bundle manager
- } catch (BundleException e) {
- throw new SlcException("Cannot uninstall " + bundle, e);
- }
- }
-
- protected Bundle findBundle(NameVersion nameVersion) {
- Bundle[] bundles = bundleContext.getBundles();
- for (Bundle bundle : bundles) {
- OsgiBundle osgiBundle = new OsgiBundle(bundle);
- if (osgiBundle.equals(nameVersion)) {
- return bundle;
- }
- }
- throw new SlcException("Could not find bundle " + nameVersion);
- }
-
- public void shutdown() {
- // FIXME use framework
- throw new UnsupportedException();
- }
-
- public String getDeployedSystemId() {
- return uuid;
- }
-
- public DeploymentData getDeploymentData() {
- throw new UnsupportedException();
- }
-
- public Distribution getDistribution() {
- throw new UnsupportedException();
- }
-
- public TargetData getTargetData() {
- throw new UnsupportedException();
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.DefaultNameVersion;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.UnsupportedException;
-import org.argeo.slc.build.Distribution;
-import org.argeo.slc.build.ModularDistribution;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.springframework.beans.factory.InitializingBean;
-
-public abstract class AbstractOsgiModularDistribution implements
- ModularDistribution, BundleContextAware, InitializingBean {
- private final static Log log = LogFactory
- .getLog(AbstractOsgiModularDistribution.class);
-
- private BundleContext bundleContext;
- private EclipseUpdateSite eclipseUpdateSite;
-
- /** Initialized by the object itself. */
- private SortedMap<NameVersion, Distribution> distributions = new TreeMap<NameVersion, Distribution>();
-
- protected abstract void fillDistributions(
- SortedMap<NameVersion, Distribution> distributions)
- throws Exception;
-
- public Distribution getModuleDistribution(String moduleName,
- String moduleVersion) {
- return distributions.get(new DefaultNameVersion(moduleName,
- moduleVersion));
- }
-
- public String getDistributionId() {
- return bundleContext.getBundle().getSymbolicName()
- + "-"
- + bundleContext.getBundle().getHeaders()
- .get(Constants.BUNDLE_VERSION);
- }
-
- public Set<NameVersion> listModulesNameVersions() {
- return distributions.keySet();
- }
-
- public Iterator<NameVersion> nameVersions() {
- return distributions.keySet().iterator();
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- public void afterPropertiesSet() throws Exception {
- fillDistributions(distributions);
- if (log.isDebugEnabled())
- log.debug("Distribution " + getName() + ":" + getVersion()
- + " loaded (" + distributions.size() + " modules)");
- }
-
- protected String findVersion(String name) {
- Set<String> versions = new HashSet<String>();
- for (NameVersion key : distributions.keySet()) {
- if (key.getName().equals(name))
- versions.add(key.getVersion());
- }
-
- if (versions.size() == 0)
- throw new SlcException("Cannot find version for name " + name);
- else if (versions.size() > 1)
- throw new SlcException("Found more than one version for name "
- + name + ": " + versions);
- else
- return versions.iterator().next();
-
- }
-
- public Object getModulesDescriptor(String descriptorType) {
- if (descriptorType.equals("eclipse"))
- return writeEclipseUpdateSite();
- else
- throw new UnsupportedException("descriptorType", descriptorType);
- }
-
- protected Set<NameVersion> writePlainUrlList() {
- return distributions.keySet();
- }
-
- protected String writeEclipseUpdateSite() {
- if (eclipseUpdateSite == null)
- throw new SlcException("No eclipse update site declared.");
-
- StringBuffer buf = new StringBuffer("");
- buf.append("<site>");
-
- List<EclipseUpdateSiteCategory> usedCategories = new ArrayList<EclipseUpdateSiteCategory>();
- for (EclipseUpdateSiteFeature feature : eclipseUpdateSite.getFeatures()) {
-
- String featureId = feature.getName();
- String featureVersion = findVersion(featureId);
- buf.append("<feature");
- buf.append(" url=\"features/").append(featureId).append('_')
- .append(featureVersion).append(".jar\"");
- buf.append(" id=\"").append(featureId).append("\"");
- buf.append(" version=\"").append(featureVersion).append("\"");
- buf.append(">\n");
-
- for (EclipseUpdateSiteCategory category : feature.getCategories()) {
- usedCategories.add(category);
- buf.append(" <category name=\"").append(category.getName())
- .append("\"/>\n");
- }
- buf.append("</feature>\n\n");
- }
-
- for (EclipseUpdateSiteCategory category : usedCategories) {
- buf.append("<category-def");
- buf.append(" name=\"").append(category.getName()).append("\"");
- buf.append(" label=\"").append(category.getLabel()).append("\"");
- buf.append(">\n");
- buf.append(" <description>").append(category.getDescription())
- .append("</description>\n");
- buf.append("</category-def>\n\n");
- }
-
- buf.append("</site>");
- return buf.toString();
- }
-
- public String getName() {
- return bundleContext.getBundle().getSymbolicName();
- }
-
- public String getVersion() {
- return bundleContext.getBundle().getHeaders()
- .get(Constants.BUNDLE_VERSION).toString();
- }
-
- @Override
- public String toString() {
- return new DefaultNameVersion(this).toString();
- }
-
- public void setEclipseUpdateSite(EclipseUpdateSite eclipseUpdateSite) {
- this.eclipseUpdateSite = eclipseUpdateSite;
- }
-
- public BundleContext getBundleContext() {
- return bundleContext;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.SortedMap;
-import java.util.StringTokenizer;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-
-import org.apache.commons.io.IOUtils;
-import org.argeo.slc.DefaultNameVersion;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.build.Distribution;
-import org.argeo.slc.core.build.VersionedResourceDistribution;
-import org.osgi.framework.Constants;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.core.io.ResourceLoader;
-
-public class BundleModularDistribution extends AbstractOsgiModularDistribution
- implements ResourceLoaderAware {
- private ResourceLoader resourceLoader;
-
- private String libDirectory = "/lib";
-
- protected void fillDistributions(
- SortedMap<NameVersion, Distribution> distributions)
- throws Exception {
- Enumeration<URL> urls = (Enumeration<URL>) getBundleContext()
- .getBundle().findEntries(libDirectory, "*.jar", false);
- while (urls.hasMoreElements()) {
- URL url = urls.nextElement();
- JarInputStream in = null;
- try {
- in = new JarInputStream(url.openStream());
- Manifest mf = in.getManifest();
- String name = mf.getMainAttributes().getValue(
- Constants.BUNDLE_SYMBOLICNAME);
- // Skip additional specs such as
- // ; singleton:=true
- if (name.indexOf(';') > -1) {
- name = new StringTokenizer(name, " ;").nextToken();
- }
-
- String version = mf.getMainAttributes().getValue(
- Constants.BUNDLE_VERSION);
- DefaultNameVersion nameVersion = new DefaultNameVersion(name,
- version);
- distributions.put(nameVersion,
- new VersionedResourceDistribution(name, version,
- resourceLoader.getResource(url.toString())));
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
- }
-
- public void setLibDirectory(String libDirectory) {
- this.libDirectory = libDirectory;
- }
-
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
-
- /*
- * @SuppressWarnings(value = { "unchecked" }) protected URL
- * findModule(String moduleName, String version) { Enumeration<URL> urls =
- * (Enumeration<URL>) bundleContext.getBundle() .findEntries(libDirectory,
- * moduleName + "*", false);
- *
- * if (!urls.hasMoreElements()) throw new SlcException("Cannot find module "
- * + moduleName);
- *
- * URL url = urls.nextElement();
- *
- * // TODO: check version as well if (urls.hasMoreElements()) throw new
- * SlcException("More than one module with name " + moduleName); return url;
- * }
- */
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EclipseUpdateSite {
- private List<EclipseUpdateSiteFeature> features = new ArrayList<EclipseUpdateSiteFeature>();
-
- public List<EclipseUpdateSiteFeature> getFeatures() {
- return features;
- }
-
- public void setFeatures(List<EclipseUpdateSiteFeature> features) {
- this.features = features;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-public class EclipseUpdateSiteCategory {
- private String name;
- private String label;
- private String description;
-
- public String getLabel() {
- return label;
- }
-
- public void setLabel(String label) {
- this.label = label;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EclipseUpdateSiteFeature {
- private String name;
- private List<EclipseUpdateSiteCategory> categories = new ArrayList<EclipseUpdateSiteCategory>();
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public List<EclipseUpdateSiteCategory> getCategories() {
- return categories;
- }
-
- public void setCategories(List<EclipseUpdateSiteCategory> categories) {
- this.categories = categories;
- }
-
-}
+++ /dev/null
-/*
- * 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.osgi.build;
-
-import java.net.URL;
-import java.util.SortedMap;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.NameVersion;
-import org.argeo.slc.build.Distribution;
-import org.argeo.slc.core.build.VersionedResourceDistribution;
-import org.argeo.slc.osgi.OsgiBundle;
-import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
-import org.osgi.framework.Bundle;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
-
-public class OsgiRuntimeModularDistribution extends
- AbstractOsgiModularDistribution implements ResourceLoaderAware {
- private final static Log log = LogFactory
- .getLog(OsgiRuntimeModularDistribution.class);
-
- private ResourceLoader resourceLoader;
-
- protected void fillDistributions(
- SortedMap<NameVersion, Distribution> distributions)
- throws Exception {
-
- String frameworkUrl = System.getProperty("osgi.framework");
- String frameworkBaseUrl = null;
- if (frameworkUrl != null)
- frameworkBaseUrl = frameworkUrl.substring(0, frameworkUrl
- .lastIndexOf('/'));
- bundles: for (Bundle bundle : getBundleContext().getBundles()) {
- OsgiBundle osgiBundle = new OsgiBundle(bundle);
-
- String originalLocation = bundle.getLocation();
-
- if (OsgiBundleUtils.isSystemBundle(bundle)) {
- continue bundles;
- }
-
- String location = originalLocation;
- if (originalLocation.startsWith("reference:file:"))
- location = originalLocation.substring("reference:".length());
-
- if (frameworkBaseUrl != null
- && originalLocation.startsWith("initial@reference:file:")) {
- location = frameworkBaseUrl
- + '/'
- + originalLocation.substring("initial@reference:file:"
- .length());
- }
-
- try {
- URL url = new URL(location);
- Resource res = resourceLoader.getResource(url.toString());
- distributions.put(osgiBundle,
- new VersionedResourceDistribution(osgiBundle, res));
-
- if (log.isTraceEnabled())
- log.debug("Added url " + url + " from original location "
- + originalLocation);
- } catch (Exception e) {
- log.warn("Cannot interpret location " + location
- + " of bundle " + bundle + ": " + e);
- }
- }
- }
-
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
-}
+++ /dev/null
-/*
- * 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.osgi.deploy;
-
-import org.argeo.slc.core.deploy.DefaultResourceSet;
-import org.eclipse.gemini.blueprint.context.BundleContextAware;
-import org.eclipse.gemini.blueprint.io.OsgiBundleResourceLoader;
-import org.eclipse.gemini.blueprint.io.OsgiBundleResourcePatternResolver;
-import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.springframework.core.io.ResourceLoader;
-
-/**
- * Retrieves ressources from an OSGi bundle either the active one or another one
- * referenced by its symbolic name.
- */
-public class OsgiResourceSet extends DefaultResourceSet implements
- BundleContextAware {
- private BundleContext bundleContext;
- private Bundle bundle = null;
- private String bundleSymbolicName = null;
-
- private OsgiBundleResourceLoader osgiBundleResourceLoader = null;
-
- @Override
- public void afterPropertiesSet() throws Exception {
- osgiBundleResourceLoader = new OsgiBundleResourceLoader(getBundle());
- if (getResourcePatternResolver() == null)
- setResourcePatternResolver(new OsgiBundleResourcePatternResolver(
- osgiBundleResourceLoader));
- super.afterPropertiesSet();
- }
-
- public Bundle getBundle() {
- if (bundle != null)
- return bundle;
- else if (bundleSymbolicName != null)// do not cache
- return OsgiBundleUtils.findBundleBySymbolicName(bundleContext,
- bundleSymbolicName);
- else
- // containing bundle
- return bundleContext.getBundle();
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- @Override
- public ResourceLoader getResourceLoaderToUse() {
- return osgiBundleResourceLoader;
- }
-
- public void setBundle(Bundle bundle) {
- this.bundle = bundle;
- }
-
- public void setBundleSymbolicName(String bundleSymbolicName) {
- this.bundleSymbolicName = bundleSymbolicName;
- }
-
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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. -->
-<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
-
-<beans xmlns:osgi="http://www.springframework.org/schema/osgi"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
- xsi:schemaLocation="http://www.springframework.org/schema/osgi
- http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <osgi:service interface="org.argeo.slc.execution.ExecutionContext"
- ref="executionContext" />
- <osgi:service
- interface="org.argeo.slc.execution.ExecutionFlowDescriptorConverter"
- ref="executionFlowDescriptorConverter" />
-
- <osgi:reference id="callbackHandler"
- interface="javax.security.auth.callback.CallbackHandler" cardinality="0..1" />
-
- <bean class="org.argeo.slc.osgi.MultipleServiceExporterPostProcessor">
- <property name="interfaces">
- <list>
- <value><![CDATA[org.argeo.slc.execution.ExecutionFlow]]></value>
- </list>
- </property>
- <property name="bundleContext" ref="bundleContext" />
- </bean>
-
- <bean id="osgiExecutionResources" class="org.argeo.slc.osgi.OsgiExecutionResources">
- <property name="executionContext" ref="executionContext" />
- </bean>
-</beans>
\ No newline at end of file
+++ /dev/null
-/*
- * 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.spring;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.node.NodeConstants;
-import org.argeo.slc.SlcException;
-
-/** Provides base method for executing code with system authorization. */
-abstract class AbstractSystemExecution {
- private final static Log log = LogFactory.getLog(AbstractSystemExecution.class);
- private final Subject subject = new Subject();
-
- /** Authenticate the calling thread */
- protected void authenticateAsSystem() {
- ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
- try {
- LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
- lc.login();
- } catch (LoginException e) {
- throw new SlcException("Cannot login as system", e);
- } finally {
- Thread.currentThread().setContextClassLoader(origClassLoader);
- }
- if (log.isTraceEnabled())
- log.trace("System authenticated");
- }
-
- protected void deauthenticateAsSystem() {
- ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
- try {
- LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
- lc.logout();
- } catch (LoginException e) {
- throw new SlcException("Cannot logout as system", e);
- } finally {
- Thread.currentThread().setContextClassLoader(origClassLoader);
- }
- }
-
- protected Subject getSubject() {
- return subject;
- }
-}
+++ /dev/null
-/*
- * 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.spring;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.security.auth.Subject;
-
-import org.eclipse.gemini.blueprint.context.DependencyInitializationAwareBeanPostProcessor;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.support.AbstractBeanFactory;
-import org.springframework.beans.factory.support.SecurityContextProvider;
-import org.springframework.beans.factory.support.SimpleSecurityContextProvider;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-
-/**
- * Executes with a system authentication the instantiation and initialization
- * methods of the application context where it has been defined.
- */
-public class AuthenticatedApplicationContextInitialization extends
- AbstractSystemExecution implements
- DependencyInitializationAwareBeanPostProcessor, ApplicationContextAware {
- /** If non empty, restricts to these beans */
- private List<String> beanNames = new ArrayList<String>();
-
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- if (beanNames.size() == 0 || beanNames.contains(beanName))
- authenticateAsSystem();
- return bean;
- }
-
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- if (beanNames.size() == 0 || beanNames.contains(beanName))
- deauthenticateAsSystem();
- return bean;
- }
-
- public void setBeanNames(List<String> beanNames) {
- this.beanNames = beanNames;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- if (applicationContext.getAutowireCapableBeanFactory() instanceof AbstractBeanFactory) {
- final AbstractBeanFactory beanFactory = ((AbstractBeanFactory) applicationContext
- .getAutowireCapableBeanFactory());
- // retrieve subject's access control context
- // and set it as the bean factory security context
- Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
- @Override
- public Void run() {
- SecurityContextProvider scp = new SimpleSecurityContextProvider(
- AccessController.getContext());
- beanFactory.setSecurityContextProvider(scp);
- return null;
- }
- });
- }
- }
-}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src"/>
+ <classpathentry kind="src" path="ext/test"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.slc.spring</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+http\://www.argeo.org/schema/slc-flow=org.argeo.slc.core.execution.xml.FlowNamespaceHandler
\ No newline at end of file
--- /dev/null
+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
--- /dev/null
+Import-Package: javax.jcr.nodetype,\
+javax.jcr.security,\
+org.apache.tools.ant.*;resolution:="optional",\
+junit.framework;resolution:="optional",\
+org.osgi.*;version=0.0.0,\
+*
--- /dev/null
+additional.bundles = org.springframework.context
+bin.includes = META-INF/,.
+source.. = src/
--- /dev/null
+# Set root logger level to DEBUG and its only appender to A1.\r
+log4j.rootLogger=WARN, console\r
+\r
+## Levels\r
+# Slc\r
+log4j.logger.org.argeo=DEBUG\r
+\r
+# Castor\r
+log4j.logger.org.exolab.castor=WARN\r
+\r
+# Spring\r
+log4j.logger.org.springframework=WARN\r
+\r
+\r
+## Appenders\r
+# A1 is set to be a ConsoleAppender.\r
+log4j.appender.console=org.apache.log4j.ConsoleAppender\r
+\r
+# A1 uses PatternLayout.\r
+log4j.appender.console.layout=org.apache.log4j.PatternLayout\r
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n\r
+\r
--- /dev/null
+/*
+ * 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<String, Resource> 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");
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+ <bean id="relativeResourceSet" class="org.argeo.slc.core.deploy.DefaultResourceSet">\r
+ <property name="base" value="classpath:/org/argeo/slc/core/deploy/data" />\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.test.SimpleTestResult;\r
+import org.argeo.slc.execution.ExecutionContext;\r
+import org.argeo.slc.execution.ExecutionFlow;\r
+import org.argeo.slc.test.TestResultPart;\r
+import org.argeo.slc.test.TestStatus;\r
+import org.springframework.context.ConfigurableApplicationContext;\r
+import org.springframework.context.support.ClassPathXmlApplicationContext;\r
+\r
+public abstract class AbstractExecutionFlowTestCase extends TestCase {\r
+\r
+ protected final Log log = LogFactory.getLog(getClass());\r
+\r
+ protected void logException(Throwable ex) {\r
+ log.info("Got Exception of class " + ex.getClass().toString()\r
+ + " with message '" + ex.getMessage() + "'.");\r
+ }\r
+\r
+ protected void validateTestResult(SimpleTestResult testResult) {\r
+ validateTestResult(testResult, TestStatus.PASSED);\r
+ }\r
+\r
+ protected void validateTestResult(SimpleTestResult testResult,\r
+ int expectedStatus) {\r
+ for (TestResultPart part : testResult.getParts()) {\r
+ if (part.getStatus() != expectedStatus) {\r
+ fail("Error found in TestResult: " + part.getMessage());\r
+ }\r
+ }\r
+ }\r
+\r
+ protected ConfigurableApplicationContext createApplicationContext(\r
+ String applicationContextSuffix) {\r
+ ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext(\r
+ inPackage(applicationContextSuffix));\r
+ // applicationContext.start();\r
+ return applicationContext;\r
+ }\r
+\r
+ protected void configureAndExecuteSlcFlow(String applicationContextSuffix,\r
+ String beanName) {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext(applicationContextSuffix);\r
+ ExecutionContext executionContext = (ExecutionContext) applicationContext\r
+ .getBean("executionContext");\r
+ ExecutionFlow executionFlow = (ExecutionFlow) applicationContext\r
+ .getBean(beanName);\r
+ if (executionFlow instanceof DefaultExecutionFlow)\r
+ ((DefaultExecutionFlow) executionFlow)\r
+ .setExecutionContext(executionContext);\r
+ try {\r
+ executionContext.beforeFlow(executionFlow);\r
+ executionFlow.run();\r
+ } finally {\r
+ executionContext.afterFlow(executionFlow);\r
+ }\r
+ applicationContext.close();\r
+ }\r
+\r
+ protected String inPackage(String suffix) {\r
+ String prefix = getClass().getPackage().getName().replace('.', '/');\r
+ return prefix + '/' + suffix;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution;\r
+\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.argeo.slc.core.test.SimpleTestResult;\r
+import org.argeo.slc.execution.ExecutionContext;\r
+import org.argeo.slc.execution.ExecutionFlow;\r
+import org.argeo.slc.test.TestStatus;\r
+import org.springframework.beans.factory.BeanCreationException;\r
+import org.springframework.context.ConfigurableApplicationContext;\r
+\r
+public class BasicExecutionFlowTest extends AbstractExecutionFlowTestCase {\r
+ // TO TEST\r
+ // - post-processing for @{} replacement in beans with complex properties\r
+ // - bean of scope other than execution are not resolved at execution\r
+\r
+ // public void testMyTest() throws Exception {\r
+ // ConfigurableApplicationContext applicationContext =\r
+ // createApplicationContext("test.xml");\r
+ // log.info("Start Execution");\r
+ // ((ExecutionFlow) applicationContext.getBean("flow1")).execute();\r
+ // applicationContext.close();\r
+ // }\r
+\r
+ public void testSpecOverriding() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("specOverriding.xml");\r
+ ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
+ SimpleTestResult res = (SimpleTestResult) applicationContext\r
+ .getBean("myTestResult");\r
+ validateTestResult(res);\r
+ }\r
+\r
+ public void testMultipleFlows() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("multipleFlow.xml");\r
+ ((ExecutionFlow) applicationContext.getBean("flow1")).run();\r
+ SimpleTestResult res = (SimpleTestResult) applicationContext\r
+ .getBean("myTestResult");\r
+ validateTestResult(res);\r
+ res.getParts().clear();\r
+ ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
+ validateTestResult(res, TestStatus.FAILED);\r
+ applicationContext.close();\r
+ }\r
+\r
+ /**\r
+ * Test placeholder resolution in a context without scope execution or proxy\r
+ * and with cascading flows (the flow A contains the flow B)\r
+ * \r
+ * @throws Exception\r
+ */\r
+ public void testPlaceHolders() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml");\r
+ ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
+ validateTestResult((SimpleTestResult) applicationContext\r
+ .getBean("myTestResult"));\r
+ applicationContext.close();\r
+ }\r
+\r
+ /**\r
+ * Test placeholder resolution in a context without scope execution or proxy\r
+ * and with cascading flows (the flow A contains the flow B) setting\r
+ * execution values (should have no effect)\r
+ * \r
+ * @throws Exception\r
+ */\r
+ public void testPlaceHoldersWithExecutionValues() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.xml");\r
+\r
+ ExecutionContext executionContext = (ExecutionContext) applicationContext\r
+ .getBean("executionContext");\r
+ Map<String, String> executionParameters = new HashMap<String, String>();\r
+ executionParameters.put("p1", "e1");\r
+ executionParameters.put("p2", "e2");\r
+ executionParameters.put("p3", "e3");\r
+ executionParameters.put("p4", "e4");\r
+ executionParameters.put("p5", "e5");\r
+ executionParameters.put("p6", "e6");\r
+ executionParameters.put("p7", "e7");\r
+ executionParameters.put("p8", "e8");\r
+ addVariables(executionContext, executionParameters);\r
+\r
+ ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
+ validateTestResult((SimpleTestResult) applicationContext\r
+ .getBean("myTestResult"));\r
+ applicationContext.close();\r
+ }\r
+\r
+ public void testPlaceHoldersExec() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("placeHolders.cascading.exec.xml");\r
+\r
+ ExecutionContext executionContext = (ExecutionContext) applicationContext\r
+ .getBean("executionContext");\r
+ Map<String, String> executionParameters = new HashMap<String, String>();\r
+ executionParameters.put("p1", "e1");\r
+ executionParameters.put("p2", "e2");\r
+ executionParameters.put("p3", "e3");\r
+ executionParameters.put("p4", "e4");\r
+ executionParameters.put("p5", "e5");\r
+ executionParameters.put("p6", "e6");\r
+ addVariables(executionContext, executionParameters);\r
+\r
+ ((ExecutionFlow) applicationContext.getBean("flowA")).run();\r
+ validateTestResult((SimpleTestResult) applicationContext\r
+ .getBean("myTestResult"));\r
+ applicationContext.close();\r
+ }\r
+\r
+ public void testCanonicFlowParameters() throws Exception {\r
+ configureAndExecuteSlcFlow("canonic-001.xml", "canonic.001");\r
+ }\r
+\r
+ public void testCanonicDefaultValues() throws Exception {\r
+ configureAndExecuteSlcFlow("canonic-002.xml", "canonic.002");\r
+ }\r
+\r
+ public void testCanonicMissingValues() throws Exception {\r
+ try {\r
+ configureAndExecuteSlcFlow("canonic-003.error.xml", "canonic.003");\r
+ fail("Parameter not set - should be rejected.");\r
+ } catch (BeanCreationException e) {\r
+ // exception expected\r
+ logException(e);\r
+ }\r
+ }\r
+\r
+ public void testCanonicUnknownParameter() throws Exception {\r
+ try {\r
+ configureAndExecuteSlcFlow("canonic-004.error.xml", "canonic.004");\r
+ fail("Unknown parameter set - should be rejected.");\r
+ } catch (BeanCreationException e) {\r
+ // exception expected\r
+ logException(e);\r
+ }\r
+ }\r
+\r
+ public void testListSetMap() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMap.xml");\r
+ ExecutionFlow executionFlow = (ExecutionFlow) applicationContext\r
+ .getBean("myFlow");\r
+ executionFlow.run();\r
+\r
+ validateTestResult((SimpleTestResult) applicationContext\r
+ .getBean("myTestResult"));\r
+\r
+ // BasicTestData res = (BasicTestData)\r
+ // applicationContext.getBean("cascadingComplex.testData");\r
+ // log.info("res=" + res.getReached().toString());\r
+\r
+ applicationContext.close();\r
+ }\r
+\r
+ public void testListSetMapMultipleFlows() throws Exception {\r
+ ConfigurableApplicationContext applicationContext = createApplicationContext("listSetMapMultipleFlow.xml");\r
+ ((ExecutionFlow) applicationContext.getBean("flow1")).run();\r
+ SimpleTestResult res = (SimpleTestResult) applicationContext\r
+ .getBean("myTestResult");\r
+ validateTestResult(res);\r
+ res.getParts().clear();\r
+ ((ExecutionFlow) applicationContext.getBean("flow2")).run();\r
+ validateTestResult(res, TestStatus.FAILED);\r
+ applicationContext.close();\r
+ }\r
+\r
+ protected void addVariables(ExecutionContext executionContext,\r
+ Map<String, String> vars) {\r
+ for (String key : vars.keySet())\r
+ executionContext.setVariable(key, vars.get(key));\r
+ }\r
+}\r
--- /dev/null
+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<URI> uris = DefaultAgentCli.asURIs(args);
+ assertEquals(1, uris.size());
+ assertEquals(
+ "flow:/org.argeo.slc.demo.minimal/HelloWorld/WithVar?testKey=555",
+ uris.get(0).toString());
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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));
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="executionModule_1" class="org.argeo.slc.core.execution.SimpleSpringExecutionModule" >\r
+ <property name="executionContext">\r
+ <ref bean="executionContext" />\r
+ </property> \r
+ <property name="name" value="dummyname" />\r
+ <property name="version" value="dummyversion" />\r
+ </bean>\r
+ \r
+ <bean id="main" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttr.primitive" p:value="660" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="echo1" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="echo1" parent="task.echo" scope="execution">\r
+ <property name="message"\r
+ value="From main! @{testKey}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="canonic.xml" />\r
+\r
+ <bean id="canonic.001" parent="canonic.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="parameterAtInstantiation" value="1" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="canonic.xml" />\r
+\r
+ <bean id="canonic.002" parent="canonic.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="parameterAtInstantiation" value="2" />\r
+ <entry key="displayWithoutControl" value="102" />\r
+ <entry key="displayWithControl" value="202" />\r
+ <entry key="hide" value="202" />\r
+ <entry key="notParameterAtInstantiation" value="202" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="canonic.xml" />\r
+\r
+ <bean id="canonic.003" parent="canonic.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <!-- missing parameter -->\r
+ <entry key="displayWithoutControl" value="102" />\r
+ <entry key="displayWithControl" value="202" />\r
+ <entry key="hide" value="202" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="canonic.xml" />\r
+\r
+ <bean id="canonic.004" parent="canonic.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="parameterAtInstantiation" value="2" />\r
+ <entry key="displayWithoutControl" value="102" />\r
+ <entry key="displayWithControl" value="202" />\r
+ <entry key="hide" value="202" />\r
+ <entry key="unknownParameter" value="1" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" />\r
+\r
+ <bean id="canonic.spec" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="parameterAtInstantiation">\r
+ <bean parent="specAttr.primitive" p:isParameter="true" p:type="integer" />\r
+ </entry>\r
+ <entry key="displayWithoutControl">\r
+ <bean parent="specAttr.primitive" p:value="100" p:isParameter="true"\r
+ p:isFrozen="true" p:type="integer" />\r
+ </entry>\r
+ <entry key="displayWithControl">\r
+ <bean parent="specAttr.primitive" p:value="200" p:isParameter="true"\r
+ p:isFrozen="false" p:type="integer" />\r
+ </entry>\r
+ <entry key="hide">\r
+ <bean parent="specAttr.primitive" p:value="300" p:isParameter="true"\r
+ p:isFrozen="false" p:isHidden="true" p:type="integer" />\r
+ </entry> \r
+ <entry key="notParameterAtInstantiation">\r
+ <bean parent="specAttr.primitive" p:value="400" p:isParameter="false"\r
+ p:isFrozen="false" p:isHidden="false" p:type="integer" />\r
+ </entry> \r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="canonic.flowTemplate" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <constructor-arg ref="canonic.spec" />\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo"\r
+ p:message="Canonical: displayWithControl=@{displayWithControl}, displayWithoutControl=@{displayWithoutControl}, hide=@{hide}">\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" />\r
+\r
+ <bean id="executionResources.spec" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="var">\r
+ <bean parent="specAttr.primitive" p:isParameter="false"\r
+ p:type="integer" p:value="60" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="executionResources.placeholderPass" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg ref="executionResources.spec" />\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="DATA" />\r
+ <property name="writeTo">\r
+ <bean parent="slcTemplate.resourcesFactoryBean" scope="execution">\r
+ <property name="executionResources" ref="executionResources" />\r
+ <property name="relativePath" value="subdir/@{var}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="executionResources.placeholderFail" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg ref="executionResources.spec" />\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="DATA" />\r
+ <property name="writeTo">\r
+ <bean factory-bean="executionResources" factory-method="getWritableResource"\r
+ scope="execution">\r
+ <constructor-arg value="subdir/@{var}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="executionResources.simple" parent="slcTemplate.simpleFlow">\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="DATA" />\r
+ <property name="writeTo">\r
+ <bean factory-bean="executionResources" factory-method="getWritableResource"\r
+ scope="execution">\r
+ <constructor-arg value="subdir/writeTo" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="executionResources" parent="slcTemplate.fileResources">\r
+ <property name="executionContext" ref="executionContext" />\r
+ <property name="withExecutionSubdirectory" value="false" />\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Copyright (C) 2007-2012 Mathieu Baudier 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. -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />
+ <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />
+
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="basic.testDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+\r
+ <bean id="myFlow" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttr.primitive" p:value="myValue" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="echo1" />\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingMap.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleList.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingList.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleSet.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingSet.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingListMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingSetMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingComplex.testData" />\r
+ </bean> \r
+ \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+\r
+ <bean id="simpleMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <map>\r
+ <entry key="key1" value="myValue_myValue" />\r
+ </map>\r
+ </property>\r
+ <property name="reached">\r
+ <map>\r
+ <entry key="key1" value="@{testKey}_@{testKey}" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="cascadingMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <map>\r
+ <entry key="key3">\r
+ <map>\r
+ <entry key="key2">\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map>\r
+ </entry>\r
+ <entry key="key2bis" value="myValue" />\r
+ </map>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ <property name="reached">\r
+ <map>\r
+ <entry key="key3">\r
+ <map>\r
+ <entry key="key2">\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map>\r
+ </entry>\r
+ <entry key="key2bis" value="@{testKey}" />\r
+ </map>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="simpleList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value> \r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ <value>myValue</value>\r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </list>\r
+ <value>@{testKey}</value>\r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="simpleSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </set>\r
+ <value>myValue</value>\r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </set>\r
+ <value>@{testKey}</value>\r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingListMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingSetMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingComplex.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ <set>\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ <list>\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ <value>myValue</value>\r
+ </list> \r
+ </set>\r
+ <value>myValue</value>\r
+ </set> \r
+ </list> \r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </set> \r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ <set>\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ <list>\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </list>\r
+ <value>@{testKey}</value>\r
+ </list> \r
+ </set>\r
+ <value>@{testKey}</value>\r
+ </set> \r
+ </list> \r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </set> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="basic.testDef" class="org.argeo.slc.core.test.BasicTestDefinition">\r
+ </bean> \r
+\r
+\r
+ <bean id="echo1" parent="task.echo" scope="prototype">\r
+ <property name="message"\r
+ value="testKey=@{testKey}" />\r
+ </bean>\r
+ \r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="basic.testDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+\r
+ <bean id="abstractFlow" parent="slcTemplate.simpleFlow" abstract="true">\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="echo1" />\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingMap.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleList.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingList.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="simpleSet.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingSet.testData" />\r
+ </bean> \r
+ \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingListMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingSetMap.testData" />\r
+ </bean> \r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData" ref="cascadingComplex.testData" />\r
+ </bean> \r
+ \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flow1" parent="abstractFlow" scope="prototype">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttr.primitive" p:value="myValue" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ </bean> \r
+\r
+ <bean id="flow2" parent="abstractFlow" scope="prototype">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttr.primitive" p:value="myValue2" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ </bean> \r
+\r
+\r
+ <bean id="simpleMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <map>\r
+ <entry key="key1" value="myValue_myValue" />\r
+ </map>\r
+ </property>\r
+ <property name="reached">\r
+ <map>\r
+ <entry key="key1" value="@{testKey}_@{testKey}" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="cascadingMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <map>\r
+ <entry key="key3">\r
+ <map>\r
+ <entry key="key2">\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map>\r
+ </entry>\r
+ <entry key="key2bis" value="myValue" />\r
+ </map>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ <property name="reached">\r
+ <map>\r
+ <entry key="key3">\r
+ <map>\r
+ <entry key="key2">\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map>\r
+ </entry>\r
+ <entry key="key2bis" value="@{testKey}" />\r
+ </map>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="simpleList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value> \r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingList.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ <value>myValue</value>\r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </list>\r
+ <value>@{testKey}</value>\r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="simpleSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingSet.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </set>\r
+ <value>myValue</value>\r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </set>\r
+ <value>@{testKey}</value>\r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingListMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </list>\r
+ </property>\r
+ <property name="reached">\r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </list>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingSetMap.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="cascadingComplex.testData" class="org.argeo.slc.core.test.BasicTestData" scope="prototype">\r
+ <property name="expected">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ <set>\r
+ <set>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ <list>\r
+ <list>\r
+ <value>myValue</value>\r
+ <value>_myValue_</value>\r
+ </list>\r
+ <value>myValue</value>\r
+ </list> \r
+ </set>\r
+ <value>myValue</value>\r
+ </set> \r
+ </list> \r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="myValue" />\r
+ </map> \r
+ </set> \r
+ </set>\r
+ </property>\r
+ <property name="reached">\r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ <list>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ <set>\r
+ <set>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ <list>\r
+ <list>\r
+ <value>@{testKey}</value>\r
+ <value>_@{testKey}_</value>\r
+ </list>\r
+ <value>@{testKey}</value>\r
+ </list> \r
+ </set>\r
+ <value>@{testKey}</value>\r
+ </set> \r
+ </list> \r
+ <set>\r
+ <map>\r
+ <entry key="key1" value="@{testKey}" />\r
+ </map> \r
+ </set> \r
+ </set>\r
+ </property>\r
+ </bean> \r
+ \r
+ <bean id="basic.testDef" class="org.argeo.slc.core.test.BasicTestDefinition">\r
+ </bean> \r
+\r
+\r
+ <bean id="echo1" parent="task.echo" scope="prototype">\r
+ <property name="message"\r
+ value="testKey=@{testKey}" />\r
+ </bean>\r
+ \r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="minimal" parent="slcTemplate.simpleFlow">\r
+ <property name="executionSpec">\r
+ <bean parent="slcTemplate.simpleSpec">\r
+<!-- <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttr.primitive" p:value="660" />\r
+ </entry>\r
+ </map>\r
+ </property> -->\r
+ </bean>\r
+ </property>\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="echo1" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="echo1" parent="task.echo" scope="execution">\r
+ <property name="message"\r
+ value="From minimal" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="myTestDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+\r
+ <bean id="fileDiff.spec" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="fileName">\r
+ <bean parent="specAttr.primitive" p:isParameter="true" p:type="string"\r
+ p:isFrozen="true" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+\r
+ <bean id="fileDiff.flowTemplate" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <property name="path" value="/fileDiff/testcases" />\r
+ <constructor-arg ref="fileDiff.spec" />\r
+ <property name="executables">\r
+ <list> \r
+ <bean parent="task.echo">\r
+ <property name="message" value="fileName=@{fileName}" />\r
+ </bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="file1" />\r
+ <property name="reached" value="@{fileName}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="echo" parent="task.echo" scope="prototype">\r
+ <property name="message" value="fileName=@{fileName}" />\r
+ </bean> \r
+ \r
+ <bean id="flow1" parent="fileDiff.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="fileName" value="file1" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean> \r
+\r
+ <bean id="flow2" parent="fileDiff.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="fileName" value="file2" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean> \r
+ \r
+ \r
+ <!-- \r
+ <bean id="flow1" parent="slcTemplate.simpleFlow">\r
+ <property name="path" value="/fileDiff/testcases" />\r
+ <constructor-arg ref="fileDiff.spec" />\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="fileName" value="file1" />\r
+ </map>\r
+ </constructor-arg> \r
+ <property name="executables">\r
+ <list> \r
+ <bean parent="task.echo" scope="execution">\r
+ <property name="message" value="fileName=@{fileName}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flow2" parent="slcTemplate.simpleFlow">\r
+ <property name="path" value="/fileDiff/testcases" />\r
+ <constructor-arg ref="fileDiff.spec" />\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="fileName" value="file2" />\r
+ </map>\r
+ </constructor-arg> \r
+ <property name="executables">\r
+ <list> \r
+ <bean parent="task.echo" scope="execution">\r
+ <property name="message" value="fileName=@{fileName}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+ -->\r
+<!-- \r
+ <bean id="main" parent="slcTemplate.simpleFlow">\r
+ <property name="executables">\r
+ <list> \r
+ <ref bean="flow1"/> \r
+ <ref bean="flow2"/> \r
+ </list>\r
+ </property>\r
+ </bean>\r
+ -->\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" />\r
+\r
+ <!-- DEFINITIONS -->\r
+ <bean id="parameterRef.spec" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="exceptionIfInitCalledTwice">\r
+ <bean parent="specAttr.ref"\r
+ p:targetClass="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testData2">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testedComponentId">\r
+ <bean parent="specAttr.primitive" p:value="100" p:isParameter="true"\r
+ p:type="integer" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="parameterRef.flowTemplate" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <constructor-arg ref="parameterRef.spec" />\r
+ <property name="executables">\r
+ <list>\r
+ <!-- Primitive -->\r
+ <bean parent="task.echo" scope="execution">\r
+ <property name="message" value="testedComponentId=@{testedComponentId}" />\r
+ </bean>\r
+\r
+ <!-- Exception if init called twice -->\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="exceptionIfInitCalledTwice" />\r
+ </bean>\r
+ <bean parent="parameterRef">\r
+ <property name="name" value="exceptionIfInitCalledTwice" />\r
+ </bean>\r
+\r
+ <!-- Basic tests -->\r
+ <bean parent="parameterRef.testRun">\r
+ <property name="testData">\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="testData1" />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ <bean parent="parameterRef.testRun">\r
+ <property name="testData" ref="ref1" />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <!-- TEST CASES -->\r
+ <bean id="parameterRef.001" parent="parameterRef.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="exceptionIfInitCalledTwice">\r
+ <bean class="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="toto" />\r
+ <property name="reached" value="toto" />\r
+ </bean>\r
+ </entry>\r
+ <entry key="testData2">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="tata" />\r
+ <property name="reached" value="toto" />\r
+ </bean>\r
+ </entry>\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+\r
+ <!-- UTILITIES -->\r
+\r
+ <bean id="ref1" parent="parameterRef">\r
+ <constructor-arg value="testData2" />\r
+ </bean>\r
+\r
+ <bean id="parameterRef.testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="parameterRef.testRun" class="org.argeo.slc.core.test.SimpleTestRun"\r
+ abstract="true">\r
+ <property name="testResult" ref="parameterRef.testResult" />\r
+ <property name="testDefinition">\r
+ <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+ </property>\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="echo1" parent="task.echo">\r
+ <property name="message" value="From minimal" />\r
+ </bean>\r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="myTestDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+\r
+ <!-- \r
+ The Flow A contains the flow B as executable.\r
+ \r
+ Parameters\r
+ p1: flow A: default - flow B: - \r
+ p2: flow A: set - flow B: - \r
+ p3: flow A: default - flow B: default \r
+ p4: flow A: set - flow B: default\r
+ p5: flow A: default - flow B: set \r
+ p6: flow A: set - flow B: set\r
+ p7: flow A: - - flow B: default\r
+ p8: flow A: - - flow B: set\r
+ \r
+ \r
+ -->\r
+\r
+ <bean id="flowA" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="p1"><bean parent="specAttr.primitive" p:value="da1" /></entry>\r
+ <entry key="p2"><bean parent="specAttr.primitive" p:value="da2" /></entry> \r
+ <entry key="p3"><bean parent="specAttr.primitive" p:value="da3" /></entry> \r
+ <entry key="p4"><bean parent="specAttr.primitive" p:value="da4" /></entry> \r
+ <entry key="p5"><bean parent="specAttr.primitive" p:value="da5" /></entry> \r
+ <entry key="p6"><bean parent="specAttr.primitive" p:value="da6" /></entry> \r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <constructor-arg> \r
+ <map>\r
+ <entry key="p2" value="va2"/>\r
+ <entry key="p4" value="va4"/>\r
+ <entry key="p6" value="va6"/>\r
+ </map>\r
+ </constructor-arg>\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da1" />\r
+ <property name="reached" value="@{p1}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va2" />\r
+ <property name="reached" value="@{p2}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da3" />\r
+ <property name="reached" value="@{p3}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va4" />\r
+ <property name="reached" value="@{p4}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da5" />\r
+ <property name="reached" value="@{p5}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va6" />\r
+ <property name="reached" value="@{p6}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <ref bean="flowB"/> \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flowB" parent="slcTemplate.simpleFlow" scope="prototype">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="p3"><bean parent="specAttr.primitive" p:value="db3" /></entry> \r
+ <entry key="p4"><bean parent="specAttr.primitive" p:value="db4" /></entry>\r
+ <entry key="p5"><bean parent="specAttr.primitive" p:value="db5" /></entry> \r
+ <entry key="p6"><bean parent="specAttr.primitive" p:value="db6" /></entry>\r
+ <entry key="p7"><bean parent="specAttr.primitive" p:value="db7" /></entry> \r
+ <entry key="p8"><bean parent="specAttr.primitive" p:value="db8" /></entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <constructor-arg> \r
+ <map>\r
+ <entry key="p3" value="vb3"/>\r
+ <entry key="p4" value="vb4"/>\r
+ <entry key="p7" value="vb7"/>\r
+ </map>\r
+ </constructor-arg> \r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da1" />\r
+ <property name="reached" value="@{p1}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va2" />\r
+ <property name="reached" value="@{p2}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da3" />\r
+ <property name="reached" value="@{p3}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va4" />\r
+ <property name="reached" value="@{p4}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da5" />\r
+ <property name="reached" value="@{p5}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va6" />\r
+ <property name="reached" value="@{p6}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p7=@{p7}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="vb7" />\r
+ <property name="reached" value="@{p7}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p8=@{p8}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="db8" />\r
+ <property name="reached" value="@{p8}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ \r
+ <!-- test in scope execution -->\r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p1=@{p1}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e1" />\r
+ <property name="reached" value="@{p1}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p2=@{p2}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e2" />\r
+ <property name="reached" value="@{p2}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p3=@{p3}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e3" />\r
+ <property name="reached" value="@{p3}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p4=@{p4}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e4" />\r
+ <property name="reached" value="@{p4}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p5=@{p5}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e5" />\r
+ <property name="reached" value="@{p5}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p6=@{p6}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="e6" />\r
+ <property name="reached" value="@{p6}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ \r
+ <!-- \r
+ p7 and p8 are not in the spec of FlowA and therefore can not be overridden\r
+ at the execution\r
+ -->\r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p7=@{p7}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="vb7" />\r
+ <property name="reached" value="@{p7}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo" scope="execution"><property name="message" value="p8=@{p8}" /><aop:scoped-proxy /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <property name="expected" value="db8" />\r
+ <property name="reached" value="@{p8}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="echo1" parent="task.echo">\r
+ <property name="message" value="From minimal" />\r
+ </bean>\r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="myTestDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+\r
+ <!-- \r
+ The Flow A contains the flow B as executable.\r
+ \r
+ Parameters\r
+ p1: flow A: default - flow B: - \r
+ p2: flow A: set - flow B: - \r
+ p3: flow A: default - flow B: default \r
+ p4: flow A: set - flow B: default\r
+ p5: flow A: default - flow B: set \r
+ p6: flow A: set - flow B: set\r
+ p7: flow A: - - flow B: default\r
+ p8: flow A: - - flow B: set\r
+ \r
+ \r
+ -->\r
+\r
+ <bean id="flowA" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="p1"><bean parent="specAttr.primitive" p:value="da1" /></entry>\r
+ <entry key="p2"><bean parent="specAttr.primitive" p:value="da2" /></entry> \r
+ <entry key="p3"><bean parent="specAttr.primitive" p:value="da3" /></entry> \r
+ <entry key="p4"><bean parent="specAttr.primitive" p:value="da4" /></entry> \r
+ <entry key="p5"><bean parent="specAttr.primitive" p:value="da5" /></entry> \r
+ <entry key="p6"><bean parent="specAttr.primitive" p:value="da6" /></entry> \r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <constructor-arg> \r
+ <map>\r
+ <entry key="p2" value="va2"/>\r
+ <entry key="p4" value="va4"/>\r
+ <entry key="p6" value="va6"/>\r
+ </map>\r
+ </constructor-arg>\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da1" />\r
+ <property name="reached" value="@{p1}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va2" />\r
+ <property name="reached" value="@{p2}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da3" />\r
+ <property name="reached" value="@{p3}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va4" />\r
+ <property name="reached" value="@{p4}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da5" />\r
+ <property name="reached" value="@{p5}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va6" />\r
+ <property name="reached" value="@{p6}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <ref bean="flowB"/> \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flowB" parent="slcTemplate.simpleFlow" scope="prototype">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="p3"><bean parent="specAttr.primitive" p:value="db3" /></entry> \r
+ <entry key="p4"><bean parent="specAttr.primitive" p:value="db4" /></entry>\r
+ <entry key="p5"><bean parent="specAttr.primitive" p:value="db5" /></entry> \r
+ <entry key="p6"><bean parent="specAttr.primitive" p:value="db6" /></entry>\r
+ <entry key="p7"><bean parent="specAttr.primitive" p:value="db7" /></entry> \r
+ <entry key="p8"><bean parent="specAttr.primitive" p:value="db8" /></entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <constructor-arg> \r
+ <map>\r
+ <entry key="p3" value="vb3"/>\r
+ <entry key="p4" value="vb4"/>\r
+ <entry key="p7" value="vb7"/>\r
+ </map>\r
+ </constructor-arg> \r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo"><property name="message" value="p1=@{p1}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da1" />\r
+ <property name="reached" value="@{p1}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ <bean parent="task.echo"><property name="message" value="p2=@{p2}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va2" />\r
+ <property name="reached" value="@{p2}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p3=@{p3}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da3" />\r
+ <property name="reached" value="@{p3}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p4=@{p4}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va4" />\r
+ <property name="reached" value="@{p4}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p5=@{p5}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="da5" />\r
+ <property name="reached" value="@{p5}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p6=@{p6}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="va6" />\r
+ <property name="reached" value="@{p6}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p7=@{p7}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="vb7" />\r
+ <property name="reached" value="@{p7}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ <bean parent="task.echo"><property name="message" value="p8=@{p8}" /></bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="db8" />\r
+ <property name="reached" value="@{p8}" />\r
+ </bean>\r
+ </property> \r
+ </bean> \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+ \r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="myTestDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+ \r
+ <bean id="spec1" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testedComponentId">\r
+ <bean parent="specAttr.primitive" p:isParameter="true"\r
+ p:type="integer" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flowTemplate1" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <constructor-arg ref="spec1" />\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo" scope="execution">\r
+ <property name="message" value="From basic @{testedComponentId}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="testData1" />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flow1" parent="flowTemplate1" scope="prototype">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="testedComponentId" value="200" />\r
+ <entry key="testData1">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <aop:scoped-proxy/>\r
+ <property name="expected" value="tata101" />\r
+ <property name="reached" value="tata@{testedComponentId}" />\r
+ </bean>\r
+ </entry>\r
+ </map> \r
+ </constructor-arg>\r
+ </bean>\r
+\r
+ <bean id="spec2" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testData1">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flowTemplate2" parent="slcTemplate.simpleFlow" abstract="true">\r
+ <constructor-arg ref="spec2" />\r
+ <property name="executables">\r
+ <list>\r
+ <ref bean="flow1"/>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+ \r
+ <bean id="flow2" parent="flowTemplate2">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="testData1">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="tata100" />\r
+ <property name="reached" value="tata100" />\r
+ </bean>\r
+ </entry>\r
+ </map> \r
+ </constructor-arg>\r
+ </bean> \r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="../imports.xml" />\r
+\r
+ <bean id="systemCallSimple" parent="slcTemplate.simpleFlow">\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="os.name=${os.name}" />\r
+ </bean>\r
+ <bean parent="task.systemCall">\r
+ <property name="cmd" value="echo Hello World" />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="systemCallList" parent="slcTemplate.simpleFlow">\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.systemCall">\r
+ <property name="command">\r
+ <list>\r
+ <value>echo</value>\r
+ <value>Hello</value>\r
+ <value>World</value>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="systemCallOsSpecific" parent="slcTemplate.simpleFlow">\r
+ <!-- Direct call to dir under Windows isnot working -->\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.systemCall">\r
+ <property name="cmd" value="dir" />\r
+ <property name="execDir" value="../.." />\r
+ <property name="osCmds">\r
+ <map>\r
+ <entry key="Linux" value="ls" />\r
+ <entry key="Mac OS X" value="ls" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ <bean parent="task.systemCall">\r
+ <property name="command">\r
+ <list>\r
+ <value>dir</value>\r
+ </list>\r
+ </property>\r
+ <property name="osCommands">\r
+ <map>\r
+ <entry key="Linux">\r
+ <list>\r
+ <value>ls</value>\r
+ </list>\r
+ </entry>\r
+ <entry key="Mac OS X">\r
+ <list>\r
+ <value>ls</value>\r
+ </list>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="systemCallWithVar" parent="slcTemplate.simpleFlow">\r
+ <constructor-arg>\r
+ <bean parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="var">\r
+ <bean parent="specAttr.primitive" p:value="660" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </constructor-arg>\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.systemCall" scope="execution">\r
+ <property name="cmd" value="echo var=@{var}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" /> \r
+\r
+ <bean id="myTestResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="myTestDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="myTestRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="myTestDef" />\r
+ <property name="testResult" ref="myTestResult"/>\r
+ </bean> \r
+ \r
+ <bean id="spec1" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testedComponentId">\r
+ <bean parent="specAttr.primitive" p:isParameter="true"\r
+ p:type="integer" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flowTemplate1" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <constructor-arg ref="spec1" />\r
+ <property name="executables">\r
+ <list>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="From basic @{testedComponentId}" />\r
+ </bean>\r
+ <bean parent="myTestRunTemplate">\r
+ <property name="testData">\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="testData1" />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ <bean parent="task.echo">\r
+ <property name="message"><value>From basic @{testedComponentId}</value></property>\r
+ </bean> \r
+ <bean parent="task.echo">\r
+ <property name="message"><value>testData1='@{testData1}'</value></property>\r
+ </bean> \r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="flow1" parent="flowTemplate1" scope="prototype">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="testedComponentId" value="200" />\r
+ <entry key="testData1">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData" scope="execution">\r
+ <aop:scoped-proxy/>\r
+ <property name="expected" value="tata101" />\r
+ <property name="reached" value="tata@{testedComponentId}" />\r
+ </bean>\r
+ </entry>\r
+ </map> \r
+ </constructor-arg>\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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"));
+ // }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
+ <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
+\r
+ <bean id="testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="testRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="testDef" />\r
+ <property name="testResult" ref="testResult"/>\r
+ </bean> \r
+\r
+ <flow:spec id="advanced.spec">\r
+ <description>spec description</description>\r
+ <flow:primitive name="param1" isParameter="true"\r
+ type="integer" />\r
+ <flow:primitive name="param2" isParameter="true"\r
+ type="integer" /> \r
+ </flow:spec>\r
+\r
+\r
+ <flow:flow id="advanced.flowTemplate" abstract="true" spec="advanced.spec"\r
+ path="/path">\r
+ <description>flow description</description>\r
+ <bean parent="task.echo">\r
+ <property name="message" value="Advanced: param1=@{param1}, param2=@{param2}" />\r
+ <flow:variable/>\r
+ </bean> \r
+ <flow:flow>\r
+ <bean parent="task.echo" p:message="Flow in Flow - param1=@{param1}, param2=@{param2} [Not variable]" />\r
+ </flow:flow>\r
+ \r
+ <bean parent="testRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <flow:variable/>\r
+ <property name="expected" value="@{param1}" />\r
+ <property name="reached" value="@{param2}" />\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ \r
+ </flow:flow>\r
+\r
+ <flow:flow id="advanced.flowTemplate2" abstract="true" spec="advanced.spec"\r
+ path="/path">\r
+ <bean parent="task.echo" p:message="Advanced2: param1=@{param1}, param2=@{param2}">\r
+ <flow:variable/>\r
+ </bean>\r
+ <flow:flow parent="advanced.flowTemplate">\r
+ <flow:arg name="param1" value="@{param1}"/>\r
+ <flow:arg name="param2">\r
+ <!-- flow:param in flow:arg -->\r
+ <flow:param name="param2" />\r
+ </flow:arg>\r
+ </flow:flow>\r
+ </flow:flow>\r
+\r
+ \r
+ <flow:flow id="flow1" parent="advanced.flowTemplate">\r
+ <flow:arg name="param1" value="1" />\r
+ <flow:arg name="param2" value="1" />\r
+ </flow:flow>\r
+ \r
+ <flow:flow id="flow2">\r
+ <flow:flow parent="advanced.flowTemplate">\r
+ <flow:arg name="param1" value="2" />\r
+ <flow:arg name="param2" value="2" />\r
+ </flow:flow>\r
+ </flow:flow>\r
+\r
+ <flow:flow id="flow3" parent="advanced.flowTemplate2">\r
+ <flow:arg name="param1" value="3" />\r
+ <flow:arg name="param2" value="3" />\r
+ </flow:flow>\r
+ \r
+ <flow:flow id="flow4" parent="advanced.flowTemplate">\r
+ <description>Would fail if param 2 is not changed at execution</description>\r
+ <flow:arg name="param1" value="4" />\r
+ <flow:arg name="param2" value="3" />\r
+ </flow:flow> \r
+\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <bean id="canonic-ns.001" parent="canonic-ns.flowTemplate">\r
+ <description>Canonic 001</description>\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="parameterAtInstantiation" value="1" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:p="http://www.springframework.org/schema/p"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <flow id="canonic-ns.002" parent="canonic-ns.flowTemplate">\r
+ <arg name="parameterAtInstantiation" value="2" />\r
+ <arg name="displayWithoutControl" value="102" />\r
+ <arg name="displayWithControl" value="202" />\r
+ <arg name="hide" value="202" />\r
+ <arg name="refWithoutValue">\r
+ <beans:bean id="testDataOk" p:expected="tata" p:reached="tata"\r
+ class="org.argeo.slc.core.test.BasicTestData" />\r
+ </arg>\r
+ </flow>\r
+</beans:beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <beans:import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
+ <beans:import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
+\r
+ <beans:import resource="canonic-ns-001.xml" />\r
+ <beans:import resource="canonic-ns-002.xml" />\r
+ <beans:import resource="tests.xml" />\r
+\r
+ <!--\r
+ Specifications definition is greatly simplified by the flow namespace\r
+ -->\r
+ <spec id="canonic-ns.spec">\r
+ <primitive name="parameterAtInstantiation" isParameter="true"\r
+ type="integer" />\r
+ <primitive name="displayWithoutControl" value="100"\r
+ isParameter="true" type="integer" isFrozen="true" />\r
+ <primitive name="displayWithControl" value="200"\r
+ isParameter="true" type="integer" />\r
+ <primitive name="hide" value="300" isParameter="true" type="integer"\r
+ isHidden="true" />\r
+ <ref name="refWithValue" targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ isParameter="true" ref="testDataNok" />\r
+ <ref name="refWithoutValue" targetClass="org.argeo.slc.core.test.BasicTestData" />\r
+ <ref name="refWithoutValueFrozen" targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ isParameter="true" isFrozen="true">\r
+ <value>\r
+ <beans:bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="tata" />\r
+ </beans:bean>\r
+ </value>\r
+ </ref>\r
+ </spec>\r
+\r
+ <flow id="canonic-ns.flowTemplate" abstract="true" spec="canonic-ns.spec"\r
+ path="/path">\r
+ <beans:bean parent="task.echo"\r
+ p:message="Canonical: displayWithControl=@{displayWithControl}, displayWithoutControl=@{displayWithoutControl}, hide=@{hide}"\r
+ scope="execution">\r
+ <aop:scoped-proxy />\r
+ </beans:bean>\r
+ <beans:ref bean="testRun" />\r
+ </flow>\r
+\r
+ <beans:bean id="testDataOk" class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="tata" />\r
+ </beans:bean>\r
+\r
+ <beans:bean id="testDataNok" class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="toto" />\r
+ </beans:bean>\r
+</beans:beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
+ <import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
+\r
+ <bean id="testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+\r
+ <bean id="testRunTemplate" class="org.argeo.slc.core.test.SimpleTestRun" abstract="true">\r
+ <property name="testDefinition" ref="testDef" />\r
+ <property name="testResult" ref="testResult"/>\r
+ </bean> \r
+\r
+ <flow:spec id="test.list.spec">\r
+ <flow:ref name="list1" targetClass="java.util.List">\r
+ <flow:value>\r
+ <!-- a list element can be used directly as default value-->\r
+ <list>\r
+ <value>val1</value>\r
+ </list>\r
+ </flow:value>\r
+ </flow:ref>\r
+ <flow:ref name="list2" targetClass="java.util.List" />\r
+ <!-- following parameters are not used in flow -->\r
+ <flow:ref name="dummyMap" targetClass="java.util.Map">\r
+ <flow:value>\r
+ <map></map>\r
+ </flow:value>\r
+ </flow:ref>\r
+ <flow:ref name="dummySet" targetClass="java.util.Set">\r
+ <flow:value>\r
+ <set></set>\r
+ </flow:value>\r
+ </flow:ref>\r
+ <flow:ref name="dummyProperties" targetClass="java.util.Properties">\r
+ <flow:value>\r
+ <props></props>\r
+ </flow:value>\r
+ </flow:ref>\r
+ \r
+ </flow:spec>\r
+\r
+\r
+ <flow:flow id="test.list.flowTemplate" abstract="true" spec="test.list.spec"\r
+ path="/path">\r
+ <bean parent="task.echo">\r
+ <property name="message" value="list1=@{list1}, list2=@{list2}" />\r
+ <flow:variable/>\r
+ </bean> \r
+\r
+ <bean parent="testRunTemplate">\r
+ <property name="testData">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected">\r
+ <flow:param name="list1"/>\r
+ </property>\r
+ <property name="reached">\r
+ <flow:param name="list2"/>\r
+ </property>\r
+ </bean>\r
+ </property> \r
+ </bean>\r
+ \r
+ </flow:flow>\r
+\r
+ <flow:flow id="test.list.flow1" parent="test.list.flowTemplate">\r
+ <flow:arg name="list1">\r
+ <list>\r
+ <value>val1</value>\r
+ <value>val2</value> \r
+ </list>\r
+ </flow:arg>\r
+ <flow:arg name="list2">\r
+ <list>\r
+ <value>val1</value>\r
+ <value>val2</value> \r
+ </list>\r
+ </flow:arg>\r
+ \r
+ <!-- not used in flow (just to test that the syntax is accepted): -->\r
+ <flow:arg name="dummyMap">\r
+ <map></map>\r
+ </flow:arg>\r
+ <flow:arg name="dummySet">\r
+ <set></set>\r
+ </flow:arg>\r
+ <flow:arg name="dummyProperties">\r
+ <props></props>\r
+ </flow:arg> \r
+ \r
+ </flow:flow>\r
+ \r
+ <flow:flow id="test.list.flow2" parent="test.list.flowTemplate">\r
+ <description>use default value for parameter "list1"</description>\r
+ <flow:arg name="list2">\r
+ <list>\r
+ <value>val1</value>\r
+ </list>\r
+ </flow:arg>\r
+ </flow:flow>\r
+\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <bean id="testRun" class="org.argeo.slc.core.test.SimpleTestRun">\r
+ <property name="testDefinition">\r
+ <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+ </property>\r
+ <property name="testData">\r
+ <flow:param name="refWithValue" />\r
+ </property>\r
+ <!-- <property name="testData">-->\r
+ <!-- <bean parent="parameterRef">-->\r
+ <!-- <constructor-arg value="refWithValue" />-->\r
+ <!-- </bean>-->\r
+ <!-- </property>-->\r
+ <property name="testResult">\r
+ <bean parent="slcDefault.test.basicSimpleTestResult" scope="execution">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="displayWithControl" value="@{displayWithControl}" />\r
+ </map>\r
+ </property>\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+</beans>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import java.util.Map;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.springframework.beans.factory.BeanFactoryUtils;\r
+import org.springframework.beans.factory.ListableBeanFactory;\r
+import org.springframework.context.ConfigurableApplicationContext;\r
+import org.springframework.context.support.ClassPathXmlApplicationContext;\r
+\r
+/** Helper for tests using a Spring application context. */\r
+public abstract class AbstractInternalSpringTestCase extends TestCase {\r
+ protected final Log log = LogFactory.getLog(getClass());\r
+ private ConfigurableApplicationContext context;\r
+\r
+ /**\r
+ * Gets (and create if necessary) the application context to use. Default\r
+ * implementation uses a class path xml application context and calls\r
+ * {@link #getApplicationContextLocation()}.\r
+ */\r
+ protected ConfigurableApplicationContext getContext() {\r
+ if (context == null) {\r
+ context = new ClassPathXmlApplicationContext(\r
+ getApplicationContextLocation());\r
+ }\r
+ return context;\r
+ }\r
+\r
+ /** Returns a bean from the underlying context */\r
+ @SuppressWarnings(value = { "unchecked" })\r
+ protected <T> T getBean(String beanId) {\r
+ return (T) getContext().getBean(beanId);\r
+ }\r
+\r
+ protected <T> T getBean(Class<? extends T> clss) {\r
+ T bean = loadSingleFromContext(getContext(), clss);\r
+ if (bean == null) {\r
+ throw new SlcException("Cannot retrieve a unique bean of type "\r
+ + clss);\r
+ } else {\r
+ return bean;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Th location of the application to load. The default implementation\r
+ * returns <i>applicationContext.xml</i> found in the same package as the\r
+ * test.\r
+ */\r
+ protected String getApplicationContextLocation() {\r
+ return inPackage("applicationContext.xml");\r
+ }\r
+\r
+ /**\r
+ * Prefixes the package of the class after converting the '.' to '/' in\r
+ * order to have a resource path.\r
+ */\r
+ protected String inPackage(String suffix) {\r
+ String prefix = getClass().getPackage().getName().replace('.', '/');\r
+ return prefix + '/' + suffix;\r
+ }\r
+\r
+ @SuppressWarnings(value = { "unchecked" })\r
+ protected <T> T loadSingleFromContext(ListableBeanFactory context,\r
+ Class<T> clss) {\r
+ Map<String, T> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(\r
+ context, clss, false, false);\r
+ if (beans.size() == 1) {\r
+ return beans.values().iterator().next();\r
+ } else if (beans.size() > 1) {\r
+ if (log.isDebugEnabled()) {\r
+ log\r
+ .debug(("Found more that on bean for type " + clss\r
+ + ": " + beans.keySet()));\r
+ }\r
+ return null;\r
+ } else {\r
+ return null;\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import java.util.List;\r
+\r
+import org.argeo.slc.core.test.SimpleTestResult;\r
+import org.argeo.slc.test.TestResultPart;\r
+import org.argeo.slc.test.TestStatus;\r
+import org.argeo.slc.test.context.ContextAware;\r
+\r
+public class ContextTest extends AbstractInternalSpringTestCase {\r
+\r
+ public void testComplexContext() {\r
+ SimpleTestResult testResult = new SimpleTestResult();\r
+ ContextUtils.compareReachedExpected(\r
+ (ContextAware) getBean("context.c1"), testResult);\r
+ ContextUtils.compareReachedExpected(\r
+ (ContextAware) getBean("context.c2"), testResult);\r
+ ContextUtils.compareReachedExpected(\r
+ (ContextAware) getBean("context.c3"), testResult);\r
+\r
+ List<TestResultPart> parts = testResult.getParts();\r
+ assertEquals(6, parts.size());\r
+ assertEquals(TestStatus.PASSED, parts.get(0).getStatus());\r
+ assertEquals(TestStatus.PASSED, parts.get(1).getStatus());\r
+ assertEquals(TestStatus.PASSED, parts.get(2).getStatus());\r
+ assertEquals(TestStatus.FAILED, parts.get(3).getStatus());\r
+ assertEquals(TestStatus.PASSED, parts.get(4).getStatus());\r
+ assertEquals(TestStatus.PASSED, parts.get(5).getStatus());\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+\r
+ Copyright (C) 2007-2012 Argeo GmbH\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+-->\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+ <bean id="parentContext.pc1" parent="parentContext.template">\r
+ <property name="values">\r
+ <map>\r
+ <entry key="rootvar" value="text" />\r
+ </map>\r
+ </property>\r
+ <property name="expectedValues">\r
+ <map>\r
+ <entry key="reference" value="20" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="context.c1" parent="context.template">\r
+ <property name="parentContext" ref="parentContext.pc1" />\r
+ <property name="values">\r
+ <map>\r
+ <entry key="reference" value="20" />\r
+ <entry key="any" value="999" />\r
+ <entry key="skipped" value="999" />\r
+ </map>\r
+ </property>\r
+ <property name="expectedValues">\r
+ <map>\r
+ <entry key="reference" value="21" />\r
+ <entry key="any" value="*" />\r
+ <entry key="skipped" value="!" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="context.c2" parent="context.template">\r
+ <property name="parentContext" ref="parentContext.pc1" />\r
+ <property name="values">\r
+ <map>\r
+ <entry key="var" value="37" />\r
+ <entry key="bad" value="56" />\r
+ </map>\r
+ </property>\r
+ <property name="expectedValues">\r
+ <map>\r
+ <entry key="var" value="37" />\r
+ <entry key="bad" value="57" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="parentContext.pc2" parent="parentContext.template">\r
+ <property name="parentContext" ref="parentContext.pc1" />\r
+ <property name="expectedValues">\r
+ <map>\r
+ <entry key="reference" value="40" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="context.c3" parent="context.template">\r
+ <property name="parentContext" ref="parentContext.pc2" />\r
+ <property name="values">\r
+ <map>\r
+ <entry key="reference" value="41" />\r
+ <entry key="rootvar" value="textX" />\r
+ </map>\r
+ </property>\r
+ <property name="expectedValues">\r
+ <map>\r
+ <entry key="reference" value="40" />\r
+ <entry key="rootvar" value="text" />\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+\r
+ <bean id="parentContext.template"\r
+ class="org.argeo.slc.core.test.context.SimpleParentContextAware"\r
+ abstract="true">\r
+ </bean>\r
+\r
+ <bean id="context.template"\r
+ class="org.argeo.slc.core.test.context.SimpleContextAware"\r
+ abstract="true">\r
+ </bean>\r
+</beans>
\ No newline at end of file
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.slc</groupId>
+ <artifactId>argeo-slc</artifactId>
+ <version>2.1.17-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.slc.spring</artifactId>
+ <name>SLC Spring Runtime</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <!-- Commons -->
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.enterprise</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.node.api</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.jcr</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.util</artifactId>
+ <version>${version.argeo-commons}</version>
+ </dependency>
+
+ <!-- SLC -->
+ <dependency>
+ <groupId>org.argeo.slc</groupId>
+ <artifactId>org.argeo.slc.api</artifactId>
+ <version>2.1.17-SNAPSHOT</version>
+ </dependency>
+
+ <!-- Spring -->
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.spring</groupId>
+ <artifactId>org.springframework.aop</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.tp.gemini</groupId>
+ <artifactId>org.eclipse.gemini.blueprint.io</artifactId>
+ </dependency>
+
+ <!-- Ant -->
+ <dependency>
+ <groupId>org.argeo.tp.apache.ant</groupId>
+ <artifactId>org.apache.ant</artifactId>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+/*
+ * 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.ant;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.slc.core.execution.AbstractExecutionFlowGenerator;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.core.io.Resource;
+
+public class AntFlowGenerator extends AbstractExecutionFlowGenerator {
+ private List<Resource> antFiles = new ArrayList<Resource>();
+
+ protected Map<String, BeanDefinition> createExecutionFlowDefinitions(
+ ConfigurableListableBeanFactory beanFactory) {
+ Map<String, BeanDefinition> definitions = new HashMap<String, BeanDefinition>();
+
+ for (Resource antFile : antFiles) {
+ AntRun antRun = new AntRun();
+ antRun.setBuildFile(antFile);
+
+ List<Runnable> executables = new ArrayList<Runnable>();
+ executables.add(antRun);
+ definitions.put("ant." + antFile.getFilename(),
+ createDefaultFlowDefinition(executables));
+ }
+ return definitions;
+ }
+
+ public void setAntFiles(List<Resource> antFiles) {
+ this.antFiles = antFiles;
+ }
+
+}
--- /dev/null
+/*
+ * 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.ant;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.helper.ProjectHelper2;
+import org.argeo.slc.SlcException;
+import org.springframework.core.io.Resource;
+
+public class AntRun implements Runnable {
+ private final static Log log = LogFactory.getLog(AntRun.class);
+
+ private Resource buildFile;
+ private File baseDir;
+
+ private List<String> targets = new ArrayList<String>();
+ private Map<Object, Object> properties = new HashMap<Object, Object>();
+
+ public void run() {
+ Project project = new Project();
+
+ try {
+ String path = buildFile.getURL().getPath();
+ project.setUserProperty("ant.file", path);
+ project.setBaseDir(extractBaseDir(path));
+
+ project.init();
+ ProjectHelper projectHelper = new ProjectHelper2();
+ project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE,
+ projectHelper);
+ projectHelper.parse(project, buildFile.getURL());
+ } catch (Exception e) {
+ throw new SlcException("Could not parse " + buildFile, e);
+ }
+
+ if (properties != null) {
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+ project.setUserProperty(entry.getKey().toString(), entry
+ .getValue().toString());
+ }
+ }
+
+ project.fireBuildStarted();
+ Throwable exception = null;
+ try {
+ project.addBuildListener(new LoggingListener());
+ if (targets.size() == 0) {
+ project.executeTarget(project.getDefaultTarget());
+ } else {
+ project.executeTargets(new Vector<String>(targets));
+ }
+ } catch (Throwable e) {
+ exception = e;
+ throw new SlcException("Could not run Ant script " + buildFile, e);
+ } finally {
+ project.fireBuildFinished(exception);
+ }
+ }
+
+ private File extractBaseDir(String path) {
+ if(this.baseDir!=null)
+ return this.baseDir;
+
+ String baseDir = null;
+ if (path.length() > 1) {
+ int indx = path.lastIndexOf('/', path.length() - 1);
+ if (indx == -1 || indx == 0) {
+ baseDir = "/";
+ } else {
+ baseDir = path.substring(0, indx) + "/";
+ }
+ } else {
+ baseDir = "/";
+ }
+ File file = new File(baseDir);
+ if (file.exists()) {
+ return file;
+ } else {
+ return new File(System.getProperty("user.dir"));
+ }
+ }
+
+ public void setBuildFile(Resource buildFile) {
+ this.buildFile = buildFile;
+ }
+
+ public void setTargets(List<String> targets) {
+ this.targets = targets;
+ }
+
+ public void setProperties(Map<Object, Object> properties) {
+ this.properties = properties;
+ }
+
+ public void setBaseDir(File baseDir) {
+ this.baseDir = baseDir;
+ }
+
+ protected static class LoggingListener implements BuildListener {
+
+ public void buildFinished(BuildEvent event) {
+ if (log.isDebugEnabled())
+ log.debug("Ant build finished: " + event);
+ }
+
+ public void buildStarted(BuildEvent event) {
+ if (log.isDebugEnabled())
+ log.debug("Ant build started: " + event);
+ }
+
+ public void messageLogged(BuildEvent event) {
+ if (event.getPriority() == Project.MSG_DEBUG) {
+ if (log.isTraceEnabled())
+ log.trace(event.getMessage());
+ } else if (event.getPriority() == Project.MSG_VERBOSE) {
+ if (log.isDebugEnabled())
+ log.debug(event.getMessage());
+ } else if (event.getPriority() == Project.MSG_INFO) {
+ log.info(event.getMessage());
+
+ } else if (event.getPriority() == Project.MSG_WARN) {
+ log.warn(event.getMessage());
+
+ } else if (event.getPriority() == Project.MSG_ERR) {
+ log.error(event.getMessage());
+ } else {
+ log.error(event.getMessage());
+ }
+ }
+
+ public void targetFinished(BuildEvent event) {
+ if (log.isTraceEnabled())
+ log.debug("Target finished: " + event.getTarget());
+ }
+
+ public void targetStarted(BuildEvent event) {
+ if (log.isTraceEnabled())
+ log.debug("Target started: " + event.getTarget());
+ }
+
+ public void taskFinished(BuildEvent event) {
+ }
+
+ public void taskStarted(BuildEvent event) {
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.build;\r
+\r
+import java.util.StringTokenizer;\r
+\r
+/**\r
+ * <p>\r
+ * An implementation of the distribution id using the standard\r
+ * Major.Minor.Release notation. And additional arbitrary string can also be\r
+ * added.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * <b>Examples:</b><br>\r
+ * 0.2.6<br>\r
+ * 2.4.12.RC1\r
+ * </p>\r
+ */\r
+public class VersionDistributionId {\r
+\r
+ private Integer major;\r
+ private Integer minor;\r
+ private Integer release;\r
+ private String additional;\r
+\r
+ /** Parse the provided string in order to set the various components. */\r
+ public void setVersionString(String str) {\r
+ StringTokenizer st = new StringTokenizer(str, ".");\r
+ if (st.hasMoreTokens())\r
+ major = Integer.parseInt(st.nextToken());\r
+ if (st.hasMoreTokens())\r
+ minor = Integer.parseInt(st.nextToken());\r
+ if (st.hasMoreTokens())\r
+ release = Integer.parseInt(st.nextToken());\r
+ if (st.hasMoreTokens())\r
+ additional = st.nextToken();\r
+ }\r
+\r
+ public Integer getMajor() {\r
+ return major;\r
+ }\r
+\r
+ public void setMajor(Integer major) {\r
+ this.major = major;\r
+ }\r
+\r
+ public Integer getMinor() {\r
+ return minor;\r
+ }\r
+\r
+ public void setMinor(Integer minor) {\r
+ this.minor = minor;\r
+ }\r
+\r
+ public Integer getRelease() {\r
+ return release;\r
+ }\r
+\r
+ public void setRelease(Integer release) {\r
+ this.release = release;\r
+ }\r
+\r
+ public String getAdditional() {\r
+ return additional;\r
+ }\r
+\r
+ public void setAdditional(String additional) {\r
+ this.additional = additional;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ // TODO Auto-generated method stub\r
+ return super.equals(obj);\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return major + "." + minor + "." + release\r
+ + (additional != null ? "." + additional : "");\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+<html>\r
+<head></head>\r
+<body>\r
+SLC Build: building of software systems.\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+/*
+ * 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<String> includes = new ArrayList<String>();
+ private String exclude;
+ private List<String> excludes = new ArrayList<String>();
+ 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<String, Resource> listResources() {
+ try {
+ Map<String, Resource> res = new TreeMap<String, Resource>();
+ 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<String, Resource> 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<String> 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<String> includes) {
+ this.includes = includes;
+ }
+
+ public void setExclude(String exclude) {
+ this.exclude = exclude;
+ }
+
+ public void setExcludes(List<String> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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.springframework.core.io.Resource;
+import org.springframework.util.DigestUtils;
+
+/** 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 org.argeo.util.DigestUtils.digest(algorithm, file);
+ } catch (IOException e) {
+ try {
+ return org.argeo.util.DigestUtils.digest(algorithm,
+ resource.getInputStream());
+ } catch (IOException e1) {
+ throw new SlcException("Cannot digest " + resource
+ + " with algorithm " + algorithm, e);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<String, Resource> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<ResourceSet> resourceSets = new ArrayList<ResourceSet>();
+
+ public Map<String, Resource> listResources() {
+ Map<String, Resource> res = new HashMap<String, Resource>();
+ for (ResourceSet resourceSet : resourceSets) {
+ res.putAll(resourceSet.listResources());
+ }
+ return res;
+ }
+
+ /** Last listed override previous for the same relative paths. */
+ public void setResourceSets(List<ResourceSet> resourceSets) {
+ this.resourceSets = resourceSets;
+ }
+
+ public List<ResourceSet> getResourceSets() {
+ return resourceSets;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, Resource> listResources();
+}
--- /dev/null
+/*
+ * 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<String, String> paths = new TreeMap<String, String>();
+
+ 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<String, String> getPaths() {
+ return paths;
+ }
+
+ public void setPaths(Map<String, String> paths) {
+ this.paths = paths;
+ }
+
+ public void setDistribution(Distribution distribution) {
+ this.distribution = distribution;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+<html>\r
+<head></head>\r
+<body>\r
+SLC Deploy: deployment of software systems.\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+/*
+ * 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<String, BeanDefinition> createExecutionFlowDefinitions(
+ ConfigurableListableBeanFactory beanFactory);
+
+ public void postProcessBeanFactory(
+ ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ if (!(beanFactory instanceof BeanDefinitionRegistry)) {
+ throw new SlcException("Can only work on "
+ + BeanDefinitionRegistry.class);
+ }
+
+ Map<String, BeanDefinition> 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<Runnable> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<FilteredNotifier> filteredNotifiers = Collections
+ // .synchronizedList(new ArrayList<FilteredNotifier>());
+
+ 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<? extends String, ? extends Object> 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
+ //
+ executionContext.beforeFlow(flow);
+ try {
+ flow.run();
+ } finally {
+ executionContext.afterFlow(flow);
+ }
+ //
+ //
+ //
+ }
+
+ // public void dispatchUpdateStatus(ExecutionProcess process,
+ // String oldStatus, String newStatus) {
+ // // filtered notifiers
+ // for (Iterator<FilteredNotifier> 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<ExecutionStep> steps) {
+ // process.addSteps(steps);
+ // for (Iterator<FilteredNotifier> it = filteredNotifiers.iterator(); it
+ // .hasNext();) {
+ // FilteredNotifier filteredNotifier = it.next();
+ // if (filteredNotifier.receiveFrom(process))
+ // filteredNotifier.getNotifier().addSteps(process, steps);
+ // }
+ // }
+
+ // public void registerProcessNotifier(ExecutionProcessNotifier notifier,
+ // Map<String, String> properties) {
+ // filteredNotifiers.add(new FilteredNotifier(notifier, properties));
+ // }
+ //
+ // public void unregisterProcessNotifier(ExecutionProcessNotifier notifier,
+ // Map<String, String> properties) {
+ // filteredNotifiers.remove(notifier);
+ // }
+
+ // protected class FilteredNotifier {
+ // private final ExecutionProcessNotifier notifier;
+ // private final String processId;
+ //
+ // public FilteredNotifier(ExecutionProcessNotifier notifier,
+ // Map<String, String> properties) {
+ // super();
+ // this.notifier = notifier;
+ // if (properties == null)
+ // properties = new HashMap<String, String>();
+ // 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;
+ // }
+ //
+ // }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, ExecutionFlow> 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<String, Object> values = new TreeMap<String, Object>();
+ 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<String, ExecutionFlow> listFlows() {
+ GenericBeanFactoryAccessor accessor = new GenericBeanFactoryAccessor(
+ applicationContext);
+ Map<String, ExecutionFlow> 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;
+ }*/
+
+}
--- /dev/null
+/*
+ * 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.DefaultNameVersion;
+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<String, ProcessThread> runningProcesses = Collections
+ .synchronizedMap(new HashMap<String, ProcessThread>());
+
+ 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<ProcessThread> it = runningProcesses.values().iterator();
+ while (it.hasNext()) {
+ ProcessThread pThread = it.next();
+ if (!pThread.isAlive())
+ it.remove();
+ }
+ }
+
+ public String process(List<URI> 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 DefaultNameVersion(path[1]);
+ StringBuilder flow = new StringBuilder();
+ for (int i = 2; i < path.length; i++)
+ flow.append('/').append(path[i]);
+
+ Map<String, Object> 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 DefaultNameVersion(moduleName, moduleVersion));
+ emd = modulesManager.getExecutionModuleDescriptor(moduleName,
+ moduleVersion);
+ } catch (SlcException e) {
+ if (defaultModulePrefix != null) {
+ moduleName = defaultModulePrefix + "." + moduleName;
+ modulesManager.start(new DefaultNameVersion(moduleName,
+ moduleVersion));
+ emd = modulesManager.getExecutionModuleDescriptor(moduleName,
+ moduleVersion);
+ } else
+ throw e;
+ }
+ return emd;
+ }
+
+ public List<ExecutionModuleDescriptor> listExecutionModuleDescriptors() {
+ return modulesManager.listExecutionModules();
+ }
+
+ public boolean ping() {
+ return true;
+ }
+
+ /*
+ * UTILITIES
+ */
+ /**
+ * @param query
+ * can be null
+ */
+ static Map<String, Object> getQueryMap(String query) {
+ Map<String, Object> map = new LinkedHashMap<String, Object>();
+ 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();
+ }
+}
--- /dev/null
+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.slc.DefaultNameVersion;
+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;
+
+/**
+ * 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<URI> 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 DefaultNameVersion(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<URI> 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 DefaultNameVersion(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<String, Object> 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<URI> asURIs(String[] args) {
+ try {
+ List<URI> uris = new ArrayList<URI>();
+ List<String> leftOvers = new ArrayList<String>();
+
+ Boolean hasArgs = false;
+ String currKey = null;
+ StringBuilder currUri = null;
+ Iterator<String> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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.ExecutionContext;
+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<String, Object> parameters = new HashMap<String, Object>();
+ private List<Runnable> executables = new ArrayList<Runnable>();
+
+ private String path;
+
+ private Boolean failOnError = true;
+
+ // Only needed if stacked execution flows are used
+ private ExecutionContext executionContext = null;
+
+ public DefaultExecutionFlow() {
+ this.executionSpec = new DefaultExecutionSpec();
+ }
+
+ public DefaultExecutionFlow(ExecutionSpec executionSpec) {
+ this.executionSpec = executionSpec;
+ }
+
+ public DefaultExecutionFlow(ExecutionSpec executionSpec,
+ Map<String, Object> 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<Runnable> 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) {
+ try {
+ if (executionContext != null)
+ if (runnable instanceof ExecutionFlow)
+ executionContext.beforeFlow((ExecutionFlow) runnable);
+ runnable.run();
+ } finally {
+ if (executionContext != null)
+ if (runnable instanceof ExecutionFlow)
+ executionContext.afterFlow((ExecutionFlow) runnable);
+ }
+ }
+
+ 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<Runnable> executables) {
+ this.executables = executables;
+ }
+
+ public void setParameters(Map<String, Object> 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;
+ }
+
+ public void setExecutionContext(ExecutionContext executionContext) {
+ this.executionContext = executionContext;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, Object> convertValues(
+ ExecutionFlowDescriptor executionFlowDescriptor) {
+ Map<String, Object> values = executionFlowDescriptor.getValues();
+ Map<String, Object> convertedValues = new HashMap<String, Object>();
+ 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<String, ExecutionFlow> executionFlows) {
+ SortedSet<ExecutionFlowDescriptor> set = new TreeSet<ExecutionFlowDescriptor>(
+ 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);
+ }
+
+ 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<String, Object> values = new TreeMap<String, Object>();
+ 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);
+ // Takes description from spring
+ BeanFactory bf = getBeanFactory();
+ if (bf != null) {
+ BeanDefinition bd = getBeanFactory().getBeanDefinition(name);
+ efd.setDescription(bd.getDescription());
+ }
+ return efd;
+ }
+
+ 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<String, ?> 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<ExecutionFlowDescriptor> {
+ @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;
+ }
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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<String, ExecutionSpecAttribute> attributes = new HashMap<String, ExecutionSpecAttribute>();
+
+ private String name = INTERNAL_NAME;
+
+ public Map<String, ExecutionSpecAttribute> getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map<String, ExecutionSpecAttribute> 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<RefValueChoice> 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<RefValueChoice> buildRefValueChoices(RefSpecAttribute rsa) {
+ List<RefValueChoice> choices = new ArrayList<RefValueChoice>();
+ 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
+
+ public synchronized void enterFlow(ExecutionFlow executionFlow) {
+ ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
+ stack.push(runtime);
+
+ Map<String, ExecutionSpecAttribute> 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 <code>null</code> 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 </code>null<code> 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<String, Object> scopedObjects = new HashMap<String, Object>();
+ private final Map<String, Object> localVariables = new HashMap<String, Object>();
+ private final String uuid = UUID.randomUUID().toString();
+
+ public ExecutionFlowRuntime(ExecutionFlow executionFlow) {
+ this.executionFlow = executionFlow;
+ }
+
+ public ExecutionFlow getExecutionFlow() {
+ return executionFlow;
+ }
+
+ public Map<String, Object> getScopedObjects() {
+ return scopedObjects;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public Map<String, Object> getLocalVariables() {
+ return localVariables;
+ }
+
+ @Override
+ public String toString() {
+ return "Stack Level #" + uuid;
+ }
+
+ }
+}
--- /dev/null
+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<ExecutionStep> steps = new ArrayList<ExecutionStep>();
+ private List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void addSteps(List<ExecutionStep> steps) {
+ steps.addAll(steps);
+ }
+
+ public List<RealizedFlow> getRealizedFlows() {
+ return realizedFlows;
+ }
+
+ public List<ExecutionStep> getSteps() {
+ return steps;
+ }
+
+ public void setSteps(List<ExecutionStep> steps) {
+ this.steps = steps;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public void setRealizedFlows(List<RealizedFlow> realizedFlows) {
+ this.realizedFlows = realizedFlows;
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution;\r
+\r
+import java.beans.PropertyDescriptor;\r
+import java.util.HashSet;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.execution.ExecutionContext;\r
+import org.argeo.slc.execution.ExecutionFlow;\r
+import org.springframework.beans.BeansException;\r
+import org.springframework.beans.MutablePropertyValues;\r
+import org.springframework.beans.PropertyValue;\r
+import org.springframework.beans.PropertyValues;\r
+import org.springframework.beans.factory.BeanDefinitionStoreException;\r
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;\r
+import org.springframework.beans.factory.config.TypedStringValue;\r
+import org.springframework.beans.factory.support.ManagedList;\r
+import org.springframework.beans.factory.support.ManagedMap;\r
+import org.springframework.beans.factory.support.ManagedSet;\r
+import org.springframework.util.ObjectUtils;\r
+import org.springframework.util.StringUtils;\r
+\r
+/**\r
+ * Spring post processor which ensures that execution parameters are properly\r
+ * set. It is used at two levels: first during instantiation for instantiation\r
+ * parameters which allow to implement templates, then at runtime in order to\r
+ * interpret @{} placeholders when object of scope execution are instantiated.\r
+ */\r
+public class ExecutionParameterPostProcessor extends\r
+ InstantiationAwareBeanPostProcessorAdapter {\r
+\r
+ private final static Log log = LogFactory\r
+ .getLog(ExecutionParameterPostProcessor.class);\r
+\r
+ private ExecutionContext executionContext;\r
+ private InstantiationManager instantiationManager;\r
+\r
+ private String placeholderPrefix = "@{";\r
+ private String placeholderSuffix = "}";\r
+ private String nullValue;\r
+\r
+ @Override\r
+ public PropertyValues postProcessPropertyValues(PropertyValues pvs,\r
+ PropertyDescriptor[] pds, Object bean, String beanName)\r
+ throws BeansException {\r
+\r
+ // TODO: resolve at execution only if scope is execution\r
+ // TODO: deal with placeholders in RuntimeBeanReference and\r
+ // RuntimeBeanNameReference\r
+\r
+ MutablePropertyValues newPvs = new MutablePropertyValues();\r
+\r
+ boolean changesOccured = false;\r
+\r
+ for (PropertyValue pv : pvs.getPropertyValues()) {\r
+ Object convertedValue = resolveValue(beanName, bean, pv.getValue());\r
+ newPvs.addPropertyValue(new PropertyValue(pv, convertedValue));\r
+ if (convertedValue != pv.getValue()) {\r
+ changesOccured = true;\r
+ }\r
+ }\r
+\r
+ return changesOccured ? newPvs : pvs;\r
+ }\r
+\r
+ @Override\r
+ public boolean postProcessAfterInstantiation(Object bean, String beanName)\r
+ throws BeansException {\r
+ if (bean instanceof ExecutionFlow)\r
+ instantiationManager.flowInitializationStarted(\r
+ (ExecutionFlow) bean, beanName);\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public Object postProcessAfterInitialization(Object bean, String beanName)\r
+ throws BeansException {\r
+ if (bean instanceof ExecutionFlow)\r
+ instantiationManager.flowInitializationFinished(\r
+ (ExecutionFlow) bean, beanName);\r
+ return bean;\r
+ }\r
+\r
+ protected String resolvePlaceholder(Object bean, String placeholder) {\r
+ if (instantiationManager.isInFlowInitialization())\r
+ return instantiationManager.getInitializingFlowParameter(\r
+ placeholder).toString();\r
+\r
+ else {// execution\r
+ // next call fail if no execution context available\r
+ Object obj = executionContext.getVariable(placeholder);\r
+ if (obj != null) {\r
+ return obj.toString();\r
+ }\r
+ }\r
+\r
+ return null;\r
+ }\r
+\r
+ public Object resolveValue(String beanName, Object bean, Object value) {\r
+ if (value instanceof TypedStringValue) {\r
+ TypedStringValue tsv = (TypedStringValue) value;\r
+ String originalValue = tsv.getValue();\r
+\r
+ String convertedValue = resolveString(beanName, bean, originalValue);\r
+ if (convertedValue == null)\r
+ return null;\r
+ return convertedValue.equals(originalValue) ? value\r
+ : new TypedStringValue(convertedValue);\r
+ } else if (value instanceof String) {\r
+ String originalValue = value.toString();\r
+ String convertedValue = resolveString(beanName, bean, originalValue);\r
+ if (convertedValue == null)\r
+ return null;\r
+ return convertedValue.equals(originalValue) ? value\r
+ : convertedValue;\r
+ } else if (value instanceof ManagedMap) {\r
+ Map<?, ?> mapVal = (Map<?, ?>) value;\r
+\r
+ Map<Object, Object> newContent = new ManagedMap<Object, Object>();\r
+ boolean entriesModified = false;\r
+ for (Iterator<?> it = mapVal.entrySet().iterator(); it.hasNext();) {\r
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();\r
+ Object key = entry.getKey();\r
+ int keyHash = (key != null ? key.hashCode() : 0);\r
+ Object newKey = resolveValue(beanName, bean, key);\r
+ int newKeyHash = (newKey != null ? newKey.hashCode() : 0);\r
+ Object val = entry.getValue();\r
+ Object newVal = resolveValue(beanName, bean, val);\r
+ newContent.put(newKey, newVal);\r
+ entriesModified = entriesModified\r
+ || (newVal != val || newKey != key || newKeyHash != keyHash);\r
+ }\r
+\r
+ return entriesModified ? newContent : value;\r
+ } else if (value instanceof ManagedList) {\r
+ List<?> listVal = (List<?>) value;\r
+ List<Object> newContent = new ManagedList<Object>();\r
+ boolean valueModified = false;\r
+\r
+ for (int i = 0; i < listVal.size(); i++) {\r
+ Object elem = listVal.get(i);\r
+ Object newVal = resolveValue(beanName, bean, elem);\r
+ newContent.add(newVal);\r
+ if (!ObjectUtils.nullSafeEquals(newVal, elem)) {\r
+ valueModified = true;\r
+ }\r
+ }\r
+ return valueModified ? newContent : value;\r
+ } else if (value instanceof ManagedSet) {\r
+ Set<?> setVal = (Set<?>) value;\r
+ Set<Object> newContent = new ManagedSet<Object>();\r
+ boolean entriesModified = false;\r
+ for (Iterator<?> it = setVal.iterator(); it.hasNext();) {\r
+ Object elem = it.next();\r
+ int elemHash = (elem != null ? elem.hashCode() : 0);\r
+ Object newVal = resolveValue(beanName, bean, elem);\r
+ int newValHash = (newVal != null ? newVal.hashCode() : 0);\r
+ newContent.add(newVal);\r
+ entriesModified = entriesModified\r
+ || (newVal != elem || newValHash != elemHash);\r
+ }\r
+ return entriesModified ? newContent : value;\r
+ } else {\r
+ // log.debug(beanName + ": " + value.getClass() + " : " + value);\r
+ return value;\r
+ }\r
+\r
+ }\r
+\r
+ private String resolveString(String beanName, Object bean, String strVal) {\r
+ // in case <null/> is passed\r
+ if (strVal == null)\r
+ return null;\r
+\r
+ String value = parseStringValue(bean, strVal, new HashSet<String>());\r
+\r
+ if (value == null)\r
+ throw new SlcException("Could not resolve placeholder '" + strVal\r
+ + "' in bean '" + beanName + "'");\r
+\r
+ return (value.equals(nullValue) ? null : value);\r
+ }\r
+\r
+ public void setPlaceholderPrefix(String placeholderPrefix) {\r
+ this.placeholderPrefix = placeholderPrefix;\r
+ }\r
+\r
+ public void setPlaceholderSuffix(String placeholderSuffix) {\r
+ this.placeholderSuffix = placeholderSuffix;\r
+ }\r
+\r
+ public void setNullValue(String nullValue) {\r
+ this.nullValue = nullValue;\r
+ }\r
+\r
+ public void setInstantiationManager(\r
+ InstantiationManager instantiationManager) {\r
+ this.instantiationManager = instantiationManager;\r
+ }\r
+\r
+ public void setExecutionContext(ExecutionContext executionContext) {\r
+ this.executionContext = executionContext;\r
+ }\r
+\r
+ //\r
+ // Following methods hacked from the internals of\r
+ // PropertyPlaceholderConfigurer\r
+ //\r
+\r
+ protected String parseStringValue(Object bean, String strVal,\r
+ Set<String> visitedPlaceholders)\r
+ throws BeanDefinitionStoreException {\r
+\r
+ // in case <null/> is passed\r
+ if (strVal == null)\r
+ return null;\r
+\r
+ StringBuffer buf = new StringBuffer(strVal);\r
+\r
+ int startIndex = strVal.indexOf(placeholderPrefix);\r
+ while (startIndex != -1) {\r
+ int endIndex = findPlaceholderEndIndex(buf, startIndex);\r
+ if (endIndex != -1) {\r
+ String placeholder = buf.substring(startIndex\r
+ + placeholderPrefix.length(), endIndex);\r
+ if (!visitedPlaceholders.add(placeholder)) {\r
+ throw new BeanDefinitionStoreException(\r
+ "Circular placeholder reference '" + placeholder\r
+ + "' in property definitions");\r
+ }\r
+ // Recursive invocation, parsing placeholders contained in\r
+ // the placeholder key.\r
+ placeholder = parseStringValue(bean, placeholder,\r
+ visitedPlaceholders);\r
+ // Now obtain the value for the fully resolved key...\r
+ String propVal = resolvePlaceholder(bean, placeholder);\r
+ if (propVal != null) {\r
+ // Recursive invocation, parsing placeholders contained\r
+ // in the\r
+ // previously resolved placeholder value.\r
+ propVal = parseStringValue(bean, propVal,\r
+ visitedPlaceholders);\r
+ buf.replace(startIndex,\r
+ endIndex + placeholderSuffix.length(), propVal);\r
+ if (log.isTraceEnabled()) {\r
+ log.trace("Resolved placeholder '" + placeholder + "'");\r
+ }\r
+ startIndex = buf.indexOf(placeholderPrefix, startIndex\r
+ + propVal.length());\r
+ } else {\r
+ throw new BeanDefinitionStoreException(\r
+ "Could not resolve placeholder '" + placeholder\r
+ + "'");\r
+ }\r
+ visitedPlaceholders.remove(placeholder);\r
+ } else {\r
+ startIndex = -1;\r
+ }\r
+ }\r
+\r
+ return buf.toString();\r
+ }\r
+\r
+ private int findPlaceholderEndIndex(CharSequence buf, int startIndex) {\r
+ int index = startIndex + placeholderPrefix.length();\r
+ int withinNestedPlaceholder = 0;\r
+ while (index < buf.length()) {\r
+ if (StringUtils.substringMatch(buf, index, placeholderSuffix)) {\r
+ if (withinNestedPlaceholder > 0) {\r
+ withinNestedPlaceholder--;\r
+ index = index + placeholderSuffix.length();\r
+ } else {\r
+ return index;\r
+ }\r
+ } else if (StringUtils\r
+ .substringMatch(buf, index, placeholderPrefix)) {\r
+ withinNestedPlaceholder++;\r
+ index = index + placeholderPrefix.length();\r
+ } else {\r
+ index++;\r
+ }\r
+ }\r
+ return -1;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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<Resource> {
+ private ExecutionResources executionResources;
+ private String relativePath;
+
+ public Resource getObject() throws Exception {
+ Assert.notNull(executionResources, "executionResources is null");
+ Assert.notNull(relativePath, "relativePath is null");
+ return executionResources.getWritableResource(relativePath);
+ }
+
+ public Class<? extends Object> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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> executionStack = new ThreadLocal<ExecutionStack>();
+ public final ThreadLocal<String> executionStackBeanName = new ThreadLocal<String>();
+
+ private final ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
+ private final ThreadLocal<String> executionContextBeanName = new ThreadLocal<String>();
+
+ 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> T dealWithSpecialScopedObject(String name,
+ ThreadLocal<T> threadLocal,
+ ThreadLocal<String> 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+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;
+
+/** 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 final AccessControlContext accessControlContext;
+
+ private List<Runnable> destructionCallbacks = new ArrayList<Runnable>();
+
+ public ExecutionThread(ProcessThreadGroup processThreadGroup, ExecutionModulesManager executionModulesManager,
+ RealizedFlow realizedFlow) {
+ super(processThreadGroup, "Flow " + realizedFlow.getFlowDescriptor().getName());
+ this.realizedFlow = realizedFlow;
+ this.executionModulesManager = executionModulesManager;
+ accessControlContext = AccessController.getContext();
+ }
+
+ 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 {
+ Subject subject = Subject.getSubject(accessControlContext);
+ try {
+ Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
+
+ @Override
+ public Void run() throws Exception {
+ 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
+ return null;
+ }
+
+ });
+ } catch (PrivilegedActionException privilegedActionException) {
+ throw (Exception) privilegedActionException.getCause();
+ }
+ } 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
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution;\r
+\r
+import java.util.Stack;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.execution.ExecutionFlow;\r
+import org.argeo.slc.execution.ExecutionSpecAttribute;\r
+\r
+/** Manage parameters that need to be set during the instantiation of a flow */\r
+public class InstantiationManager {\r
+\r
+ private final static Log log = LogFactory\r
+ .getLog(InstantiationManager.class);\r
+\r
+ private ThreadLocal<Stack<ExecutionFlow>> flowStack = new ThreadLocal<Stack<ExecutionFlow>>();\r
+\r
+ public Object createRef(String name) {\r
+\r
+ if ((flowStack.get() == null) || flowStack.get().empty()) {\r
+ throw new SlcException("No flow is currently initializing."\r
+ + " Declare ParameterRef as inner beans or prototypes.");\r
+ }\r
+\r
+ return getInitializingFlowParameter(name);\r
+ }\r
+\r
+ public void flowInitializationStarted(ExecutionFlow flow, String flowName) {\r
+ // set the flow name if it is DefaultExecutionFlow\r
+ if (flow instanceof DefaultExecutionFlow) {\r
+ ((DefaultExecutionFlow) flow).setBeanName(flowName);\r
+ }\r
+\r
+ if (log.isTraceEnabled())\r
+ log.trace("Start initialization of " + flow.hashCode() + " ("\r
+ + flow + " - " + flow.getClass() + ")");\r
+\r
+ // log.info("# flowInitializationStarted " + flowName);\r
+ // create a stack for this thread if there is none\r
+ if (flowStack.get() == null) {\r
+ flowStack.set(new Stack<ExecutionFlow>());\r
+ }\r
+ flowStack.get().push(flow);\r
+ }\r
+\r
+ public void flowInitializationFinished(ExecutionFlow flow, String flowName) {\r
+ if (log.isTraceEnabled())\r
+ log.trace("Finish initialization of " + flow.hashCode() + " ("\r
+ + flow + " - " + flow.getClass() + ")");\r
+\r
+ if (flowStack.get() != null) {\r
+ ExecutionFlow registeredFlow = flowStack.get().pop();\r
+ if (registeredFlow != null) {\r
+ if (!flow.getName().equals(registeredFlow.getName()))\r
+ throw new SlcException("Current flow is " + flow);\r
+ // log.info("# flowInitializationFinished " + flowName);\r
+ // initializingFlow.set(null);\r
+ }\r
+ } else {\r
+ // happens for flows imported as services\r
+ log.warn("flowInitializationFinished - Flow Stack is null");\r
+ }\r
+ }\r
+\r
+ protected ExecutionFlow findInitializingFlowWithParameter(String key) {\r
+ if ((flowStack.get() == null) || flowStack.get().empty())\r
+ throw new SlcException("No initializing flow available.");\r
+\r
+ // first look in the outer flow (that may override parameters)\r
+ for (int i = 0; i < flowStack.get().size(); i++) {\r
+ if (flowStack.get().elementAt(i).isSetAsParameter(key)) {\r
+ return flowStack.get().elementAt(i);\r
+ }\r
+ }\r
+ throw new SlcException("Key " + key + " is not set as parameter in "\r
+ + flowStack.get().firstElement().toString() + " (stack size="\r
+ + flowStack.get().size() + ")");\r
+\r
+ }\r
+\r
+ public Object getInitializingFlowParameter(String key) {\r
+ return findInitializingFlowWithParameter(key).getParameter(key);\r
+ }\r
+\r
+ public Class<?> getInitializingFlowParameterClass(String key) {\r
+ ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key)\r
+ .getExecutionSpec().getAttributes().get(key);\r
+ if (attr instanceof RefSpecAttribute)\r
+ return ((RefSpecAttribute) attr).getTargetClass();\r
+ else if (attr instanceof PrimitiveSpecAttribute) {\r
+ String type = ((PrimitiveSpecAttribute) attr).getType();\r
+ Class<?> clss = PrimitiveUtils.typeAsClass(type);\r
+ if (clss == null)\r
+ throw new SlcException("Cannot convert type " + type\r
+ + " to class.");\r
+ return clss;\r
+ } else\r
+ return null;\r
+ }\r
+\r
+ public Boolean isInFlowInitialization() {\r
+ return (flowStack.get() != null) && !flowStack.get().empty();\r
+ }\r
+}\r
--- /dev/null
+/*
+ * 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.argeo.slc.execution.ExecutionFlow;
+import org.argeo.slc.execution.ExecutionStack;
+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<String, Object> variables = Collections
+ .synchronizedMap(new HashMap<String, Object>());
+
+ private final String uuid;
+
+ private ApplicationContext applicationContext;
+ private ExecutionStack executionStack;
+
+ 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);
+
+ // if the variable was not found, look in the stack starting at the
+ // upper flows
+ if (value == null) {
+ value = executionStack.findLocalVariable(key);
+ }
+ return value;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ @Override
+ public void beforeFlow(ExecutionFlow executionFlow) {
+ // getUuid();
+ executionStack.enterFlow(executionFlow);
+ setVariable(ExecutionContext.VAR_FLOW_ID,
+ executionStack.getCurrentStackLevelUuid());
+ setVariable(ExecutionContext.VAR_FLOW_NAME, executionFlow.getName());
+ }
+
+ @Override
+ public void afterFlow(ExecutionFlow executionFlow) {
+ executionStack.leaveFlow(executionFlow);
+ }
+
+ @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;
+ }
+
+ public void setExecutionStack(ExecutionStack executionStack) {
+ this.executionStack = executionStack;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String> {
+ private ExecutionResources executionResources;
+ private Resource resource;
+ private Boolean overwrite = false;
+
+ /** Return an existing file on the file system. */
+ public String 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<? extends Object> 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
+ * <code>false</code>.
+ */
+ public void setOverwrite(Boolean overwrite) {
+ this.overwrite = overwrite;
+ }
+
+}
--- /dev/null
+/*
+ * 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<Object> {
+ 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 : "");
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+
+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;
+
+/**
+ * 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<ExecutionThread> executionThreads = Collections.synchronizedSet(new HashSet<ExecutionThread>());
+
+ // private Boolean hadAnError = false;
+ private Boolean killed = false;
+
+ private final AccessControlContext accessControlContext;
+
+ public ProcessThread(ThreadGroup processesThreadGroup, ExecutionModulesManager executionModulesManager,
+ ExecutionProcess process) {
+ super(processesThreadGroup, "SLC Process #" + process.getUuid());
+ this.executionModulesManager = executionModulesManager;
+ this.process = process;
+ processThreadGroup = new ProcessThreadGroup(process);
+ accessControlContext = AccessController.getContext();
+ }
+
+ 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 {
+ Subject subject = Subject.getSubject(accessControlContext);
+ try {
+ Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
+
+ @Override
+ public Void run() throws Exception {
+ process();
+ return null;
+ }
+
+ });
+ } catch (PrivilegedActionException privilegedActionException) {
+ Throwable cause = privilegedActionException.getCause();
+ if (cause instanceof InterruptedException)
+ throw (InterruptedException) cause;
+ else
+ throw new SlcException("Cannot process", cause);
+ }
+ // 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<RealizedFlow> flowsToProcess = new ArrayList<RealizedFlow>();
+ 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<ExecutionStep> newSteps = new ArrayList<ExecutionStep>();
+ 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;
+ }
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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;
+
+/** The thread group attached to a given {@link SlcExecution}. */
+public class ProcessThreadGroup extends ThreadGroup {
+// private final Authentication authentication;
+ private final static Integer STEPS_BUFFER_CAPACITY = 5000;
+
+ private BlockingQueue<ExecutionStep> steps = new ArrayBlockingQueue<ExecutionStep>(
+ STEPS_BUFFER_CAPACITY);
+
+ private Boolean hadAnError = false;
+
+ public ProcessThreadGroup(ExecutionProcess executionProcess) {
+ super("SLC Process #" + executionProcess.getUuid() + " thread group");
+// this.authentication = SecurityContextHolder.getContext()
+// .getAuthentication();
+ }
+
+// public Authentication getAuthentication() {
+// return authentication;
+// }
+
+ public void dispatchAddStep(ExecutionStep step) {
+ // ExecutionProcess slcProcess = processThread.getProcess();
+ // List<ExecutionStep> steps = new ArrayList<ExecutionStep>();
+ // 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<ExecutionStep> steps) {
+ // ExecutionProcess slcProcess = processThread.getProcess();
+ // executionModulesManager.dispatchAddSteps(slcProcess, steps);
+ // }
+
+ public BlockingQueue<ExecutionStep> getSteps() {
+ return steps;
+ }
+
+ public Boolean hadAnError() {
+ return hadAnError;
+ }
+}
--- /dev/null
+/*
+ * 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<RefValueChoice> 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<RefValueChoice> getChoices() {
+ return choices;
+ }
+
+ public void setChoices(List<RefValueChoice> 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 : "");
+ }
+
+}
--- /dev/null
+/*
+ * 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 + "]";
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<Resource>,
+ InitializingBean {
+ private Resource source;
+
+ private List<String> filters = new ArrayList<String>();
+ private Map<Pattern, String> patterns = new HashMap<Pattern, String>();
+
+ private String charset = "UTF-8";
+ private Charset cs;
+ private CharsetDecoder decoder;
+
+ // private CharsetEncoder encoder;
+
+ public Resource 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<String> tokens = new ArrayList<String>(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<String> filters) {
+ this.filters = filters;
+ }
+
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <bean id="slcDefault.executionResources" parent="slcTemplate.fileResources"
+ scope="execution" lazy-init="true">
+ <aop:scoped-proxy proxy-target-class="false" />
+ <property name="executionContext" ref="executionContext" />
+ </bean>
+
+ <bean id="slcDefault.writableResource" parent="slcTemplate.writableResource"
+ abstract="true">
+ <property name="executionResources" ref="slcDefault.executionResources" />
+ </bean>
+
+ <bean id="slcDefault.osFile" parent="slcTemplate.osFile" abstract="true">
+ <property name="executionResources" ref="slcDefault.executionResources" />
+ </bean>
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.Map;\r
+\r
+import org.argeo.slc.SlcException;\r
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
+\r
+/**\r
+ * Composite <code>RunnableFactory</code>, redirecting the Runnable \r
+ * creation to on of the configured <code>RunnableFactory</code> depending\r
+ * on an entry of the data of the <code>RunnableDataNode</code>.\r
+ */\r
+public class CompositeRunnableFactory implements RunnableFactory {\r
+\r
+ /**\r
+ * Key used to access factory ID in the data of the <code>RunnableDataNode</code>\r
+ */\r
+ private String factoryKey;\r
+\r
+ /**\r
+ * Maps a factory ID to an ExecutionFlowFactory\r
+ */\r
+ private Map<String, RunnableFactory> factories;\r
+\r
+ public void createAndRegisterRunnable(RunnableDataNode node,\r
+ BeanDefinitionRegistry beanDefinitionRegistry) {\r
+ findFactory(node).createAndRegisterRunnable(node, beanDefinitionRegistry);\r
+ } \r
+ \r
+ /**\r
+ * Finds the <code>RunnableFactory</code> to use for a <code>RunnableDataNode</code>\r
+ * @param node\r
+ * @return the <code>RunnableFactory</code> to use for the <code>RunnableDataNode</code>\r
+ */\r
+ private RunnableFactory findFactory(RunnableDataNode node) {\r
+ // get the factory ID from the data of the RunnableDescriptor\r
+ Map<String, Object> data = node.getData();\r
+ if (!data.containsKey(factoryKey)) {\r
+ throw new SlcException("No data value for key '" + factoryKey + "'");\r
+ }\r
+ String factoryId = data.get(factoryKey).toString();\r
+ \r
+ // see if we have a factory for the factory ID\r
+ if ((factories != null) && factories.containsKey(factoryId)) {\r
+ return factories.get(factoryId);\r
+ }\r
+ // if not, look for a bean of name equals to the factory ID\r
+ else {\r
+ throw new SlcException("Not implemented");\r
+ } \r
+ }\r
+ \r
+ public void setFactoryKey(String factoryKey) {\r
+ this.factoryKey = factoryKey;\r
+ }\r
+\r
+ public void setFactories(Map<String, RunnableFactory> factories) {\r
+ this.factories = factories;\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+/**\r
+ * Default implementation of <code>RunnableDataNode</code>\r
+ *\r
+ */\r
+public class DefaultRunnableDataNode implements RunnableDataNode {\r
+\r
+ private List<RunnableDataNode> children = new ArrayList<RunnableDataNode>();\r
+ \r
+ private RunnableDataNode parent;\r
+ \r
+ /**\r
+ * Data of the RunnableDataNode. Does not contain\r
+ * parent data.\r
+ */\r
+ private Map<String, Object> properData = new HashMap<String, Object>();\r
+ \r
+ private String path;\r
+ \r
+ private String beanName;\r
+\r
+ public boolean isLeaf() {\r
+ return children.size() == 0;\r
+ }\r
+ \r
+ public List<RunnableDataNode> getChildren() {\r
+ return children;\r
+ }\r
+\r
+ public void addChild(RunnableDataNode child) {\r
+ child.setParent(this);\r
+ children.add(child);\r
+ }\r
+ \r
+ public Map<String, Object> getData() {\r
+ Map<String, Object> data = new HashMap<String, Object>();\r
+ if(parent != null) {\r
+ Map<String, Object> parentData = parent.getData();\r
+ if(parentData != null) {\r
+ data.putAll(parentData);\r
+ }\r
+ }\r
+ // entries defined in parentData can be overridden\r
+ // in properData\r
+ if(properData != null) {\r
+ data.putAll(properData);\r
+ }\r
+ return data;\r
+ }\r
+\r
+ public Map<String, Object> getProperData() {\r
+ return properData;\r
+ }\r
+\r
+ public void setProperData(Map<String, Object> properData) {\r
+ this.properData = properData;\r
+ }\r
+\r
+ public String getPath() {\r
+ return path;\r
+ }\r
+\r
+ public void setPath(String path) {\r
+ this.path = path;\r
+ }\r
+\r
+ public String getBeanName() {\r
+ return beanName;\r
+ }\r
+\r
+ public void setBeanName(String beanName) {\r
+ this.beanName = beanName;\r
+ }\r
+\r
+ public void setParent(RunnableDataNode parent) {\r
+ this.parent = parent;\r
+ }\r
+\r
+ public RunnableDataNode getParent() {\r
+ return parent;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.HashMap;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.springframework.aop.scope.ScopedProxyUtils;\r
+import org.springframework.beans.BeansException;\r
+import org.springframework.beans.MutablePropertyValues;\r
+import org.springframework.beans.factory.config.BeanDefinitionHolder;\r
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;\r
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;\r
+import org.springframework.beans.factory.config.RuntimeBeanReference;\r
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
+import org.springframework.beans.factory.support.GenericBeanDefinition;\r
+import org.springframework.core.Ordered;\r
+\r
+/**\r
+ * Generates <code>ExecutionFlows</code> and <code>Runnables</code> as\r
+ * beans in the Spring Application Context.\r
+ * Called by the Application Context as a <code>BeanFactoryPostProcessor</code>.\r
+ * Two kinds of beans are generated:\r
+ * <code>RunnableCallFlow</code>, calling a list of <code>Runnables</code> from the\r
+ * Application Context after configuring the <code>ExecutionContext</code>, \r
+ * and outputs of a <code>RunnableFactory</code>.\r
+ */\r
+public class ExecutionFlowGenerator implements BeanFactoryPostProcessor,\r
+ Ordered {\r
+ \r
+ private final Log log = LogFactory.getLog(getClass());\r
+\r
+ /**\r
+ * Source providing a list of <code>RunnableCallFlowDescriptor</code> \r
+ * used to create <code>RunnableCallFlow</code> and a list of \r
+ * <code>RunnableDataNode</code> used to create any kind of flow via a factory\r
+ */\r
+ protected ExecutionFlowGeneratorSource source;\r
+ \r
+ /**\r
+ * Factory used to create Runnables in the Application context from\r
+ * the <code>RunnableDataNode</code> provided from the source.\r
+ */\r
+ protected RunnableFactory runnableFactory;\r
+ \r
+ /**\r
+ * Bean name of the <code>ExecutionContext</code>.\r
+ * Used to provide the created <code>RunnableCallFlow</code> beans \r
+ * with a <code>RuntimeBeanReference</code> to\r
+ * the <code>ExecutionContext</code>\r
+ */\r
+ private String executionContextBeanName = "executionContext";\r
+ \r
+ /**\r
+ * Bean name of the context values Map.\r
+ * A bean of class HashMap is created with this name, and a \r
+ * <code>RuntimeBeanReference</code> is provided to the created\r
+ * <code>RunnableCallFlow</code> beans.\r
+ */\r
+ private String contextValuesBeanName = "executionFlowGenerator.contextValues";\r
+ \r
+ /**\r
+ * Prefix added to the bean names defined in each \r
+ * <code>RunnableCallFlowDescriptor</code>\r
+ */\r
+ private String flowBeanNamesPrefix = "";\r
+ \r
+ private int order = Ordered.HIGHEST_PRECEDENCE;\r
+ \r
+ public void postProcessBeanFactory(\r
+ ConfigurableListableBeanFactory beanFactory) throws BeansException {\r
+\r
+ // assert that the beanFactory is a BeanDefinitionRegistry\r
+ if (!(beanFactory instanceof BeanDefinitionRegistry)) {\r
+ throw new SlcException("Can only work on "\r
+ + BeanDefinitionRegistry.class);\r
+ } \r
+ \r
+ // add bean for the Context Values Map\r
+ createAndRegisterContextValuesBean((BeanDefinitionRegistry) beanFactory);\r
+ \r
+ // add beans for each RunnableDataNode\r
+ for(RunnableDataNode node : source.getRunnableDataNodes()) {\r
+ runnableFactory.createAndRegisterRunnable(node, (BeanDefinitionRegistry) beanFactory);\r
+ }\r
+ \r
+ // add beans for each RunnableCallFlowDescriptor of the source to the application context\r
+ for (RunnableCallFlowDescriptor descriptor : source\r
+ .getRunnableCallFlowDescriptors()) {\r
+ createAndRegisterFlowFor(descriptor, (BeanDefinitionRegistry) beanFactory);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Creates a <code>RunnableCallFlow</code> bean\r
+ * for a <code>RunnableCallFlowDescriptor</code> and registers \r
+ * it in the <code>BeanDefinitionRegistry</code>\r
+ * @param flowDescriptor\r
+ * @param registry\r
+ */\r
+ private void createAndRegisterFlowFor(RunnableCallFlowDescriptor flowDescriptor, BeanDefinitionRegistry registry) {\r
+ // create the flow bean\r
+ GenericBeanDefinition flowBean = new GenericBeanDefinition();\r
+ flowBean.setBeanClass(RunnableCallFlow.class);\r
+ \r
+ String beanName = flowBeanNamesPrefix + flowDescriptor.getBeanName();\r
+ \r
+ MutablePropertyValues mpv = new MutablePropertyValues(); \r
+ mpv.addPropertyValue("runnableCalls", flowDescriptor.getRunnableCalls());\r
+ mpv.addPropertyValue("sharedContextValuesMap", new RuntimeBeanReference(contextValuesBeanName));\r
+ \r
+ mpv.addPropertyValue("name", beanName);\r
+ mpv.addPropertyValue("path", flowDescriptor.getPath());\r
+\r
+ mpv.addPropertyValue("executionContext", new RuntimeBeanReference(executionContextBeanName));\r
+ \r
+ flowBean.setPropertyValues(mpv);\r
+ \r
+ // register it\r
+ if(log.isDebugEnabled()) {\r
+ log.debug("Registering bean definition for RunnableCallFlow " + beanName);\r
+ }\r
+ registry.registerBeanDefinition(beanName, flowBean);\r
+ }\r
+ \r
+ /**\r
+ * Creates the Context Values bean and register it in the\r
+ * <code>BeanDefinitionRegistry</code>\r
+ * @param registry\r
+ */\r
+ private void createAndRegisterContextValuesBean(BeanDefinitionRegistry registry) {\r
+ GenericBeanDefinition contextValuesBean = new GenericBeanDefinition();\r
+ contextValuesBean.setBeanClass(HashMap.class);\r
+ \r
+ BeanDefinitionHolder bdh = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(contextValuesBean, contextValuesBeanName), registry, true); \r
+ registry.registerBeanDefinition(contextValuesBeanName, bdh.getBeanDefinition()); \r
+ }\r
+ \r
+ public int getOrder() {\r
+ return order;\r
+ }\r
+\r
+ public void setOrder(int order) {\r
+ this.order = order;\r
+ }\r
+\r
+ public void setSource(ExecutionFlowGeneratorSource source) {\r
+ this.source = source;\r
+ }\r
+\r
+ public void setRunnableFactory(RunnableFactory runnableFactory) {\r
+ this.runnableFactory = runnableFactory;\r
+ }\r
+\r
+ public void setExecutionContextBeanName(String executionContextBeanName) {\r
+ this.executionContextBeanName = executionContextBeanName;\r
+ }\r
+\r
+ public void setContextValuesBeanName(String contextValuesBeanName) {\r
+ this.contextValuesBeanName = contextValuesBeanName;\r
+ }\r
+\r
+ public void setFlowBeanNamesPrefix(String flowBeanNamesPrefix) {\r
+ this.flowBeanNamesPrefix = flowBeanNamesPrefix;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * Provides 2 types of information required by an <code>ExecutionFlowGenerator</code>: \r
+ * a list of <code>RunnableCallFlowDescriptor</code> used to create <code>RunnableCallFlow</code>\r
+ * and a list of <code>RunnableDataNode</code> used to create any kind of flow via a factory.\r
+ */\r
+public interface ExecutionFlowGeneratorSource {\r
+ \r
+ /**\r
+ * @return a list of <code>RunnableCallFlowDescriptor</code> used \r
+ * by a <code>ExecutionFlowGenerator</code> to create <code>RunnableCallFlow</code>\r
+ */\r
+ public List<RunnableCallFlowDescriptor> getRunnableCallFlowDescriptors();\r
+ \r
+ /**\r
+ * @return a list of <code>RunnableDataNode</code> used \r
+ * by a <code>ExecutionFlowGenerator</code> to create any kind of flow via a factory\r
+ */\r
+ public List<RunnableDataNode> getRunnableDataNodes();\r
+ \r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.Map;\r
+\r
+/**\r
+ * Storage class for information required to call a flow \r
+ * of the Spring execution context: \r
+ * bean name of the flow,\r
+ * variables to add to the Execution Context before the call \r
+ * and variables (context values) to add to a Map \r
+ * potentially referenced by the called flow \r
+ */\r
+public class RunnableCall {\r
+ \r
+ /**\r
+ * Bean name of the flow to call\r
+ */\r
+ private String beanName;\r
+ \r
+ /**\r
+ * Variables to add to the execution context before the call\r
+ */\r
+ private Map<String, Object> executionVariables;\r
+ \r
+ /**\r
+ * Variables to add to the Map potentially referenced by\r
+ * the called flow\r
+ */\r
+ private Map<String, Object> contextValues;\r
+\r
+ public String getBeanName() {\r
+ return beanName;\r
+ }\r
+\r
+ public void setBeanName(String beanName) {\r
+ this.beanName = beanName;\r
+ }\r
+\r
+ public Map<String, Object> getExecutionVariables() {\r
+ return executionVariables;\r
+ }\r
+\r
+ public void setExecutionVariables(Map<String, Object> executionVariables) {\r
+ this.executionVariables = executionVariables;\r
+ }\r
+\r
+ public Map<String, Object> getContextValues() {\r
+ return contextValues;\r
+ }\r
+\r
+ public void setContextValues(Map<String, Object> contextValues) {\r
+ this.contextValues = contextValues;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.core.execution.DefaultExecutionSpec;\r
+import org.argeo.slc.execution.ExecutionContext;\r
+import org.argeo.slc.execution.ExecutionFlow;\r
+import org.argeo.slc.execution.ExecutionSpec;\r
+import org.springframework.context.ApplicationContext;\r
+import org.springframework.context.ApplicationContextAware;\r
+\r
+/**\r
+ * Execution Flow calling a list of <code>Runnable</code> (identified by their\r
+ * bean name in the Spring Application Context) after configuring the Execution\r
+ * context and a Map potentially shared by the called <code>Runnable</code>\r
+ * \r
+ */\r
+public class RunnableCallFlow implements ExecutionFlow, ApplicationContextAware {\r
+\r
+ private final static Log log = LogFactory.getLog(RunnableCallFlow.class);\r
+\r
+ /**\r
+ * Key in the execution context for the index of the call (e.g. 0 for the\r
+ * first runnable called, ...)\r
+ */\r
+ public final static String VAR_CALL_INDEX = "slcVar.runnableCallFlow.callIndex";\r
+\r
+ /**\r
+ * Name of the flow. Also bean name\r
+ */\r
+ private String name;\r
+\r
+ /**\r
+ * Path of the flow\r
+ */\r
+ private String path;\r
+\r
+ /**\r
+ * Whether an exception in a <code>Runnable</code> shall stop the execution\r
+ * of the flow\r
+ */\r
+ private Boolean failOnError = true;\r
+\r
+ /**\r
+ * List of <code>Runnable</code> to call, with bean name, execution\r
+ * variables and context values\r
+ */\r
+ private List<RunnableCall> runnableCalls;\r
+\r
+ /**\r
+ * Map potentially referenced by called flows. Updated with the context\r
+ * values of a Runnable before calling it.\r
+ */\r
+ private Map<String, Object> sharedContextValuesMap;\r
+\r
+ /**\r
+ * ExecutionSpec of the flow. Does not contain any attribute.\r
+ */\r
+ private ExecutionSpec executionSpec = new DefaultExecutionSpec();\r
+\r
+ /**\r
+ * Reference to the ExecutionContext\r
+ */\r
+ private ExecutionContext executionContext;\r
+\r
+ /**\r
+ * Reference to the Spring <code>ApplicationContext</code>. Set via\r
+ * <code>setApplicationContext</code>, the class implementing\r
+ * <code>ApplicationContextAware</code>\r
+ */\r
+ private ApplicationContext applicationContext;\r
+\r
+ /**\r
+ * Runs a <code>Runnable</code> after configuring the Execution Context and\r
+ * <code>sharedContextValuesMap</code>\r
+ * \r
+ * @param runnable\r
+ * the <code>Runnable</code> to call\r
+ * @param executionVariables\r
+ * the variables to add to the <code>ExecutionContext</code>\r
+ * @param contextValues\r
+ * the variables to add to <code>sharedContextValuesMap</code>\r
+ * @param callIndex\r
+ * index of the call (0 for the first called\r
+ * <code>Runnable</code>) set as variable of the\r
+ * <code>ExecutionContext</code>\r
+ */\r
+ private void run(Runnable runnable, Map<String, Object> executionVariables,\r
+ Map<String, Object> contextValues, int callIndex) {\r
+ // add all variables to the Execution Context\r
+ for (Map.Entry<String, Object> entry : executionVariables.entrySet()) {\r
+ executionContext.setVariable(entry.getKey(), entry.getValue());\r
+ }\r
+\r
+ // add call Index Variable\r
+ executionContext.setVariable(VAR_CALL_INDEX, callIndex);\r
+\r
+ // clear sharedContextValues and add all values of contextValues\r
+ if (sharedContextValuesMap != null) {\r
+ sharedContextValuesMap.clear();\r
+ sharedContextValuesMap.putAll(contextValues);\r
+ }\r
+\r
+ // then run the runnable\r
+ doExecuteRunnable(runnable);\r
+ }\r
+\r
+ public void doExecuteRunnable(Runnable runnable) {\r
+ runnable.run();\r
+ }\r
+\r
+ /**\r
+ * Executes the flow. For each <code>RunnableCall</code>, the corresponding\r
+ * flow is retrieved from the Spring Application Context, the\r
+ * <code>ExecutionContext</code> and <code>sharedContextValuesMap</code> are\r
+ * configured and the <code>Runnable</code> is called.\r
+ */\r
+ public void run() {\r
+ if (applicationContext == null) {\r
+ throw new SlcException("No ApplicationContext defined");\r
+ }\r
+\r
+ try {\r
+ for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
+ RunnableCall runnableCall = runnableCalls.get(callIndex);\r
+ Object bean = applicationContext.getBean(\r
+ runnableCall.getBeanName(), Runnable.class);\r
+ if (log.isDebugEnabled())\r
+ log.debug("Running flow '" + runnableCall.getBeanName()\r
+ + "'");\r
+ run((Runnable) bean, runnableCall.getExecutionVariables(),\r
+ runnableCall.getContextValues(), callIndex);\r
+ }\r
+ } catch (RuntimeException e) {\r
+ if (failOnError)\r
+ throw e;\r
+ else {\r
+ log.error("Execution flow failed,"\r
+ + " but process did not fail"\r
+ + " because failOnError property"\r
+ + " is set to false: " + e);\r
+ if (log.isTraceEnabled())\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ public Iterator<Runnable> runnables() {\r
+ List<Runnable> runnables = new ArrayList<Runnable>();\r
+ for (int callIndex = 0; callIndex < runnableCalls.size(); ++callIndex) {\r
+ RunnableCall runnableCall = runnableCalls.get(callIndex);\r
+ Object bean = applicationContext.getBean(\r
+ runnableCall.getBeanName(), Runnable.class);\r
+ runnables.add((Runnable) bean);\r
+ }\r
+ return runnables.iterator();\r
+ }\r
+\r
+ public Runnable getRunnable() {\r
+ if (runnableCalls.size() == 1)\r
+ return runnables().next();\r
+ else\r
+ throw new SlcException("There are " + runnableCalls.size()\r
+ + " runnables in flow " + getName());\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ return new StringBuffer("RunnableCallFlow ").append(name).toString();\r
+ }\r
+\r
+ public ExecutionSpec getExecutionSpec() {\r
+ return executionSpec;\r
+ }\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public Object getParameter(String key) {\r
+ throw new SlcException("RunnableCallFlow have no parameters");\r
+ }\r
+\r
+ public String getPath() {\r
+ return path;\r
+ }\r
+\r
+ public Boolean isSetAsParameter(String key) {\r
+ // The ExecutionSpec having no attribute,\r
+ // always return false\r
+ return false;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public void setPath(String path) {\r
+ this.path = path;\r
+ }\r
+\r
+ public void setExecutionContext(ExecutionContext executionContext) {\r
+ this.executionContext = executionContext;\r
+ }\r
+\r
+ public void setRunnableCalls(List<RunnableCall> runnableCalls) {\r
+ this.runnableCalls = runnableCalls;\r
+ }\r
+\r
+ public void setApplicationContext(ApplicationContext applicationContext) {\r
+ this.applicationContext = applicationContext;\r
+ }\r
+\r
+ public void setSharedContextValuesMap(Map<String, Object> contextValues) {\r
+ this.sharedContextValuesMap = contextValues;\r
+ }\r
+\r
+ public void setFailOnError(Boolean failOnError) {\r
+ this.failOnError = failOnError;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * Storage Class for information required to\r
+ * instantiate a <code>RunnableCallFlow</code>:\r
+ * bean name of the flow, \r
+ * path of the flow \r
+ * and list of <code>RunnableCall</code>. \r
+ *\r
+ */\r
+public class RunnableCallFlowDescriptor {\r
+ \r
+ /**\r
+ * Bean name of the flow to instantiate\r
+ */\r
+ private String beanName;\r
+ \r
+ /**\r
+ * Path of the flow to instantiate\r
+ */\r
+ private String path;\r
+ \r
+ /**\r
+ * List of <code>RunnableCall</code> \r
+ */\r
+ private List<RunnableCall> runnableCalls = new ArrayList<RunnableCall>();\r
+\r
+ public String getBeanName() {\r
+ return beanName;\r
+ }\r
+\r
+ public void setBeanName(String beanName) {\r
+ this.beanName = beanName;\r
+ }\r
+\r
+ public String getPath() {\r
+ return path;\r
+ }\r
+\r
+ public void setPath(String path) {\r
+ this.path = path;\r
+ }\r
+\r
+ public List<RunnableCall> getRunnableCalls() {\r
+ return runnableCalls;\r
+ }\r
+\r
+ public void setRunnableCalls(List<RunnableCall> runnableCalls) {\r
+ this.runnableCalls = runnableCalls;\r
+ }\r
+ \r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+/**\r
+ * Stores information relative to a Runnable.\r
+ * Allows to structure the information as a tree, each node\r
+ * storing data as a Map.\r
+ */\r
+public interface RunnableDataNode {\r
+\r
+ /**\r
+ * @return a Map containing the data associated with this node.\r
+ * Data associated with parent nodes are expected\r
+ * to be contained in the returned Map\r
+ */\r
+ public Map<String, Object> getData(); \r
+\r
+ /**\r
+ * @return the name of the bean to create.\r
+ * Can be null if no bean shall be created for the \r
+ * <code>RunnableDataNode</code> (e.g. is is a sub-node)\r
+ */\r
+ public String getBeanName();\r
+ \r
+ /**\r
+ * @return the path of the flow bean to create.\r
+ * Can be null if the bean to created is not an\r
+ * <code>ExecutionFlow</code> or if no bean shall be created for the \r
+ * <code>RunnableDataNode</code> (e.g. is is a sub-node)\r
+ */\r
+ public String getPath();\r
+ \r
+ /**\r
+ * @return whether the <code>RunnableDataNode</code> has\r
+ * children or not.\r
+ * Expected to be equivalent to <code>getChildren().empty()</code>\r
+ */\r
+ public boolean isLeaf();\r
+\r
+ /**\r
+ * @return the list of <code>RunnableDataNode</code> children.\r
+ * Can be empty. Shall not be null.\r
+ */\r
+ public List<RunnableDataNode> getChildren();\r
+ \r
+ /**\r
+ * @return the <code>RunnableDataNode</code> parent.\r
+ * Can be null if no parent is defined (top node).\r
+ */\r
+ public RunnableDataNode getParent();\r
+ \r
+ /**\r
+ * Sets the <code>RunnableDataNode</code> parent\r
+ * @param parent\r
+ */\r
+ public void setParent(RunnableDataNode parent); \r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.generator;\r
+\r
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;\r
+\r
+/**\r
+ * Interprets a <code>RunnableDataNode</code> by creating corresponding\r
+ * beans and registering them in a <code>BeanDefinitionRegistry</code>\r
+ *\r
+ */\r
+public interface RunnableFactory {\r
+\r
+ public void createAndRegisterRunnable(RunnableDataNode node,\r
+ BeanDefinitionRegistry beanDefinitionRegistry);\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <description>Bare minimal runtime configuration. In general you will
+ want to use simple.xml instead.
+ </description>
+
+ <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+ <property name="scopes">
+ <map>
+ <entry key="execution">
+ <bean class="org.argeo.slc.core.execution.ExecutionScope" />
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+
+ <bean id="executionStack" class="org.argeo.slc.core.execution.DefaultExecutionStack"
+ scope="execution">
+ <aop:scoped-proxy proxy-target-class="false" />
+ </bean>
+
+ <bean id="instantiationManager" class="org.argeo.slc.core.execution.InstantiationManager" />
+
+ <bean class="org.argeo.slc.core.execution.ExecutionParameterPostProcessor">
+ <property name="executionContext" ref="executionContext" />
+ <property name="instantiationManager" ref="instantiationManager" />
+ </bean>
+
+ <!-- <bean class="org.argeo.slc.core.execution.ExecutionAspect"> -->
+ <!-- <property name="executionStack" ref="executionStack" /> -->
+ <!-- <property name="executionContext" ref="executionContext" /> -->
+ <!-- </bean> -->
+
+ <aop:aspectj-autoproxy />
+
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <description>Default Capabilities</description>
+
+ <import resource="runtime.xml" />
+
+ <bean id="executionContext" class="org.argeo.slc.core.execution.MapExecutionContext"
+ scope="execution">
+ <aop:scoped-proxy proxy-target-class="false" />
+ <property name="executionStack" ref="executionStack" />
+ </bean>
+
+ <bean id="executionFlowDescriptorConverter"
+ class="org.argeo.slc.core.execution.DefaultExecutionFlowDescriptorConverter"></bean>
+
+ <bean
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
+ <property name="ignoreUnresolvablePlaceholders" value="true" />
+ </bean>
+
+ <bean id="parameterRef" class="org.argeo.slc.core.execution.ParameterRef"
+ abstract="true">
+ <property name="instantiationManager" ref="instantiationManager" />
+ </bean>
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="specAttr.primitive" class="org.argeo.slc.core.execution.PrimitiveSpecAttribute"
+ abstract="true" />
+ <bean id="specAttr.resource" class="org.argeo.slc.core.execution.ResourceSpecAttribute"
+ abstract="true" />
+ <bean id="specAttr.ref" class="org.argeo.slc.core.execution.RefSpecAttribute"
+ abstract="true" />
+
+ <bean id="slcTemplate.simpleFlow" class="org.argeo.slc.core.execution.DefaultExecutionFlow"
+ abstract="true" />
+ <bean id="slcTemplate.simpleSpec" class="org.argeo.slc.core.execution.DefaultExecutionSpec"
+ abstract="true" />
+
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <description>
+ 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.
+ </description>
+
+ <import resource="simple.xml" />
+
+ <import resource="specs.xml" />
+ <import resource="templates.xml" />
+ <import resource="defaults.xml" />
+ <import resource="utils.xml" />
+ <import resource="tasks/core.xml" />
+
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<Resource> classpath = new ArrayList<Resource>();
+ private List<Resource> pBootClasspath = new ArrayList<Resource>();
+ private Resource jvm = null;
+ private String mainClass;
+ private String mainJar;
+ private List<String> jvmArgs = new ArrayList<String>();
+ private List<String> args = new ArrayList<String>();
+
+ private String systemPropertiesFileProperty = null;
+ private String systemPropertiesFileDir = null;
+ private String systemPropertiesFileName = null;
+
+ public void afterPropertiesSet() throws Exception {
+ List<Object> command = new ArrayList<Object>();
+ 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<Object, Object> 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<Resource> getClasspath() {
+ return classpath;
+ }
+
+ public void setClasspath(List<Resource> classpath) {
+ this.classpath = classpath;
+ }
+
+ public List<Resource> getPBootClasspath() {
+ return pBootClasspath;
+ }
+
+ public void setPBootClasspath(List<Resource> 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<String> getJvmArgs() {
+ return jvmArgs;
+ }
+
+ public void setJvmArgs(List<String> jvmArgs) {
+ this.jvmArgs = jvmArgs;
+ }
+
+ public List<String> getArgs() {
+ return args;
+ }
+
+ public void setArgs(List<String> 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<List<Object>> {
+ private List<List<Object>> lists = new ArrayList<List<Object>>();
+
+ public void setLists(List<List<Object>> lists) {
+ this.lists = lists;
+ }
+
+ public List<Object> getObject() throws Exception {
+ List<Object> merged = new ArrayList<Object>();
+ for (List<Object> lst : lists) {
+ merged.addAll(lst);
+ }
+ return merged;
+ }
+
+ public Class<?> getObjectType() {
+ return List.class;
+ }
+
+ public boolean isSingleton() {
+ return false;
+ }
+
+}
--- /dev/null
+/*
+ * 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<Object> args = new ArrayList<Object>();
+
+ 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<Object> args) {
+ this.args = args;
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.tasks;\r
+\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.core.test.context.SimpleContextAware;\r
+import org.argeo.slc.test.context.ContextAware;\r
+\r
+/**\r
+ * Overrides Values and Expected values of a target \r
+ * <code>SimpleContextAware</code> with the corresponding\r
+ * values and expected values of a source <code>ContextAware</code>\r
+ *\r
+ */\r
+public class OverrideContextAware implements Runnable {\r
+\r
+ private ContextAware source;\r
+\r
+ private SimpleContextAware target;\r
+ \r
+ /**\r
+ * Whether an exception shall be thrown if a value\r
+ * or expected value of the source is not defined\r
+ * in the target\r
+ */\r
+ private Boolean failIfUndefinedInSource = true;\r
+ \r
+ public void run() {\r
+ // override values\r
+ if(source.getValues() != null)\r
+ for(String key : source.getValues().keySet()) {\r
+ if(failIfUndefinedInSource && !target.getValues().containsKey(key)) {\r
+ throw new SlcException("No entry in target values for key '" + key + "'");\r
+ }\r
+ target.getValues().put(key, source.getValues().get(key));\r
+ }\r
+ \r
+ // override expected values\r
+ if(source.getExpectedValues() != null)\r
+ for(String key : source.getExpectedValues().keySet()) {\r
+ if(failIfUndefinedInSource && !target.getExpectedValues().containsKey(key)) {\r
+ throw new SlcException("No entry in target expected values for key '" + key + "'");\r
+ }\r
+ target.getExpectedValues().put(key, source.getExpectedValues().get(key));\r
+ } \r
+ } \r
+ \r
+ public void setSource(ContextAware source) {\r
+ this.source = source;\r
+ }\r
+\r
+ public void setTarget(SimpleContextAware target) {\r
+ this.target = target;\r
+ }\r
+\r
+ public void setFailIfUndefinedInSource(Boolean failIfUndefinedInSource) {\r
+ this.failIfUndefinedInSource = failIfUndefinedInSource;\r
+ } \r
+}\r
--- /dev/null
+/*
+ * 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;
+
+/** 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<Object> 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<SystemCallOutputListener> outputListeners = Collections
+ .synchronizedList(new ArrayList<SystemCallOutputListener>());
+
+ private Map<String, List<Object>> osCommands = new HashMap<String, List<Object>>();
+ private Map<String, String> osCmds = new HashMap<String, String>();
+ private Map<String, String> environmentVariables = new HashMap<String, String>();
+
+ 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";
+ @SuppressWarnings("unused")
+ private boolean firstLine = true;
+ @SuppressWarnings("unused")
+ 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<Object> 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<Object>();
+ 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<String, String> environmentVariablesToUse = null;
+ environmentVariablesToUse = new HashMap<String, String>();
+ 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<Object> 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<Object>();
+ command.add(arg);
+ return this;
+ }
+
+ /** Append the argument (for chaining) */
+ public SystemCall arg(String arg, String value) {
+ if (command == null)
+ command = new ArrayList<Object>();
+ 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<Object> 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<String, List<Object>> osCommands) {
+ this.osCommands = osCommands;
+ }
+
+ public void setOsCmds(Map<String, String> osCmds) {
+ this.osCmds = osCmds;
+ }
+
+ public void setEnvironmentVariables(Map<String, String> environmentVariables) {
+ this.environmentVariables = environmentVariables;
+ }
+
+ public Map<String, String> 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<SystemCallOutputListener> 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() {
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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<Attachment, Resource> attachments = new HashMap<Attachment, Resource>();
+ private List<AttachmentsEnabled> attachTo = new ArrayList<AttachmentsEnabled>();
+ 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<Attachment, Resource> attachments) {
+ this.attachments = attachments;
+ }
+
+ public void setAttachTo(List<AttachmentsEnabled> 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;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="task.echo" class="org.argeo.slc.core.execution.tasks.Echo"
+ abstract="true" />
+ <bean id="task.systemCall" class="org.argeo.slc.core.execution.tasks.SystemCall"
+ abstract="true" />
+ <bean id="task.closeTestResult" class="org.argeo.slc.core.execution.tasks.CloseTestResult"
+ abstract="true" />
+ <bean id="task.slcManager" class="org.argeo.slc.core.execution.tasks.SlcManager"
+ abstract="true" />
+ <bean id="task.overrideContextAware" class="org.argeo.slc.core.execution.tasks.OverrideContextAware"
+ abstract="true" />
+ <bean id="task.uploadAttachments" class="org.argeo.slc.core.execution.tasks.UploadAttachments"
+ abstract="true" />
+
+ <bean id="taskArg.attachment" class="org.argeo.slc.core.attachment.SimpleAttachment"
+ abstract="true" />
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <bean id="slcTemplate.fileResources" class="org.argeo.slc.core.execution.FileExecutionResources"
+ abstract="true" />
+
+ <bean id="slcTemplate.resourcesFactoryBean" parent="slcTemplate.writableResource"
+ abstract="true" />
+
+ <bean id="slcTemplate.writableResource"
+ class="org.argeo.slc.core.execution.ExecutionResourcesFactoryBean"
+ abstract="true" />
+
+ <bean id="slcTemplate.osFile" class="org.argeo.slc.core.execution.OsFileFactoryBean"
+ abstract="true" />
+
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:aop="http://www.springframework.org/schema/aop"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+ <bean id="mergedLists" class="org.argeo.slc.core.execution.tasks.MergedLists"
+ abstract="true">
+ </bean>
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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.BeanMetadataElement;
+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);
+
+ 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<BeanMetadataElement> executables = new ManagedList<BeanMetadataElement>(
+ 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;
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.execution.xml;\r
+\r
+import org.springframework.aop.scope.ScopedProxyUtils;\r
+import org.springframework.beans.factory.config.BeanDefinitionHolder;\r
+import org.springframework.beans.factory.parsing.BeanComponentDefinition;\r
+import org.springframework.beans.factory.xml.BeanDefinitionDecorator;\r
+import org.springframework.beans.factory.xml.ParserContext;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.Node;\r
+\r
+/**\r
+ * Inspired by org.springframework.aop.config.ScopedProxyBeanDefinitionDecorator\r
+ */\r
+public class ExecutionScopeDecorator implements BeanDefinitionDecorator { \r
+ private static final String PROXY_TARGET_CLASS = "proxy-target-class"; \r
+ \r
+ public BeanDefinitionHolder decorate(Node node,\r
+ BeanDefinitionHolder definition, ParserContext parserContext) {\r
+ \r
+ definition.getBeanDefinition().setScope("execution");\r
+ \r
+ // Default: CGLib not used\r
+ boolean proxyTargetClass = false;\r
+ if (node instanceof Element) {\r
+ Element ele = (Element) node;\r
+ if (ele.hasAttribute(PROXY_TARGET_CLASS)) {\r
+ proxyTargetClass = Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS)).booleanValue();\r
+ }\r
+ }\r
+ \r
+ // Register the original bean definition as it will be referenced by the scoped proxy and is relevant for tooling (validation, navigation).\r
+ String targetBeanName = ScopedProxyUtils.getTargetBeanName(definition.getBeanName());\r
+ parserContext.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(definition.getBeanDefinition(), targetBeanName));\r
+ \r
+ return ScopedProxyUtils.createScopedProxy(definition, parserContext.getRegistry(), proxyTargetClass); \r
+ }\r
+}\r
--- /dev/null
+/*
+ * 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 <flow:flow> 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;
+
+ @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 <flow:flow name=\"/my/path/flowName\">.");
+ 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<Element> argsElems = new ArrayList<Element>();
+ List<Element> execElems = new ArrayList<Element>();
+ List<Element> specElems = new ArrayList<Element>();
+ 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<String, Object> args = new ManagedMap<String, Object>(
+ 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<Object> executables = new ManagedList<Object>(
+ 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<? extends ExecutionFlow> getBeanClass(Element element) {
+ String clss = element.getAttribute("class");
+ if (StringUtils.hasText(clss))
+ // TODO: check that it actually works
+ try {
+ return (Class<? extends ExecutionFlow>) getClass()
+ .getClassLoader().loadClass(clss);
+ } catch (ClassNotFoundException e) {
+ try {
+ return (Class<? extends ExecutionFlow>) 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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<ParameterRef> getBeanClass(Element element) {
+ return ParameterRef.class;
+ }
+}
--- /dev/null
+/*
+ * 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 <flow:spec> tag */
+public class SpecBeanDefinitionParser extends
+ AbstractSingleBeanDefinitionParser {
+ private Log log = LogFactory.getLog(SpecBeanDefinitionParser.class);
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext,
+ BeanDefinitionBuilder builder) {
+ builder.getBeanDefinition().setDescription(
+ DomUtils.getChildElementValueByTagName(element, "description"));
+
+ ManagedMap<String, BeanDefinition> attributes = new ManagedMap<String, BeanDefinition>();
+
+ // Primitives
+ for (Element child : (List<Element>) 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<Element>) 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<Element> choices = DomUtils.getChildElementsByTagName(
+ choicesElem, "choice");
+ ManagedList<BeanDefinition> choiceBeans = new ManagedList<BeanDefinition>(
+ 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);
+
+ }
+
+ protected void putInAttributes(
+ ManagedMap<String, BeanDefinition> 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<DefaultExecutionSpec> getBeanClass(Element element) {
+ return DefaultExecutionSpec.class;
+ }
+
+ protected boolean shouldGenerateIdAsFallback() {
+ return false;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:beans="http://www.springframework.org/schema/beans"
+ targetNamespace="http://www.argeo.org/schema/slc-flow"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <xsd:import namespace="http://www.springframework.org/schema/beans"
+ schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" />
+
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ SLC Flow Schema, version 0.12
+ Authors: Mathieu Baudier
+
+ This simplifies the definition of SLC flows and their integration with
+ regular Spring beans.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="flow">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Adds an SLC execution flow, using the default implementation.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="beans:identifiedType">
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" />
+ <xsd:sequence>
+ <xsd:element name="arg" minOccurs="0" maxOccurs="unbounded"
+ type="flow:argType">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Parameter for an execution flow which will override at instantiation the
+ value of the parameter already defined as default value or in a parent bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:sequence>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="flow:flow" />
+ </xsd:choice>
+ <!--
+ <xsd:any namespace="##other" processContents="strict"
+ minOccurs="0" maxOccurs="unbounded" />
+ -->
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Name of the flow (alternative to ID).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="class" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Another implementation of execution flow.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="path" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The hierarchical path under which to register this flow.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="spec" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference to the related specification bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="parent" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The parent bean definition (in Spring sense).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="abstract" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether this flow is abstract (in Spring sense).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="spec">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ SLC flow specifications, defining the parameters and variables
+ which can be used in related flows, along with their default values and
+ various constraints.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="beans:identifiedType">
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" />
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="primitive" type="flow:primitiveSpecAttributeType"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A primitive specification attribute, that is, a plain standard value
+ and not a reference to an object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="ref" type="flow:refSpecAttributeType"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference specification attribute, that is, a reference to another object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="specAttributeType">
+ <xsd:choice>
+ <xsd:element name="value" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute as an inner bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice minOccurs="1" maxOccurs="1">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="beans:list" />
+ <xsd:element ref="beans:set" />
+ <xsd:element ref="beans:map" />
+ <xsd:element ref="beans:props" />
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the attribute, under which in can then be referenced.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="value" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="ref" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute as a reference to another bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isParameter" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is a parameter, that is, it has to be set at
+ instantiation but can be modified afterwards for objects of scope execution.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isFrozen" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is frozen, that is, it cannot be modified at runtime.
+ A frozen attribute has to be a parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isHidden" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is hidden, that is, it should not be displayed in UIs.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:complexType name="primitiveSpecAttributeType">
+ <xsd:complexContent>
+ <xsd:extension base="flow:specAttributeType">
+ <xsd:attribute name="type" default="string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The type of the primitive specification attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="string" />
+ <xsd:enumeration value="integer" />
+ <xsd:enumeration value="long" />
+ <xsd:enumeration value="float" />
+ <xsd:enumeration value="double" />
+ <xsd:enumeration value="boolean" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="refSpecAttributeType">
+ <xsd:complexContent>
+ <xsd:extension base="flow:specAttributeType">
+ <xsd:choice>
+ <xsd:element name="choices" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Possible values to chose from, if ommitted, all the beans in the
+ application context which implement the provided targetClass will
+ be considered.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded"
+ type="flow:refChoiceType">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A choice for a reference specification attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:attribute name="targetClass" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The class that has to be implemented by the underlying object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="refChoiceType">
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="description" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A human readable description of this choice.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:complexType name="argType">
+ <xsd:choice minOccurs="0" maxOccurs="1">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="flow:param" />
+ <xsd:element ref="beans:list" />
+ <xsd:element ref="beans:set" />
+ <xsd:element ref="beans:map" />
+ <xsd:element ref="beans:props" />
+ </xsd:choice>
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="value" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The plain value of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="ref" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The value of the related parameter as a reference to a bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:attribute name="as-flow" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ If decorating an executable bean, it will generate an implicit SLC
+ execution flow with the provided value as name.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <!--
+ <xsd:attribute name="var" type="xsd:boolean"> <xsd:annotation>
+ <xsd:documentation><![CDATA[ If true, the decorated bean is set to
+ scope execution and proxied. ]]></xsd:documentation> </xsd:annotation>
+ </xsd:attribute>
+ -->
+
+ <xsd:element name="variable">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Marks a bean definition as being variable, i.e. a scoped proxy of scope execution
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="proxy-target-class" type="xsd:boolean"
+ default="true">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Are class-based (CGLIB) proxies to be created?
+ This is the default;
+ in order to switch to standard Java
+ interface-based proxies, turn this flag to
+ "false".
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="param">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ If within a property tag of a bean, it will set the value of this property
+ with a reference to a parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="xsd:string" use="required">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="instantiationManager" type="xsd:string"
+ use="optional" default="instantiationManager">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference to the instantiation manager to use instead of the default one
+ (expert usage).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:beans="http://www.springframework.org/schema/beans"
+ targetNamespace="http://www.argeo.org/schema/slc-flow"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+ <xsd:import namespace="http://www.springframework.org/schema/beans"
+ schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" />
+
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ SLC Flow Schema, version 1.2
+ Authors: Mathieu Baudier
+
+ This simplifies the definition of SLC flows and their integration with
+ regular Spring beans.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:element name="flow">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Adds an SLC execution flow, using the default implementation.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="beans:identifiedType">
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" />
+ <xsd:sequence>
+ <xsd:element name="arg" minOccurs="0" maxOccurs="unbounded"
+ type="flow:argType">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Parameter for an execution flow which will override at instantiation the
+ value of the parameter already defined as default value or in a parent bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ <xsd:sequence>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="flow:flow" />
+ <xsd:element ref="flow:spec" />
+ </xsd:choice>
+ <!-- <xsd:any namespace="##other" processContents="strict" minOccurs="0"
+ maxOccurs="unbounded" /> -->
+ </xsd:sequence>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Name of the flow (alternative to ID).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="class" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Another implementation of execution flow.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="path" type="xsd:string">
+ <!-- DEPRECATED: not used anymore -->
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The hierarchical path under which to register this flow.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="spec" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference to the related specification bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="parent" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The parent bean definition (in Spring sense).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="abstract" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether this flow is abstract (in Spring sense).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="spec">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ SLC flow specifications, defining the parameters and variables
+ which can be used in related flows, along with their default values and
+ various constraints.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:complexContent>
+ <xsd:extension base="beans:identifiedType">
+ <xsd:sequence>
+ <xsd:element ref="beans:description" minOccurs="0" />
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="primitive" type="flow:primitiveSpecAttributeType"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A primitive specification attribute, that is, a plain standard value
+ and not a reference to an object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="ref" type="flow:refSpecAttributeType"
+ minOccurs="0" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference specification attribute, that is, a reference to another object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="specAttributeType">
+ <xsd:choice>
+ <xsd:element name="value" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute as an inner bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice minOccurs="1" maxOccurs="1">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="beans:list" />
+ <xsd:element ref="beans:set" />
+ <xsd:element ref="beans:map" />
+ <xsd:element ref="beans:props" />
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the attribute, under which in can then be referenced.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="value" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="ref" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The default value of the attribute as a reference to another bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isImmutable" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is a parameter, that is, it has to be set at
+ instantiation but can be modified afterwards for objects of scope execution.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isParameter" use="optional" type="xsd:boolean"
+ default="false">
+ <!-- DEPRECATED: old name of isImmutable -->
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is a parameter, that is, it has to be set at
+ instantiation but can be modified afterwards for objects of scope execution.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isConstant" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is frozen, that is, it cannot be modified at runtime.
+ A frozen attribute has to be a parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isFrozen" use="optional" type="xsd:boolean"
+ default="false">
+ <!-- DEPRECATED: old name of isConstant -->
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is frozen, that is, it cannot be modified at runtime.
+ A frozen attribute has to be a parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="isHidden" use="optional" type="xsd:boolean"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Whether the attribute is hidden, that is, it should not be displayed in UIs.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:complexType name="primitiveSpecAttributeType">
+ <xsd:complexContent>
+ <xsd:extension base="flow:specAttributeType">
+ <xsd:attribute name="type" default="string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The type of the primitive specification attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="string" />
+ <xsd:enumeration value="password" />
+ <xsd:enumeration value="integer" />
+ <xsd:enumeration value="long" />
+ <xsd:enumeration value="float" />
+ <xsd:enumeration value="double" />
+ <xsd:enumeration value="boolean" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="refSpecAttributeType">
+ <xsd:complexContent>
+ <xsd:extension base="flow:specAttributeType">
+ <xsd:choice>
+ <xsd:element name="choices" minOccurs="0" maxOccurs="1">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Possible values to chose from, if ommitted, all the beans in the
+ application context which implement the provided targetClass will
+ be considered.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice>
+ <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded"
+ type="flow:refChoiceType">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A choice for a reference specification attribute.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ <xsd:attribute name="targetClass" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The class that has to be implemented by the underlying object.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="refChoiceType">
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="description" use="optional" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A human readable description of this choice.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:complexType name="argType">
+ <xsd:choice minOccurs="0" maxOccurs="1">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ <xsd:element ref="flow:param" />
+ <xsd:element ref="beans:list" />
+ <xsd:element ref="beans:set" />
+ <xsd:element ref="beans:map" />
+ <xsd:element ref="beans:props" />
+ </xsd:choice>
+ <xsd:attribute name="name" use="required" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="value" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The plain value of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="ref" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The value of the related parameter as a reference to a bean.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+
+ <xsd:attribute name="as-flow" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ If decorating an executable bean, it will generate an implicit SLC
+ execution flow with the provided value as name.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <!-- <xsd:attribute name="var" type="xsd:boolean"> <xsd:annotation> <xsd:documentation><![CDATA[
+ If true, the decorated bean is set to scope execution and proxied. ]]></xsd:documentation>
+ </xsd:annotation> </xsd:attribute> -->
+
+ <xsd:element name="variable">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Marks a bean definition as being variable, i.e. a scoped proxy of scope execution
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="proxy-target-class" type="xsd:boolean"
+ default="true">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Are class-based (CGLIB) proxies to be created?
+ This is the default;
+ in order to switch to standard Java
+ interface-based proxies, turn this flag to
+ "false".
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="param">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ If within a property tag of a bean, it will set the value of this property
+ with a reference to a parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="xsd:string" use="required">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ The name of the related parameter.
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="instantiationManager" type="xsd:string"
+ use="optional" default="instantiationManager">
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ A reference to the instantiation manager to use instead of the default one
+ (expert usage).
+ ]]></xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import org.argeo.slc.test.TestData;\r
+\r
+public class BasicTestData implements TestData {\r
+ private Object expected;\r
+ private Object reached;\r
+\r
+ public Object getExpected() {\r
+ return expected;\r
+ }\r
+\r
+ public void setExpected(Object expected) {\r
+ this.expected = expected;\r
+ }\r
+\r
+ public Object getReached() {\r
+ return reached;\r
+ }\r
+\r
+ public void setReached(Object reached) {\r
+ this.reached = reached;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.core.test.context.ContextUtils;\r
+import org.argeo.slc.test.IncompatibleTestDataException;\r
+import org.argeo.slc.test.TestData;\r
+import org.argeo.slc.test.TestDefinition;\r
+import org.argeo.slc.test.TestResult;\r
+import org.argeo.slc.test.TestRun;\r
+import org.argeo.slc.test.TestStatus;\r
+import org.argeo.slc.test.context.ContextAware;\r
+\r
+/** Understands basic test data and context aware test data. */\r
+public class BasicTestDefinition implements TestDefinition {\r
+\r
+ public void execute(TestRun testRun) {\r
+ if (testRun.<TestData> getTestData() instanceof BasicTestData) {\r
+ BasicTestData testData = testRun.getTestData();\r
+ TestResult result = testRun.getTestResult();\r
+\r
+ if (result == null)\r
+ throw new SlcException("No test result defined.");\r
+\r
+ try {\r
+ if (testData.getExpected().equals(testData.getReached())) {\r
+ result.addResultPart(new SimpleResultPart(\r
+ TestStatus.PASSED, "Reached and expected equals"));\r
+ } else {\r
+ result.addResultPart(new SimpleResultPart(\r
+ TestStatus.FAILED, "Expected "\r
+ + testData.getExpected() + " but reached "\r
+ + testData.getReached()));\r
+ }\r
+ } catch (Exception e) {\r
+ result.addResultPart(new SimpleResultPart(TestStatus.ERROR,\r
+ "Could not compare", e));\r
+ }\r
+ } else if (testRun.<TestData> getTestData() instanceof ContextAware) {\r
+ TestData testData = testRun.getTestData();\r
+ ContextUtils.compareReachedExpected((ContextAware) testData,\r
+ testRun.getTestResult());\r
+ } else {\r
+ throw new IncompatibleTestDataException(testRun);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import java.io.Serializable;\r
+\r
+import org.argeo.slc.test.TestResultPart;\r
+import org.argeo.slc.test.TestRun;\r
+import org.argeo.slc.test.TestRunAware;\r
+import org.argeo.slc.test.TestStatus;\r
+\r
+/**\r
+ * <p>\r
+ * Basic implementation of a result part, implementing the standard three status\r
+ * approach for test results.\r
+ * </p>\r
+ * \r
+ * @see TestStatus\r
+ */\r
+public class SimpleResultPart implements TestResultPart, TestStatus,\r
+ TestRunAware, Serializable {\r
+ private static final long serialVersionUID = 6669675957685071901L;\r
+\r
+ private Long tid;\r
+\r
+ private String testRunUuid;\r
+\r
+ /** The status. Default to ERROR since it should always be explicitely set. */\r
+ private Integer status = ERROR;\r
+ private String message;\r
+ private String exceptionMessage;\r
+\r
+ public SimpleResultPart() {\r
+ }\r
+\r
+ public SimpleResultPart(Integer status, String message) {\r
+ this(status, message, null);\r
+ }\r
+\r
+ public SimpleResultPart(Integer status, String message, Exception exception) {\r
+ this.status = status;\r
+ this.message = message;\r
+ setException(exception);\r
+ }\r
+\r
+ public String getMessage() {\r
+ return message;\r
+ }\r
+\r
+ public void setMessage(String message) {\r
+ this.message = message;\r
+ }\r
+\r
+ public void setStatus(Integer status) {\r
+ this.status = status;\r
+ }\r
+\r
+ public Integer getStatus() {\r
+ return status;\r
+ }\r
+\r
+ public String getExceptionMessage() {\r
+ return exceptionMessage;\r
+ }\r
+\r
+ public void setException(Exception exception) {\r
+ if (exception == null)\r
+ return;\r
+\r
+ StringBuffer buf = new StringBuffer("");\r
+ buf.append(exception.toString());\r
+ buf.append('\n');\r
+ for (StackTraceElement elem : exception.getStackTrace()) {\r
+ buf.append('\t').append(elem.toString()).append('\n');\r
+ }\r
+\r
+ if (exception.getCause() != null)\r
+ addRootCause(buf, exception.getCause());\r
+\r
+ this.exceptionMessage = buf.toString();\r
+ }\r
+\r
+ protected void addRootCause(StringBuffer buf, Throwable cause) {\r
+ if (cause == null)\r
+ return;\r
+\r
+ buf.append("Caused by: " + cause.getMessage());\r
+ for (StackTraceElement elem : cause.getStackTrace()) {\r
+ buf.append('\t').append(elem.toString()).append('\n');\r
+ }\r
+\r
+ if (cause.getCause() != null) {\r
+ addRootCause(buf, cause.getCause());\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public String toString() {\r
+ StringBuffer buf = new StringBuffer("");\r
+ buf.append(SlcTestUtils.statusToString(status));\r
+ if (status == PASSED || status == FAILED) {\r
+ buf.append(' ');\r
+ } else if (status == ERROR) {\r
+ buf.append(" ");\r
+ }\r
+ buf.append(message);\r
+ return buf.toString();\r
+ }\r
+\r
+ /** @deprecated */\r
+ Long getTid() {\r
+ return tid;\r
+ }\r
+\r
+ /** @deprecated */\r
+ void setTid(Long tid) {\r
+ this.tid = tid;\r
+ }\r
+\r
+ public String getTestRunUuid() {\r
+ return testRunUuid;\r
+ }\r
+\r
+ /** For ORM */\r
+ public void setTestRunUuid(String testRunUuid) {\r
+ this.testRunUuid = testRunUuid;\r
+ }\r
+\r
+ public void notifyTestRun(TestRun testRun) {\r
+ testRunUuid = testRun.getUuid();\r
+ }\r
+\r
+ public void setExceptionMessage(String exceptionMessage) {\r
+ this.exceptionMessage = exceptionMessage;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+import java.util.UUID;\r
+import java.util.Vector;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.test.TestResult;\r
+import org.argeo.slc.test.TestResultPart;\r
+import org.argeo.slc.test.TestRun;\r
+\r
+/**\r
+ * Basic implementation of a test result containing only a list of result parts.\r
+ */\r
+public class SimpleTestResult implements TestResult {\r
+ private static Log log = LogFactory.getLog(SimpleTestResult.class);\r
+\r
+ private String uuid;\r
+ private String currentTestRunUuid;\r
+\r
+ private Boolean throwError = true;\r
+\r
+ private Date closeDate;\r
+ private List<TestResultPart> parts = new Vector<TestResultPart>();\r
+\r
+ private Map<String, String> attributes = new TreeMap<String, String>();\r
+\r
+ public void addResultPart(TestResultPart part) {\r
+ if (throwError && part.getStatus() == ERROR) {\r
+ throw new SlcException(\r
+ "There was an error in the underlying test: "\r
+ + part.getExceptionMessage());\r
+ }\r
+ parts.add(part);\r
+ if (log.isDebugEnabled())\r
+ log.debug(part);\r
+ }\r
+\r
+ public void close() {\r
+ parts.clear();\r
+ closeDate = new Date();\r
+ }\r
+\r
+ public List<TestResultPart> getParts() {\r
+ return parts;\r
+ }\r
+\r
+ public Date getCloseDate() {\r
+ return closeDate;\r
+ }\r
+\r
+ public void setThrowError(Boolean throwError) {\r
+ this.throwError = throwError;\r
+ }\r
+\r
+ public void notifyTestRun(TestRun testRun) {\r
+ currentTestRunUuid = testRun.getUuid();\r
+ }\r
+\r
+ public String getUuid() {\r
+ if (uuid == null) {\r
+ uuid = UUID.randomUUID().toString();\r
+ }\r
+ return uuid;\r
+ }\r
+\r
+ public void setUuid(String uuid) {\r
+ this.uuid = uuid;\r
+ }\r
+\r
+ public String getCurrentTestRunUuid() {\r
+ return currentTestRunUuid;\r
+ }\r
+\r
+ public Map<String, String> getAttributes() {\r
+ return attributes;\r
+ }\r
+\r
+ public void setAttributes(Map<String, String> attributes) {\r
+ this.attributes = attributes;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import java.util.UUID;\r
+\r
+import org.argeo.slc.deploy.DeployedSystem;\r
+import org.argeo.slc.test.ExecutableTestRun;\r
+import org.argeo.slc.test.TestData;\r
+import org.argeo.slc.test.TestDefinition;\r
+import org.argeo.slc.test.TestResult;\r
+import org.argeo.slc.test.WritableTestRun;\r
+\r
+/**\r
+ * A basic bean implementation of a <code>WritableTestRun</code>, holding\r
+ * references to the various parts of a test run.\r
+ */\r
+public class SimpleTestRun implements WritableTestRun, ExecutableTestRun {\r
+ private String uuid;\r
+\r
+ // private String slcExecutionUuid;\r
+ // private String slcExecutionStepUuid;\r
+\r
+ private DeployedSystem deployedSystem;\r
+ private TestData testData;\r
+ private TestDefinition testDefinition;\r
+ private TestResult testResult;\r
+\r
+ /** Executes the underlying test definition. */\r
+ public void run() {\r
+ uuid = UUID.randomUUID().toString();\r
+ if (testResult != null)\r
+ testResult.notifyTestRun(this);\r
+\r
+ testDefinition.execute(this);\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T extends DeployedSystem> T getDeployedSystem() {\r
+ return (T) deployedSystem;\r
+ }\r
+\r
+ public void setDeployedSystem(DeployedSystem deployedSystem) {\r
+ this.deployedSystem = deployedSystem;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T extends TestData> T getTestData() {\r
+ return (T) testData;\r
+ }\r
+\r
+ public void setTestData(TestData testData) {\r
+ this.testData = testData;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T extends TestDefinition> T getTestDefinition() {\r
+ return (T) testDefinition;\r
+ }\r
+\r
+ public void setTestDefinition(TestDefinition testDefinition) {\r
+ this.testDefinition = testDefinition;\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ public <T extends TestResult> T getTestResult() {\r
+ return (T) testResult;\r
+ }\r
+\r
+ public void setTestResult(TestResult testResult) {\r
+ this.testResult = testResult;\r
+ }\r
+\r
+ public String getUuid() {\r
+ return uuid;\r
+ }\r
+\r
+ public void setUuid(String uuid) {\r
+ this.uuid = uuid;\r
+ }\r
+\r
+ // public String getSlcExecutionUuid() {\r
+ // return slcExecutionUuid;\r
+ // }\r
+ //\r
+ // public void setSlcExecutionUuid(String slcExecutionUuid) {\r
+ // this.slcExecutionUuid = slcExecutionUuid;\r
+ // }\r
+ //\r
+ // public String getSlcExecutionStepUuid() {\r
+ // return slcExecutionStepUuid;\r
+ // }\r
+ //\r
+ // public void setSlcExecutionStepUuid(String slcExecutionStepUuid) {\r
+ // this.slcExecutionStepUuid = slcExecutionStepUuid;\r
+ // }\r
+}\r
--- /dev/null
+/*
+ * 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() {
+
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test;\r
+\r
+import org.argeo.slc.UnsupportedException;\r
+import org.argeo.slc.test.TestData;\r
+import org.argeo.slc.test.TestDataProvider;\r
+\r
+/** Utilities for dealing with test datas. */\r
+public class TestDataUtils {\r
+ /** Extracts the test data from the given provider. */\r
+ public static <T extends TestData> T getFromProvider(Object obj,\r
+ Class<T> clss, String key) {\r
+ if (obj instanceof TestDataProvider) {\r
+ TestDataProvider testDataProvider = (TestDataProvider) obj;\r
+ return testDataProvider.getTestData(clss, key);\r
+ } else {\r
+ throw new UnsupportedException("test data provider", obj);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Extracts the test data from the given provider using <code>null</code>\r
+ * as key.\r
+ */\r
+ public static <T extends TestData> T getFromProvider(Object obj,\r
+ Class<T> clss) {\r
+ return getFromProvider(obj, clss, null);\r
+ }\r
+\r
+ /**\r
+ * Returns it self after making the proper checks. Used for test data being\r
+ * their own data providers.\r
+ */\r
+ @SuppressWarnings("unchecked")\r
+ public static <T extends TestData> T getItSelf(Class<T> clss,\r
+ TestData testDataObject) {\r
+ if (clss.isAssignableFrom(testDataObject.getClass())) {\r
+ return (T) testDataObject;\r
+ } else {\r
+ throw new UnsupportedException("test data", testDataObject);\r
+ }\r
+\r
+ }\r
+\r
+ /** Makes sure this is an utility class. */\r
+ private TestDataUtils() {\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.core.test.SimpleResultPart;\r
+import org.argeo.slc.test.TestResult;\r
+import org.argeo.slc.test.TestStatus;\r
+import org.argeo.slc.test.context.ContextAware;\r
+import org.argeo.slc.test.context.ParentContextAware;\r
+\r
+/** Utilities for comparing and synchronising contexts. */\r
+public class ContextUtils {\r
+ private final static Log log = LogFactory.getLog(ContextUtils.class);\r
+\r
+ public static void compareReachedExpected(ContextAware contextAware,\r
+ TestResult testResult) {\r
+ for (String key : contextAware.getExpectedValues().keySet()) {\r
+\r
+ // Compare expected values with reached ones\r
+ Object expectedValue = contextAware.getExpectedValues().get(key);\r
+\r
+ if (expectedValue.toString().equals(\r
+ contextAware.getContextSkipFlag())) {\r
+ if (log.isDebugEnabled())\r
+ log.debug("Skipped check for key '" + key + "'");\r
+ continue;\r
+ }\r
+\r
+ if (contextAware.getValues().containsKey(key)) {\r
+ Object reachedValue = contextAware.getValues().get(key);\r
+\r
+ if (expectedValue.equals(contextAware.getContextAnyFlag())) {\r
+ testResult.addResultPart(new SimpleResultPart(\r
+ TestStatus.PASSED, "Expected any value for key '"\r
+ + key + "'"));\r
+ } else if (expectedValue.equals(reachedValue)) {\r
+ testResult.addResultPart(new SimpleResultPart(\r
+ TestStatus.PASSED, "Values matched for key '" + key\r
+ + "'"));\r
+ } else {\r
+ testResult.addResultPart(new SimpleResultPart(\r
+ TestStatus.FAILED, "Mismatch for key '" + key\r
+ + "': expected '" + expectedValue\r
+ + "' but reached '" + reachedValue + "'"));\r
+ }\r
+ } else {\r
+ testResult.addResultPart(new SimpleResultPart(\r
+ TestStatus.FAILED, "No value reached for key '" + key\r
+ + "'"));\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Makes sure that all children and sub-children of parent share the same\r
+ * maps for values and expected values.\r
+ */\r
+ public static void synchronize(ParentContextAware parent) {\r
+ Map<String, Object> expectedValuesCommon = new TreeMap<String, Object>(\r
+ parent.getExpectedValues());\r
+ synchronize(parent, expectedValuesCommon);\r
+ if (log.isDebugEnabled())\r
+ log.debug("Synchronized context " + parent);\r
+\r
+ }\r
+\r
+ private static void synchronize(ParentContextAware parent,\r
+ Map<String, Object> expectedValuesCommon) {\r
+ for (ContextAware child : parent.getChildContexts()) {\r
+ // Values\r
+ putNotContained(parent.getValues(), child.getValues());\r
+ child.setValues(parent.getValues());\r
+\r
+ // Expected Values\r
+ // Expected values reference is not overridden: each child has its\r
+ // own expected values map.\r
+ overrideContained(expectedValuesCommon, child.getExpectedValues());\r
+\r
+ // Creates a new Map in order not to disturb other context using the\r
+ // same keys\r
+ Map<String, Object> expectedValuesCommonChild = new TreeMap<String, Object>(\r
+ expectedValuesCommon);\r
+ putNotContained(expectedValuesCommonChild,\r
+ child.getExpectedValues());\r
+\r
+ if (child instanceof ParentContextAware) {\r
+ // Recursive sync\r
+ synchronize((ParentContextAware) child,\r
+ expectedValuesCommonChild);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Put into common map the values from child map which are not already\r
+ * defined in common map.\r
+ */\r
+ public static void putNotContained(Map<String, Object> commonMap,\r
+ Map<String, Object> childMap) {\r
+ for (String key : childMap.keySet()) {\r
+ if (!commonMap.containsKey(key)) {\r
+ commonMap.put(key, childMap.get(key));\r
+ }\r
+ }\r
+ }\r
+\r
+ /** Overrides child map values with the values already set in common map */\r
+ public static void overrideContained(Map<String, Object> commonMap,\r
+ Map<String, Object> childMap) {\r
+ for (String key : childMap.keySet()) {\r
+ if (commonMap.containsKey(key)) {\r
+ childMap.put(key, commonMap.get(key));\r
+ }\r
+ }\r
+ }\r
+\r
+ /** Makes sure this cannot be instantiated. */\r
+ private ContextUtils() {\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import org.argeo.slc.core.test.TestDataUtils;\r
+import org.argeo.slc.test.TestData;\r
+import org.argeo.slc.test.TestDataProvider;\r
+\r
+public class DefaultContextTestData extends SimpleContextAware implements\r
+ TestData, TestDataProvider {\r
+\r
+ public <T extends TestData> T getTestData(Class<T> clss, String key) {\r
+ return TestDataUtils.getItSelf(clss, this);\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import java.util.Map;\r
+import java.util.TreeMap;\r
+\r
+import org.argeo.slc.SlcException;\r
+import org.argeo.slc.test.context.ContextAware;\r
+import org.argeo.slc.test.context.ParentContextAware;\r
+import org.springframework.beans.factory.InitializingBean;\r
+\r
+public class SimpleContextAware implements ContextAware, InitializingBean {\r
+ private ParentContextAware parentContext;\r
+\r
+ private Map<String, Object> values = new TreeMap<String, Object>();\r
+ private Map<String, Object> expectedValues = new TreeMap<String, Object>();\r
+\r
+ private String contextSkipFlag = DEFAULT_SKIP_FLAG;\r
+ private String contextAnyFlag = DEFAULT_ANY_FLAG;\r
+\r
+ public Map<String, Object> getValues() {\r
+ return values;\r
+ }\r
+\r
+ public void setValues(Map<String, Object> values) {\r
+ this.values = values;\r
+ }\r
+\r
+ public Map<String, Object> getExpectedValues() {\r
+ return expectedValues;\r
+ }\r
+\r
+ public void setExpectedValues(Map<String, Object> expectedValues) {\r
+ this.expectedValues = expectedValues;\r
+ }\r
+\r
+ /** Used to add this context as a child by setting a property. */\r
+ public void setParentContext(ParentContextAware parentContextAware) {\r
+ if (parentContext != null)\r
+ throw new SlcException("Parent context already set");\r
+ this.parentContext = parentContextAware;\r
+ this.parentContext.addChildContext(this);\r
+ }\r
+\r
+ protected ParentContextAware getParentContext() {\r
+ return parentContext;\r
+ }\r
+\r
+ public void afterPropertiesSet() throws Exception {\r
+ if (parentContext != null) {\r
+ ContextUtils.synchronize(parentContext);\r
+ }\r
+ }\r
+\r
+ public String getContextSkipFlag() {\r
+ return contextSkipFlag;\r
+ }\r
+\r
+ public void setContextSkipFlag(String contextSkipFlag) {\r
+ this.contextSkipFlag = contextSkipFlag;\r
+ }\r
+\r
+ public String getContextAnyFlag() {\r
+ return contextAnyFlag;\r
+ }\r
+\r
+ public void setContextAnyFlag(String contextAnyFlag) {\r
+ this.contextAnyFlag = contextAnyFlag;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.slc.core.test.context;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.argeo.slc.test.context.ContextAware;\r
+import org.argeo.slc.test.context.ParentContextAware;\r
+import org.springframework.beans.factory.InitializingBean;\r
+\r
+public class SimpleParentContextAware extends SimpleContextAware implements\r
+ ParentContextAware, InitializingBean {\r
+ private List<ContextAware> children = new Vector<ContextAware>();\r
+\r
+ public Collection<ContextAware> getChildContexts() {\r
+ return children;\r
+ }\r
+\r
+ public void addChildContext(ContextAware contextAware) {\r
+ children.add(contextAware);\r
+ }\r
+\r
+ @Override\r
+ public void afterPropertiesSet() throws Exception {\r
+ if (getParentContext() != null) {\r
+ // If has a parent, sync it.\r
+ super.afterPropertiesSet();\r
+ } else {\r
+ if (children.size() > 0) {\r
+ // No need to synchronize if no children\r
+ ContextUtils.synchronize(this);\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<html>\r
+<head></head>\r
+<body>\r
+Context variables to be passed between parts of tests.\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+<html>\r
+<head></head>\r
+<body>\r
+SLC Test: test of software systems.\r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
+ default-lazy-init="true">
+
+ <bean name="slcDefault.test.testRun"
+ class="org.argeo.slc.core.test.SimpleTestRun"
+ scope="prototype">
+ </bean>
+
+ <bean name="slcDefault.test.uuid" class="java.util.UUID"
+ factory-method="randomUUID" scope="prototype">
+ </bean>
+
+ <bean id="slcDefault.test.basicSimpleTestResult"
+ class="org.argeo.slc.core.test.SimpleTestResult"
+ abstract="true">
+ <property name="uuid">
+ <bean factory-bean="slcDefault.test.uuid"
+ factory-method="toString">
+ </bean>
+ </property>
+ </bean>
+
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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.jcr;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+
+/**
+ * Writes arbitrary metadata into a child node of a given node (or the node
+ * itself if metadata node name is set to null)
+ */
+public class JcrMetadataWriter implements Runnable {
+ private final static Log log = LogFactory.getLog(JcrMetadataWriter.class);
+
+ private Node baseNode;
+ private String metadataNodeName = SlcNames.SLC_METADATA;
+
+ private Map<String, String> metadata = new HashMap<String, String>();
+
+ public void run() {
+ try {
+ Node metadataNode;
+ if (metadataNodeName != null)
+ metadataNode = baseNode.hasNode(metadataNodeName) ? baseNode
+ .getNode(metadataNodeName) : baseNode
+ .addNode(metadataNodeName);
+ else
+ metadataNode = baseNode;
+
+ for (String key : metadata.keySet())
+ metadataNode.setProperty(key, metadata.get(key));
+
+ baseNode.getSession().save();
+
+ if (log.isDebugEnabled())
+ log.debug("Wrote " + metadata.size() + " metadata entries to "
+ + metadataNode);
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot write metadata to " + baseNode, e);
+ } finally {
+ JcrUtils.discardUnderlyingSessionQuietly(baseNode);
+ }
+
+ }
+
+ public void setBaseNode(Node baseNode) {
+ this.baseNode = baseNode;
+ }
+
+ public void setMetadataNodeName(String metadataNodeName) {
+ this.metadataNodeName = metadataNodeName;
+ }
+
+ public void setMetadata(Map<String, String> metadata) {
+ this.metadata = metadata;
+ }
+
+}
--- /dev/null
+/*
+ * 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.jcr;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Repository;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.core.attachment.AttachmentsEnabled;
+import org.argeo.slc.test.TestResult;
+import org.argeo.slc.test.TestResultPart;
+import org.argeo.slc.test.TestRun;
+import org.argeo.slc.test.TestStatus;
+
+/**
+ * {@link TestResult} wrapping a JCR node of type
+ * {@link SlcTypes#SLC_TEST_RESULT}.
+ */
+public class JcrTestResult implements TestResult, SlcNames, AttachmentsEnabled {
+ private final static Log log = LogFactory.getLog(JcrTestResult.class);
+
+ /** Should only be set for an already existing result. */
+ private String uuid;
+ private Repository repository;
+ private Session session;
+ /**
+ * For testing purposes, best practice is to not set them explicitely but
+ * via other mechanisms such as JAAS or SPring Security.
+ */
+ private Credentials credentials = null;
+ private String resultType = SlcTypes.SLC_TEST_RESULT;
+
+ /** cached for performance purposes */
+ private String nodeIdentifier = null;
+
+ private Map<String, String> attributes = new HashMap<String, String>();
+
+ public void init() {
+ try {
+ session = repository.login(credentials);
+ if (uuid == null) {
+ // create new result
+ uuid = UUID.randomUUID().toString();
+ String path = SlcJcrUtils.createResultPath(session, uuid);
+ Node resultNode = JcrUtils.mkdirs(session, path, resultType);
+ resultNode.setProperty(SLC_UUID, uuid);
+ for (String attr : attributes.keySet()) {
+ String property = attr;
+ // compatibility with legacy applications
+ if ("testCase".equals(attr))
+ property = SLC_TEST_CASE;
+ else if ("testCaseType".equals(attr))
+ property = SLC_TEST_CASE_TYPE;
+ resultNode.setProperty(property, attributes.get(attr));
+ }
+ session.save();
+ if (log.isDebugEnabled())
+ log.debug("Created test result " + uuid);
+ }
+ } catch (Exception e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot initialize JCR result", e);
+ }
+ }
+
+ public void destroy() {
+ JcrUtils.logoutQuietly(session);
+ if (log.isTraceEnabled())
+ log.trace("Logged out session for result " + uuid);
+ }
+
+ public Node getNode() {
+ try {
+ Node resultNode;
+ if (nodeIdentifier != null) {
+ return session.getNodeByIdentifier(nodeIdentifier);
+ } else {
+ QueryManager qm = session.getWorkspace().getQueryManager();
+ Query q = qm.createQuery("select * from ["
+ + SlcTypes.SLC_TEST_RESULT + "] where [slc:uuid]='"
+ + uuid + "'", Query.JCR_SQL2);
+ resultNode = JcrUtils.querySingleNode(q);
+ if (resultNode != null)
+ nodeIdentifier = resultNode.getIdentifier();
+ }
+ return resultNode;
+ } catch (Exception e) {
+ throw new SlcException("Cannot get result node", e);
+ }
+ }
+
+ public void notifyTestRun(TestRun testRun) {
+ // TODO store meta data about the test running
+ // if (log.isDebugEnabled())
+ // log.debug("Running test "
+ // + testRun.getTestDefinition().getClass().getName() + "...");
+ }
+
+ public void addResultPart(TestResultPart testResultPart) {
+ Node node = getNode();
+
+ try {
+ // error : revert all unsaved changes on the resultNode to be sure
+ // it is in a consistant state
+ if (testResultPart.getExceptionMessage() != null)
+ JcrUtils.discardQuietly(node.getSession());
+ node.getSession().save();
+
+ // add the new result part, retrieving status information
+ Node resultPartNode = node.addNode(SlcNames.SLC_RESULT_PART,
+ SlcTypes.SLC_CHECK);
+ resultPartNode.setProperty(SLC_SUCCESS, testResultPart.getStatus()
+ .equals(TestStatus.PASSED));
+ if (testResultPart.getMessage() != null)
+ resultPartNode.setProperty(SLC_MESSAGE,
+ testResultPart.getMessage());
+ if (testResultPart.getStatus().equals(TestStatus.ERROR)) {
+ resultPartNode.setProperty(SLC_ERROR_MESSAGE,
+ (testResultPart.getExceptionMessage() == null) ? ""
+ : testResultPart.getExceptionMessage());
+ }
+
+ // helper update aggregate status node
+ Node mainStatus;
+ if (!node.hasNode(SLC_AGGREGATED_STATUS)) {
+
+ mainStatus = node.addNode(SLC_AGGREGATED_STATUS,
+ SlcTypes.SLC_CHECK);
+ mainStatus.setProperty(SLC_SUCCESS,
+ resultPartNode.getProperty(SLC_SUCCESS).getBoolean());
+ if (resultPartNode.hasProperty(SLC_MESSAGE))
+ mainStatus.setProperty(SLC_MESSAGE, resultPartNode
+ .getProperty(SLC_MESSAGE).getString());
+ if (resultPartNode.hasProperty(SLC_ERROR_MESSAGE))
+ mainStatus.setProperty(SLC_ERROR_MESSAGE, resultPartNode
+ .getProperty(SLC_ERROR_MESSAGE).getString());
+ } else {
+ mainStatus = node.getNode(SLC_AGGREGATED_STATUS);
+ if (mainStatus.hasProperty(SLC_ERROR_MESSAGE)) {
+ // main status already in error we do nothing
+ } else if (resultPartNode.hasProperty(SLC_ERROR_MESSAGE)) {
+ // main status was not in error and new result part is in
+ // error; we update main status
+ mainStatus.setProperty(SLC_SUCCESS, false);
+ mainStatus.setProperty(SLC_ERROR_MESSAGE, resultPartNode
+ .getProperty(SLC_ERROR_MESSAGE).getString());
+ if (resultPartNode.hasProperty(SLC_MESSAGE))
+ mainStatus.setProperty(SLC_MESSAGE, resultPartNode
+ .getProperty(SLC_MESSAGE).getString());
+ else
+ // remove old message to remain consistent
+ mainStatus.setProperty(SLC_MESSAGE, "");
+ } else if (!mainStatus.getProperty(SLC_SUCCESS).getBoolean()) {
+ // main status was already failed and new result part is not
+ // in error, we do nothing
+ } else if (!resultPartNode.getProperty(SLC_SUCCESS)
+ .getBoolean()) {
+ // new resultPart that is failed
+ mainStatus.setProperty(SLC_SUCCESS, false);
+ if (resultPartNode.hasProperty(SLC_MESSAGE))
+ mainStatus.setProperty(SLC_MESSAGE, resultPartNode
+ .getProperty(SLC_MESSAGE).getString());
+ else
+ // remove old message to remain consistent
+ mainStatus.setProperty(SLC_MESSAGE, "");
+ } else if (resultPartNode.hasProperty(SLC_MESSAGE)
+ && (!mainStatus.hasProperty(SLC_MESSAGE) || (""
+ .equals(mainStatus.getProperty(SLC_MESSAGE)
+ .getString().trim())))) {
+ mainStatus.setProperty(SLC_MESSAGE, resultPartNode
+ .getProperty(SLC_MESSAGE).getString());
+ }
+ }
+ JcrUtils.updateLastModified(node);
+ node.getSession().save();
+ } catch (Exception e) {
+ JcrUtils.discardUnderlyingSessionQuietly(node);
+ throw new SlcException("Cannot add ResultPart to node " + node, e);
+ }
+ }
+
+ public String getUuid() {
+ Node node = getNode();
+ try {
+ return node.getProperty(SLC_UUID).getString();
+ } catch (Exception e) {
+ throw new SlcException("Cannot get UUID from " + node, e);
+ }
+ }
+
+ /** JCR session is NOT logged out */
+ public void close() {
+ Node node = getNode();
+ try {
+ if (node.hasNode(SLC_COMPLETED))
+ return;
+ node.setProperty(SLC_COMPLETED, new GregorianCalendar());
+ JcrUtils.updateLastModified(node);
+ node.getSession().save();
+ } catch (Exception e) {
+ JcrUtils.discardUnderlyingSessionQuietly(node);
+ throw new SlcException("Cannot get close date from " + node, e);
+ }
+ }
+
+ public Date getCloseDate() {
+ Node node = getNode();
+ try {
+ if (!node.hasNode(SLC_COMPLETED))
+ return null;
+ return node.getProperty(SLC_COMPLETED).getDate().getTime();
+ } catch (Exception e) {
+ throw new SlcException("Cannot get close date from " + node, e);
+ }
+ }
+
+ public Map<String, String> getAttributes() {
+ Node node = getNode();
+ try {
+ Map<String, String> map = new HashMap<String, String>();
+ PropertyIterator pit = node.getProperties();
+ while (pit.hasNext()) {
+ Property p = pit.nextProperty();
+ if (!p.isMultiple())
+ map.put(p.getName(), p.getValue().getString());
+ }
+ return map;
+ } catch (Exception e) {
+ throw new SlcException("Cannot get close date from " + node, e);
+ }
+ }
+
+ public void addAttachment(Attachment attachment) {
+ // TODO implement it
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ public void setResultType(String resultType) {
+ this.resultType = resultType;
+ }
+
+ public void setAttributes(Map<String, String> attributes) {
+ if (uuid != null)
+ throw new SlcException(
+ "Attributes cannot be set on an already initialized test result."
+ + " Update the related JCR node directly instead.");
+ this.attributes = attributes;
+ }
+
+ public void setCredentials(Credentials credentials) {
+ this.credentials = credentials;
+ }
+}
--- /dev/null
+/*
+ * 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.jcr;
+
+import org.argeo.slc.SlcNames;
+
+/** JCR related constants used across SLC */
+public interface SlcJcrConstants {
+ public final static String PROPERTY_PATH = "argeo.slc.jcr.path";
+
+ public final static String SLC_BASE_PATH = "/" + SlcNames.SLC_SYSTEM;
+ public final static String AGENTS_BASE_PATH = SLC_BASE_PATH + "/"
+ + SlcNames.SLC_AGENTS;
+ public final static String VM_AGENT_FACTORY_PATH = AGENTS_BASE_PATH + "/"
+ + SlcNames.SLC_VM;
+}
--- /dev/null
+/*
+ * 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.jcr;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.node.NodeUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+
+/**
+ * Utilities around the SLC JCR Result model. Note that it relies on fixed base
+ * paths (convention over configuration) for optimization purposes.
+ */
+public class SlcJcrResultUtils {
+
+ /**
+ * Returns the path to the current slc:result node
+ */
+ public static String getSlcResultsBasePath(Session session) {
+ try {
+ Node userHome = NodeUtils.getUserHome(session);
+ if (userHome == null)
+ throw new SlcException("No user home available for "
+ + session.getUserID());
+ return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
+ + SlcNames.SLC_RESULTS;
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while getting Slc Results Base Path.", re);
+ }
+ }
+
+ /**
+ * Returns the base node to store SlcResults. If it does not exists, it is
+ * created. If a node already exists at the given path with the wrong type,
+ * it throws an exception.
+ *
+ * @param session
+ * @return
+ */
+ public static Node getSlcResultsParentNode(Session session) {
+ try {
+ String absPath = getSlcResultsBasePath(session);
+ if (session.nodeExists(absPath)) {
+ Node currNode = session.getNode(absPath);
+ if (currNode.isNodeType(NodeType.NT_UNSTRUCTURED))
+ return currNode;
+ else
+ throw new SlcException(
+ "A node already exists at this path : " + absPath
+ + " that has the wrong type. ");
+ } else {
+ Node slcResParNode = JcrUtils.mkdirs(session, absPath);
+ slcResParNode.setPrimaryType(NodeType.NT_UNSTRUCTURED);
+ session.save();
+ return slcResParNode;
+ }
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while creating slcResult root parent node.",
+ re);
+ }
+ }
+
+ /**
+ * Returns the path to the current Result UI specific node, depending the
+ * current user
+ */
+ public static String getMyResultsBasePath(Session session) {
+ try {
+ Node userHome = NodeUtils.getUserHome(session);
+ if (userHome == null)
+ throw new SlcException("No user home available for "
+ + session.getUserID());
+ return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
+ + SlcNames.SLC_MY_RESULTS;
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while getting Slc Results Base Path.", re);
+ }
+ }
+
+ /**
+ * Creates a new node with type SlcTypes.SLC_MY_RESULT_ROOT_FOLDER at the
+ * given absolute path. If a node already exists at the given path, returns
+ * that node if it has the correct type and throws an exception otherwise.
+ *
+ * @param session
+ * @return
+ */
+ public static Node getMyResultParentNode(Session session) {
+ try {
+ String absPath = getMyResultsBasePath(session);
+ if (session.nodeExists(absPath)) {
+ Node currNode = session.getNode(absPath);
+ if (currNode.isNodeType(SlcTypes.SLC_MY_RESULT_ROOT_FOLDER))
+ return currNode;
+ else
+ throw new SlcException(
+ "A node already exists at this path : " + absPath
+ + " that has the wrong type. ");
+ } else {
+ Node myResParNode = JcrUtils.mkdirs(session, absPath);
+ myResParNode.setPrimaryType(SlcTypes.SLC_MY_RESULT_ROOT_FOLDER);
+ session.save();
+ return myResParNode;
+ }
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while creating user MyResult base node.",
+ re);
+ }
+ }
+
+ /**
+ * Creates a new node with type SlcTypes.SLC_RESULT_FOLDER at the given
+ * absolute path. If a node already exists at the given path, returns that
+ * node if it has the correct type and throws an exception otherwise.
+ *
+ * @param session
+ * @param absPath
+ * @return
+ */
+ public static synchronized Node createResultFolderNode(Session session,
+ String absPath) {
+ try {
+ if (session.nodeExists(absPath)) {
+ // Sanity check
+ Node currNode = session.getNode(absPath);
+ if (currNode.isNodeType(SlcTypes.SLC_RESULT_FOLDER))
+ return currNode;
+ else
+ throw new SlcException(
+ "A node already exists at this path : " + absPath
+ + " that has the wrong type. ");
+ }
+ Node rfNode = JcrUtils.mkdirs(session, absPath);
+ rfNode.setPrimaryType(SlcTypes.SLC_RESULT_FOLDER);
+ Node statusNode = rfNode.addNode(SlcNames.SLC_AGGREGATED_STATUS,
+ SlcTypes.SLC_CHECK);
+ statusNode.setProperty(SlcNames.SLC_SUCCESS, true);
+ session.save();
+ return rfNode;
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while creating Result Folder node.", re);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.jcr;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.node.NodeUtils;
+import org.argeo.slc.DefaultNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.execution.PrimitiveAccessor;
+import org.argeo.slc.core.execution.PrimitiveUtils;
+import org.argeo.slc.deploy.ModuleDescriptor;
+import org.argeo.slc.test.TestStatus;
+
+/**
+ * Utilities around the SLC JCR model. Note that it relies on fixed base paths
+ * (convention over configuration) for optimization purposes.
+ */
+public class SlcJcrUtils implements SlcNames {
+ public final static Integer AGENT_FACTORY_DEPTH = 3;
+
+ /** Extracts the path of a flow relative to its execution module */
+ public static String flowRelativePath(String fullFlowPath) {
+ String[] tokens = fullFlowPath.split("/");
+ StringBuffer buf = new StringBuffer(fullFlowPath.length());
+ for (int i = AGENT_FACTORY_DEPTH + 3; i < tokens.length; i++) {
+ buf.append('/').append(tokens[i]);
+ }
+ return buf.toString();
+ }
+
+ /** Extracts the path to the related execution module */
+ public static String modulePath(String fullFlowPath) {
+ String[] tokens = fullFlowPath.split("/");
+ StringBuffer buf = new StringBuffer(fullFlowPath.length());
+ for (int i = 0; i < AGENT_FACTORY_DEPTH + 3; i++) {
+ if (!tokens[i].equals(""))
+ buf.append('/').append(tokens[i]);
+ }
+ return buf.toString();
+ }
+
+ /** Extracts the module name from a flow path */
+ public static String moduleName(String fullFlowPath) {
+ String[] tokens = fullFlowPath.split("/");
+ String moduleName = tokens[AGENT_FACTORY_DEPTH + 2];
+ moduleName = moduleName.substring(0, moduleName.indexOf('_'));
+ return moduleName;
+ }
+
+ /** Extracts the module name and version from a flow path */
+ public static NameVersion moduleNameVersion(String fullFlowPath) {
+ String[] tokens = fullFlowPath.split("/");
+ String module = tokens[AGENT_FACTORY_DEPTH + 2];
+ String moduleName = module.substring(0, module.indexOf('_'));
+ String moduleVersion = module.substring(module.indexOf('_') + 1);
+ return new DefaultNameVersion(moduleName, moduleVersion);
+ }
+
+ /** Module node name based on module name and version */
+ public static String getModuleNodeName(ModuleDescriptor moduleDescriptor) {
+ return moduleDescriptor.getName() + "_" + moduleDescriptor.getVersion();
+ }
+
+ /** Extracts the agent factory of a flow */
+ public static String flowAgentFactoryPath(String fullFlowPath) {
+ String[] tokens = fullFlowPath.split("/");
+ StringBuffer buf = new StringBuffer(fullFlowPath.length());
+ // first token is always empty
+ for (int i = 1; i < AGENT_FACTORY_DEPTH + 1; i++) {
+ buf.append('/').append(tokens[i]);
+ }
+ return buf.toString();
+ }
+
+ /** Create a new execution process path based on the current time */
+ public static String createExecutionProcessPath(Session session, String uuid) {
+ Calendar now = new GregorianCalendar();
+ return getSlcProcessesBasePath(session) + '/'
+ + JcrUtils.dateAsPath(now, true) + uuid;
+ }
+
+ /** Get the base for the user processi. */
+ public static String getSlcProcessesBasePath(Session session) {
+ try {
+ Node userHome = NodeUtils.getUserHome(session);
+ if (userHome == null)
+ throw new SlcException("No user home available for "
+ + session.getUserID());
+ return userHome.getPath() + '/' + SlcNames.SLC_SYSTEM + '/'
+ + SlcNames.SLC_PROCESSES;
+ } catch (RepositoryException re) {
+ throw new SlcException(
+ "Unexpected error while getting Slc Results Base Path.", re);
+ }
+ }
+
+ /**
+ * Create a new execution result path in the user home based on the current
+ * time
+ */
+ public static String createResultPath(Session session, String uuid)
+ throws RepositoryException {
+ Calendar now = new GregorianCalendar();
+ StringBuffer absPath = new StringBuffer(
+ SlcJcrResultUtils.getSlcResultsBasePath(session) + '/');
+ // Remove hours and add title property to the result process path on
+ // request of O. Capillon
+ // return getSlcProcessesBasePath(session) + '/'
+ // + JcrUtils.dateAsPath(now, true) + uuid;
+ String relPath = JcrUtils.dateAsPath(now, false);
+ List<String> names = JcrUtils.tokenize(relPath);
+ for (String name : names) {
+ absPath.append(name + "/");
+ Node node = JcrUtils.mkdirs(session, absPath.toString());
+ try {
+ node.addMixin(NodeType.MIX_TITLE);
+ node.setProperty(Property.JCR_TITLE, name.substring(1));
+ } catch (RepositoryException e) {
+ throw new SlcException(
+ "unable to create execution process path", e);
+ }
+ }
+ return absPath.toString() + uuid;
+ }
+
+ /**
+ * Set the value of the primitive accessor as a JCR property. Does nothing
+ * if the value is null.
+ */
+ public static void setPrimitiveAsProperty(Node node, String propertyName,
+ PrimitiveAccessor primitiveAccessor) {
+ String type = primitiveAccessor.getType();
+ Object value = primitiveAccessor.getValue();
+ setPrimitiveAsProperty(node, propertyName, type, value);
+ }
+
+ /** Map a primitive value to JCR property value. */
+ public static void setPrimitiveAsProperty(Node node, String propertyName,
+ String type, Object value) {
+ if (value == null)
+ return;
+ if (value instanceof CharSequence)
+ value = PrimitiveUtils.convert(type,
+ ((CharSequence) value).toString());
+ if (value instanceof char[])
+ value = new String((char[]) value);
+
+ try {
+ if (type.equals(PrimitiveAccessor.TYPE_STRING))
+ node.setProperty(propertyName, value.toString());
+ else if (type.equals(PrimitiveAccessor.TYPE_PASSWORD))
+ node.setProperty(propertyName, value.toString());
+ else if (type.equals(PrimitiveAccessor.TYPE_INTEGER))
+ node.setProperty(propertyName, (long) ((Integer) value));
+ else if (type.equals(PrimitiveAccessor.TYPE_LONG))
+ node.setProperty(propertyName, ((Long) value));
+ else if (type.equals(PrimitiveAccessor.TYPE_FLOAT))
+ node.setProperty(propertyName, (double) ((Float) value));
+ else if (type.equals(PrimitiveAccessor.TYPE_DOUBLE))
+ node.setProperty(propertyName, ((Double) value));
+ else if (type.equals(PrimitiveAccessor.TYPE_BOOLEAN))
+ node.setProperty(propertyName, ((Boolean) value));
+ else
+ throw new SlcException("Unsupported type " + type);
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot set primitive of " + type
+ + " as property " + propertyName + " on " + node, e);
+ }
+ }
+
+ /** Aggregates the {@link TestStatus} of this sub-tree. */
+ public static Integer aggregateTestStatus(Node node) {
+ try {
+ Integer status = TestStatus.PASSED;
+ if (node.isNodeType(SlcTypes.SLC_CHECK))
+ if (node.getProperty(SLC_SUCCESS).getBoolean())
+ status = TestStatus.PASSED;
+ else if (node.hasProperty(SLC_ERROR_MESSAGE))
+ status = TestStatus.ERROR;
+ else
+ status = TestStatus.FAILED;
+
+ NodeIterator it = node.getNodes();
+ while (it.hasNext()) {
+ Node curr = it.nextNode();
+
+ // Manually skip aggregated status
+ if (!SlcNames.SLC_AGGREGATED_STATUS.equals(curr.getName())) {
+ Integer childStatus = aggregateTestStatus(curr);
+ if (childStatus > status)
+ status = childStatus;
+ }
+ }
+ return status;
+ } catch (Exception e) {
+ throw new SlcException("Could not aggregate test status from "
+ + node, e);
+ }
+ }
+
+ /**
+ * Aggregates the {@link TestStatus} of this sub-tree.
+ *
+ * @return the same {@link StringBuffer}, for convenience (typically calling
+ * toString() on it)
+ */
+ public static StringBuffer aggregateTestMessages(Node node,
+ StringBuffer messages) {
+ try {
+ if (node.isNodeType(SlcTypes.SLC_CHECK)) {
+ if (node.hasProperty(SLC_MESSAGE)) {
+ if (messages.length() > 0)
+ messages.append('\n');
+ messages.append(node.getProperty(SLC_MESSAGE).getString());
+ }
+ if (node.hasProperty(SLC_ERROR_MESSAGE)) {
+ if (messages.length() > 0)
+ messages.append('\n');
+ messages.append(node.getProperty(SLC_ERROR_MESSAGE)
+ .getString());
+ }
+ }
+ NodeIterator it = node.getNodes();
+ while (it.hasNext()) {
+ Node child = it.nextNode();
+ // Manually skip aggregated status
+ if (!SlcNames.SLC_AGGREGATED_STATUS.equals(child.getName())) {
+ aggregateTestMessages(child, messages);
+ }
+ }
+ return messages;
+ } catch (Exception e) {
+ throw new SlcException("Could not aggregate test messages from "
+ + node, e);
+ }
+ }
+
+ /** Prevents instantiation */
+ private SlcJcrUtils() {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.jcr.execution;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.UUID;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcConstants;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.execution.DefaultAgent;
+import org.argeo.slc.core.execution.ProcessThread;
+import org.argeo.slc.execution.ExecutionModulesManager;
+import org.argeo.slc.execution.ExecutionProcess;
+import org.argeo.slc.jcr.SlcJcrConstants;
+
+/** SLC VM agent synchronizing with a JCR repository. */
+public class JcrAgent extends DefaultAgent implements SlcNames {
+ // final static String ROLE_REMOTE = "ROLE_REMOTE";
+ final static String NODE_REPO_URI = "argeo.node.repo.uri";
+
+ private Repository repository;
+
+ private String agentNodeName = "default";
+
+ /*
+ * LIFECYCLE
+ */
+ protected String initAgentUuid() {
+ Session session = null;
+ try {
+ session = repository.login();
+
+ String agentFactoryPath = getAgentFactoryPath();
+ Node vmAgentFactoryNode = JcrUtils.mkdirsSafe(session, agentFactoryPath, SlcTypes.SLC_AGENT_FACTORY);
+ JcrUtils.addPrivilege(session, SlcJcrConstants.SLC_BASE_PATH, SlcConstants.ROLE_SLC, Privilege.JCR_ALL);
+ if (!vmAgentFactoryNode.hasNode(agentNodeName)) {
+ String uuid = UUID.randomUUID().toString();
+ Node agentNode = vmAgentFactoryNode.addNode(agentNodeName, SlcTypes.SLC_AGENT);
+ agentNode.setProperty(SLC_UUID, uuid);
+ }
+ session.save();
+ return vmAgentFactoryNode.getNode(agentNodeName).getProperty(SLC_UUID).getString();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot find JCR agent UUID", e);
+ } finally {
+ JcrUtils.logoutQuietly(session);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ }
+
+ /*
+ * SLC AGENT
+ */
+ @Override
+ protected ProcessThread createProcessThread(ThreadGroup processesThreadGroup,
+ ExecutionModulesManager modulesManager, ExecutionProcess process) {
+ if (process instanceof JcrExecutionProcess)
+ return new JcrProcessThread(processesThreadGroup, modulesManager, (JcrExecutionProcess) process);
+ else
+ return super.createProcessThread(processesThreadGroup, modulesManager, process);
+ }
+
+ /*
+ * UTILITIES
+ */
+ public String getNodePath() {
+ return getAgentFactoryPath() + '/' + getAgentNodeName();
+ }
+
+ public String getAgentFactoryPath() {
+ try {
+ Boolean isRemote = System.getProperty(NODE_REPO_URI) != null;
+ String agentFactoryPath;
+ if (isRemote) {
+ InetAddress localhost = InetAddress.getLocalHost();
+ agentFactoryPath = SlcJcrConstants.AGENTS_BASE_PATH + "/" + localhost.getCanonicalHostName();
+
+ if (agentFactoryPath.equals(SlcJcrConstants.VM_AGENT_FACTORY_PATH))
+ throw new SlcException("Unsupported hostname " + localhost.getCanonicalHostName());
+ } else {// local
+ agentFactoryPath = SlcJcrConstants.VM_AGENT_FACTORY_PATH;
+ }
+ return agentFactoryPath;
+ } catch (UnknownHostException e) {
+ throw new SlcException("Cannot find agent factory base path", e);
+ }
+ }
+
+ /*
+ * BEAN
+ */
+ public String getAgentNodeName() {
+ return agentNodeName;
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ public void setAgentNodeName(String agentNodeName) {
+ this.agentNodeName = agentNodeName;
+ }
+}
--- /dev/null
+/*
+ * 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.jcr.execution;
+
+import javax.jcr.Session;
+
+import org.argeo.slc.core.attachment.Attachment;
+import org.argeo.slc.core.attachment.AttachmentUploader;
+import org.springframework.core.io.Resource;
+
+/** JCR based attachment uploader */
+public class JcrAttachmentUploader implements AttachmentUploader {
+ private Session session;
+
+ public void upload(Attachment attachment, Resource resource) {
+ session.toString();
+ // not yet implemented, need to review the interface
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+}
--- /dev/null
+/*
+ * 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.jcr.execution;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
+import org.argeo.slc.core.execution.PrimitiveValue;
+import org.argeo.slc.core.execution.RefSpecAttribute;
+import org.argeo.slc.core.execution.RefValueChoice;
+import org.argeo.slc.deploy.ModuleDescriptor;
+import org.argeo.slc.execution.ExecutionFlowDescriptor;
+import org.argeo.slc.execution.ExecutionModuleDescriptor;
+import org.argeo.slc.execution.ExecutionModulesListener;
+import org.argeo.slc.execution.ExecutionModulesManager;
+import org.argeo.slc.execution.ExecutionSpec;
+import org.argeo.slc.execution.ExecutionSpecAttribute;
+import org.argeo.slc.jcr.SlcJcrUtils;
+
+/**
+ * Synchronizes the local execution runtime with a JCR repository. For the time
+ * being the state is completely reset from one start to another.
+ */
+public class JcrExecutionModulesListener implements ExecutionModulesListener,
+ SlcNames {
+ private final static String SLC_EXECUTION_MODULES_PROPERTY = "slc.executionModules";
+
+ private final static Log log = LogFactory
+ .getLog(JcrExecutionModulesListener.class);
+ private JcrAgent agent;
+
+ private ExecutionModulesManager modulesManager;
+
+ private Repository repository;
+ /**
+ * We don't use a thread bound session because many different threads will
+ * call this critical component and we don't want to login each time. We
+ * therefore rather protect access to this session via synchronized.
+ */
+ private Session session;
+
+ /*
+ * LIFECYCLE
+ */
+ public void init() {
+ try {
+ session = repository.login();
+ clearAgent();
+ if (modulesManager != null) {
+ Node agentNode = session.getNode(agent.getNodePath());
+
+ List<ModuleDescriptor> moduleDescriptors = modulesManager
+ .listModules();
+
+ // scan SLC-ExecutionModule metadata
+ for (ModuleDescriptor md : moduleDescriptors) {
+ if (md.getMetadata().containsKey(
+ ExecutionModuleDescriptor.SLC_EXECUTION_MODULE)) {
+ String moduleNodeName = SlcJcrUtils
+ .getModuleNodeName(md);
+ Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
+ .getNode(moduleNodeName) : agentNode
+ .addNode(moduleNodeName);
+ moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
+ moduleNode.setProperty(SLC_NAME, md.getName());
+ moduleNode.setProperty(SLC_VERSION, md.getVersion());
+ moduleNode.setProperty(Property.JCR_TITLE,
+ md.getTitle());
+ moduleNode.setProperty(Property.JCR_DESCRIPTION,
+ md.getDescription());
+ moduleNode.setProperty(SLC_STARTED, md.getStarted());
+ }
+ }
+
+ // scan execution modules property
+ String executionModules = System
+ .getProperty(SLC_EXECUTION_MODULES_PROPERTY);
+ if (executionModules != null) {
+ for (String executionModule : executionModules.split(",")) {
+ allModules: for (ModuleDescriptor md : moduleDescriptors) {
+ String moduleNodeName = SlcJcrUtils
+ .getModuleNodeName(md);
+ if (md.getName().equals(executionModule)) {
+ Node moduleNode = agentNode
+ .hasNode(moduleNodeName) ? agentNode
+ .getNode(moduleNodeName) : agentNode
+ .addNode(moduleNodeName);
+ moduleNode
+ .addMixin(SlcTypes.SLC_EXECUTION_MODULE);
+ moduleNode.setProperty(SLC_NAME, md.getName());
+ moduleNode.setProperty(SLC_VERSION,
+ md.getVersion());
+ moduleNode.setProperty(Property.JCR_TITLE,
+ md.getTitle());
+ moduleNode.setProperty(
+ Property.JCR_DESCRIPTION,
+ md.getDescription());
+ moduleNode.setProperty(SLC_STARTED,
+ md.getStarted());
+ break allModules;
+ }
+ }
+ }
+
+ // save if needed
+ if (session.hasPendingChanges())
+ session.save();
+ }
+ }
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ JcrUtils.logoutQuietly(session);
+ throw new SlcException("Cannot initialize modules", e);
+ }
+ }
+
+ public void destroy() {
+ clearAgent();
+ JcrUtils.logoutQuietly(session);
+ }
+
+ protected synchronized void clearAgent() {
+ try {
+ Node agentNode = session.getNode(agent.getNodePath());
+ for (NodeIterator nit = agentNode.getNodes(); nit.hasNext();)
+ nit.nextNode().remove();
+ session.save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot clear agent " + agent, e);
+ }
+ }
+
+ /*
+ * EXECUTION MODULES LISTENER
+ */
+
+ public synchronized void executionModuleAdded(
+ ModuleDescriptor moduleDescriptor) {
+ syncExecutionModule(moduleDescriptor);
+ }
+
+ protected void syncExecutionModule(ModuleDescriptor moduleDescriptor) {
+ try {
+ Node agentNode = session.getNode(agent.getNodePath());
+ String moduleNodeName = SlcJcrUtils
+ .getModuleNodeName(moduleDescriptor);
+ Node moduleNode = agentNode.hasNode(moduleNodeName) ? agentNode
+ .getNode(moduleNodeName) : agentNode
+ .addNode(moduleNodeName);
+ moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
+ moduleNode.setProperty(SLC_NAME, moduleDescriptor.getName());
+ moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
+ moduleNode.setProperty(Property.JCR_TITLE,
+ moduleDescriptor.getTitle());
+ moduleNode.setProperty(Property.JCR_DESCRIPTION,
+ moduleDescriptor.getDescription());
+ moduleNode.setProperty(SLC_STARTED, moduleDescriptor.getStarted());
+ session.save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot sync module " + moduleDescriptor, e);
+ }
+ }
+
+ public synchronized void executionModuleRemoved(
+ ModuleDescriptor moduleDescriptor) {
+ try {
+ String moduleName = SlcJcrUtils.getModuleNodeName(moduleDescriptor);
+ Node agentNode = session.getNode(agent.getNodePath());
+ if (agentNode.hasNode(moduleName)) {
+ Node moduleNode = agentNode.getNode(moduleName);
+ for (NodeIterator nit = moduleNode.getNodes(); nit.hasNext();) {
+ nit.nextNode().remove();
+ }
+ moduleNode.setProperty(SLC_STARTED, false);
+ }
+ session.save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot remove module " + moduleDescriptor,
+ e);
+ }
+ }
+
+ public synchronized void executionFlowAdded(ModuleDescriptor module,
+ ExecutionFlowDescriptor efd) {
+ try {
+ Node agentNode = session.getNode(agent.getNodePath());
+ Node moduleNode = agentNode.getNode(SlcJcrUtils
+ .getModuleNodeName(module));
+ String relativePath = getExecutionFlowRelativePath(efd);
+ @SuppressWarnings("unused")
+ Node flowNode = null;
+ if (!moduleNode.hasNode(relativePath)) {
+ flowNode = createExecutionFlowNode(moduleNode, relativePath,
+ efd);
+ session.save();
+ } else {
+ flowNode = moduleNode.getNode(relativePath);
+ }
+
+ if (log.isTraceEnabled())
+ log.trace("Flow " + efd + " added to JCR");
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new SlcException("Cannot add flow " + efd + " from module "
+ + module, e);
+ }
+
+ }
+
+ protected Node createExecutionFlowNode(Node moduleNode,
+ String relativePath, ExecutionFlowDescriptor efd)
+ throws RepositoryException {
+ Node flowNode = null;
+ List<String> pathTokens = Arrays.asList(relativePath.split("/"));
+
+ Iterator<String> names = pathTokens.iterator();
+ // create intermediary paths
+ Node currNode = moduleNode;
+ while (names.hasNext()) {
+ String name = names.next();
+ if (currNode.hasNode(name))
+ currNode = currNode.getNode(name);
+ else {
+ if (names.hasNext())
+ currNode = currNode.addNode(name);
+ else
+ flowNode = currNode.addNode(name,
+ SlcTypes.SLC_EXECUTION_FLOW);
+ }
+ }
+
+ // name, description
+ flowNode.setProperty(SLC_NAME, efd.getName());
+ String endName = pathTokens.get(pathTokens.size() - 1);
+ flowNode.setProperty(Property.JCR_TITLE, endName);
+ if (efd.getDescription() != null
+ && !efd.getDescription().trim().equals("")) {
+ flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
+ } else {
+ flowNode.setProperty(Property.JCR_DESCRIPTION, endName);
+ }
+
+ // execution spec
+ ExecutionSpec executionSpec = efd.getExecutionSpec();
+ String esName = executionSpec.getName();
+ if (esName == null || esName.equals(ExecutionSpec.INTERNAL_NAME)
+ || esName.contains("#")/* automatically generated bean name */) {
+ // internal spec node
+ mapExecutionSpec(flowNode, executionSpec);
+ } else {
+ // reference spec node
+ Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
+ .getNode(SLC_EXECUTION_SPECS) : moduleNode
+ .addNode(SLC_EXECUTION_SPECS);
+ Node executionSpecNode = executionSpecsNode.addNode(esName,
+ SlcTypes.SLC_EXECUTION_SPEC);
+ executionSpecNode.setProperty(SLC_NAME, esName);
+ executionSpecNode.setProperty(Property.JCR_TITLE, esName);
+ if (executionSpec.getDescription() != null
+ && !executionSpec.getDescription().trim().equals(""))
+ executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
+ executionSpec.getDescription());
+ mapExecutionSpec(executionSpecNode, executionSpec);
+ flowNode.setProperty(SLC_SPEC, executionSpecNode);
+ }
+
+ // flow values
+ for (String attr : efd.getValues().keySet()) {
+ ExecutionSpecAttribute esa = executionSpec.getAttributes()
+ .get(attr);
+ if (esa instanceof PrimitiveSpecAttribute) {
+ PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
+ // if spec reference there will be no node at this stage
+ Node valueNode = JcrUtils.getOrAdd(flowNode, attr);
+ valueNode.setProperty(SLC_TYPE, psa.getType());
+ SlcJcrUtils.setPrimitiveAsProperty(valueNode, SLC_VALUE,
+ (PrimitiveValue) efd.getValues().get(attr));
+ }
+ }
+
+ return flowNode;
+ }
+
+ /**
+ * Base can be either an execution spec node, or an execution flow node (in
+ * case the execution spec is internal)
+ */
+ protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
+ throws RepositoryException {
+ for (String attrName : executionSpec.getAttributes().keySet()) {
+ ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
+ attrName);
+ Node attrNode = baseNode.addNode(attrName);
+ // booleans
+ attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
+ attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
+ attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
+ attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
+
+ if (esa instanceof PrimitiveSpecAttribute) {
+ attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
+ PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
+ SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
+ attrNode.setProperty(SLC_TYPE, psa.getType());
+ } else if (esa instanceof RefSpecAttribute) {
+ attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
+ RefSpecAttribute rsa = (RefSpecAttribute) esa;
+ attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
+ Object value = rsa.getValue();
+ if (rsa.getChoices() != null) {
+ Integer index = null;
+ int count = 0;
+ for (RefValueChoice choice : rsa.getChoices()) {
+ String name = choice.getName();
+ if (value != null && name.equals(value.toString()))
+ index = count;
+ Node choiceNode = attrNode.addNode(choice.getName());
+ choiceNode.addMixin(NodeType.MIX_TITLE);
+ choiceNode.setProperty(Property.JCR_TITLE,
+ choice.getName());
+ if (choice.getDescription() != null
+ && !choice.getDescription().trim().equals(""))
+ choiceNode.setProperty(Property.JCR_DESCRIPTION,
+ choice.getDescription());
+ count++;
+ }
+
+ if (index != null)
+ attrNode.setProperty(SLC_VALUE, index);
+ }
+ }
+ }
+ }
+
+ public synchronized void executionFlowRemoved(ModuleDescriptor module,
+ ExecutionFlowDescriptor executionFlow) {
+ try {
+ Node agentNode = session.getNode(agent.getNodePath());
+ Node moduleNode = agentNode.getNode(SlcJcrUtils
+ .getModuleNodeName(module));
+ String relativePath = getExecutionFlowRelativePath(executionFlow);
+ if (moduleNode.hasNode(relativePath))
+ moduleNode.getNode(relativePath).remove();
+ agentNode.getSession().save();
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot remove flow " + executionFlow
+ + " from module " + module, e);
+ }
+ }
+
+ /*
+ * UTILITIES
+ */
+ /** @return the relative path, never starts with '/' */
+ @SuppressWarnings("deprecation")
+ protected String getExecutionFlowRelativePath(
+ ExecutionFlowDescriptor executionFlow) {
+ String relativePath = executionFlow.getPath() == null ? executionFlow
+ .getName() : executionFlow.getPath() + '/'
+ + executionFlow.getName();
+ // we assume that it is more than one char long
+ if (relativePath.charAt(0) == '/')
+ relativePath = relativePath.substring(1);
+ // FIXME quick hack to avoid duplicate '/'
+ relativePath = relativePath.replaceAll("//", "/");
+ return relativePath;
+ }
+
+ /*
+ * BEAN
+ */
+ public void setAgent(JcrAgent agent) {
+ this.agent = agent;
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ public void setModulesManager(ExecutionModulesManager modulesManager) {
+ this.modulesManager = modulesManager;
+ }
+
+}
--- /dev/null
+/*
+ * 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.jcr.execution;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.execution.ProcessThread;
+import org.argeo.slc.execution.ExecutionProcess;
+import org.argeo.slc.execution.ExecutionStep;
+import org.argeo.slc.execution.RealizedFlow;
+import org.argeo.slc.jcr.SlcJcrUtils;
+
+/** Execution process implementation based on a JCR node. */
+public class JcrExecutionProcess implements ExecutionProcess, SlcNames {
+ private final static Log log = LogFactory.getLog(JcrExecutionProcess.class);
+ private final Node node;
+
+ private Long nextLogLine = 1l;
+
+ public JcrExecutionProcess(Node node) {
+ this.node = node;
+ }
+
+ public synchronized String getUuid() {
+ try {
+ return node.getProperty(SLC_UUID).getString();
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot get uuid for " + node, e);
+ }
+ }
+
+ public synchronized String getStatus() {
+ try {
+ return node.getProperty(SLC_STATUS).getString();
+ } catch (RepositoryException e) {
+ log.error("Cannot get status: " + e);
+ // we should re-throw exception because this information can
+ // probably used for monitoring in case there are already unexpected
+ // exceptions
+ return UNKOWN;
+ }
+ }
+
+ public synchronized void setStatus(String status) {
+ try {
+ node.setProperty(SLC_STATUS, status);
+ // last modified properties needs to be manually updated
+ // see https://issues.apache.org/jira/browse/JCR-2233
+ JcrUtils.updateLastModified(node);
+ node.getSession().save();
+ } catch (RepositoryException e) {
+ JcrUtils.discardUnderlyingSessionQuietly(node);
+ // we should re-throw exception because this information can
+ // probably used for monitoring in case there are already unexpected
+ // exceptions
+ log.error("Cannot set status " + status + ": " + e);
+ }
+ }
+
+ /**
+ * Synchronized in order to make sure that there is no concurrent
+ * modification of {@link #nextLogLine}.
+ */
+ public synchronized void addSteps(List<ExecutionStep> steps) {
+ try {
+ steps: for (ExecutionStep step : steps) {
+ String type;
+ if (step.getType().equals(ExecutionStep.TRACE))
+ type = SlcTypes.SLC_LOG_TRACE;
+ else if (step.getType().equals(ExecutionStep.DEBUG))
+ type = SlcTypes.SLC_LOG_DEBUG;
+ else if (step.getType().equals(ExecutionStep.INFO))
+ type = SlcTypes.SLC_LOG_INFO;
+ else if (step.getType().equals(ExecutionStep.WARNING))
+ type = SlcTypes.SLC_LOG_WARNING;
+ else if (step.getType().equals(ExecutionStep.ERROR))
+ type = SlcTypes.SLC_LOG_ERROR;
+ else
+ // skip
+ continue steps;
+
+ String relPath = SLC_LOG + '/'
+ + step.getThread().replace('/', '_') + '/'
+ + step.getLocation().replace('.', '/');
+ String path = node.getPath() + '/' + relPath;
+ // clean special character
+ // TODO factorize in JcrUtils
+ path = path.replace('@', '_');
+
+ Node location = JcrUtils.mkdirs(node.getSession(), path);
+ Node logEntry = location.addNode(Long.toString(nextLogLine),
+ type);
+ logEntry.setProperty(SLC_MESSAGE, step.getLog());
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTime(step.getTimestamp());
+ logEntry.setProperty(SLC_TIMESTAMP, calendar);
+
+ // System.out.println("Logged " + logEntry.getPath());
+
+ nextLogLine++;
+ }
+
+ // last modified properties needs to be manually updated
+ // see https://issues.apache.org/jira/browse/JCR-2233
+ JcrUtils.updateLastModified(node);
+
+ node.getSession().save();
+ } catch (Exception e) {
+ JcrUtils.discardUnderlyingSessionQuietly(node);
+ e.printStackTrace();
+ }
+ }
+
+ // public Node getNode() {
+ // return node;
+ // }
+
+ public List<RealizedFlow> getRealizedFlows() {
+ try {
+ List<RealizedFlow> realizedFlows = new ArrayList<RealizedFlow>();
+ Node rootRealizedFlowNode = node.getNode(SLC_FLOW);
+ // we just manage one level for the time being
+ NodeIterator nit = rootRealizedFlowNode.getNodes(SLC_FLOW);
+ while (nit.hasNext()) {
+ Node realizedFlowNode = nit.nextNode();
+
+ if (realizedFlowNode.hasNode(SLC_ADDRESS)) {
+ String flowPath = realizedFlowNode.getNode(SLC_ADDRESS)
+ .getProperty(Property.JCR_PATH).getString();
+ NameVersion moduleNameVersion = SlcJcrUtils
+ .moduleNameVersion(flowPath);
+ ((ProcessThread) Thread.currentThread())
+ .getExecutionModulesManager().start(
+ moduleNameVersion);
+ }
+
+ RealizedFlow realizedFlow = new JcrRealizedFlow(
+ realizedFlowNode);
+ if (realizedFlow != null)
+ realizedFlows.add(realizedFlow);
+ }
+ return realizedFlows;
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot get realized flows", e);
+ }
+ }
+
+ public String getNodePath() {
+ try {
+ return node.getPath();
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot get process node path for " + node,
+ e);
+ }
+ }
+
+ public Repository getRepository() {
+ try {
+ return node.getSession().getRepository();
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot get process JCR repository for "
+ + node, e);
+ }
+ }
+}
--- /dev/null
+/*
+
+ * 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.jcr.execution;
+
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.core.execution.ProcessThread;
+import org.argeo.slc.execution.ExecutionModulesManager;
+import org.argeo.slc.execution.ExecutionProcess;
+import org.argeo.slc.execution.RealizedFlow;
+
+/** Where the actual execution takes place */
+public class JcrProcessThread extends ProcessThread implements SlcNames {
+
+ public JcrProcessThread(ThreadGroup processesThreadGroup,
+ ExecutionModulesManager executionModulesManager,
+ JcrExecutionProcess process) {
+ super(processesThreadGroup, executionModulesManager, process);
+ }
+
+ /** Overridden in order to set progress status on realized flow nodes. */
+ @Override
+ protected void process() throws InterruptedException {
+ Session session = null;
+ if (getProcess() instanceof JcrExecutionProcess)
+ try {
+ session = ((JcrExecutionProcess) getProcess()).getRepository()
+ .login();
+
+ List<RealizedFlow> realizedFlows = getProcess()
+ .getRealizedFlows();
+ for (RealizedFlow realizedFlow : realizedFlows) {
+ Node realizedFlowNode = session
+ .getNode(((JcrRealizedFlow) realizedFlow).getPath());
+ setFlowStatus(realizedFlowNode, ExecutionProcess.RUNNING);
+
+ try {
+ //
+ // EXECUTE THE FLOW
+ //
+ execute(realizedFlow, true);
+
+ setFlowStatus(realizedFlowNode,
+ ExecutionProcess.COMPLETED);
+ } catch (RepositoryException e) {
+ throw e;
+ } catch (InterruptedException e) {
+ setFlowStatus(realizedFlowNode, ExecutionProcess.KILLED);
+ throw e;
+ } catch (RuntimeException e) {
+ setFlowStatus(realizedFlowNode, ExecutionProcess.ERROR);
+ throw e;
+ }
+ }
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot process "
+ + getJcrExecutionProcess().getNodePath(), e);
+ } finally {
+ JcrUtils.logoutQuietly(session);
+ }
+ else
+ super.process();
+ }
+
+ protected void setFlowStatus(Node realizedFlowNode, String status)
+ throws RepositoryException {
+ realizedFlowNode.setProperty(SLC_STATUS, status);
+ realizedFlowNode.getSession().save();
+ }
+
+ protected JcrExecutionProcess getJcrExecutionProcess() {
+ return (JcrExecutionProcess) getProcess();
+ }
+}
--- /dev/null
+package org.argeo.slc.jcr.execution;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.argeo.slc.SlcException;
+import org.argeo.slc.SlcNames;
+import org.argeo.slc.SlcTypes;
+import org.argeo.slc.core.execution.DefaultExecutionSpec;
+import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
+import org.argeo.slc.core.execution.PrimitiveUtils;
+import org.argeo.slc.core.execution.RefSpecAttribute;
+import org.argeo.slc.execution.ExecutionFlowDescriptor;
+import org.argeo.slc.execution.ExecutionSpecAttribute;
+import org.argeo.slc.execution.RealizedFlow;
+import org.argeo.slc.jcr.SlcJcrUtils;
+
+public class JcrRealizedFlow extends RealizedFlow implements SlcNames {
+ private static final long serialVersionUID = -3709453850260712001L;
+ private String path;
+
+ public JcrRealizedFlow(Node node) {
+ try {
+ this.path = node.getPath();
+ loadFromNode(node);
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot initialize from " + node, e);
+ }
+ }
+
+ protected void loadFromNode(Node realizedFlowNode)
+ throws RepositoryException {
+ if (realizedFlowNode.hasNode(SLC_ADDRESS)) {
+ String flowPath = realizedFlowNode.getNode(SLC_ADDRESS)
+ .getProperty(Property.JCR_PATH).getString();
+ // TODO: convert to local path if remote
+ // FIXME start related module
+ Node flowNode = realizedFlowNode.getSession().getNode(flowPath);
+ String flowName = flowNode.getProperty(SLC_NAME).getString();
+ String description = null;
+ if (flowNode.hasProperty(Property.JCR_DESCRIPTION))
+ description = flowNode.getProperty(Property.JCR_DESCRIPTION)
+ .getString();
+
+ Node executionModuleNode = flowNode.getSession().getNode(
+ SlcJcrUtils.modulePath(flowPath));
+ String executionModuleName = executionModuleNode.getProperty(
+ SLC_NAME).getString();
+ String executionModuleVersion = executionModuleNode.getProperty(
+ SLC_VERSION).getString();
+
+ RealizedFlow realizedFlow = this;
+ realizedFlow.setModuleName(executionModuleName);
+ realizedFlow.setModuleVersion(executionModuleVersion);
+
+ // retrieve execution spec
+ DefaultExecutionSpec executionSpec = new DefaultExecutionSpec();
+ Map<String, ExecutionSpecAttribute> attrs = readExecutionSpecAttributes(realizedFlowNode);
+ executionSpec.setAttributes(attrs);
+
+ // set execution spec name
+ if (flowNode.hasProperty(SlcNames.SLC_SPEC)) {
+ Node executionSpecNode = flowNode.getProperty(SLC_SPEC)
+ .getNode();
+ executionSpec.setBeanName(executionSpecNode.getProperty(
+ SLC_NAME).getString());
+ }
+
+ // explicitly retrieve values
+ Map<String, Object> values = new HashMap<String, Object>();
+ for (String attrName : attrs.keySet()) {
+ ExecutionSpecAttribute attr = attrs.get(attrName);
+ Object value = attr.getValue();
+ values.put(attrName, value);
+ }
+
+ ExecutionFlowDescriptor efd = new ExecutionFlowDescriptor(flowName,
+ description, values, executionSpec);
+ realizedFlow.setFlowDescriptor(efd);
+ } else {
+ throw new SlcException("Unsupported realized flow "
+ + realizedFlowNode);
+ }
+ }
+
+ protected Map<String, ExecutionSpecAttribute> readExecutionSpecAttributes(
+ Node node) {
+ try {
+ Map<String, ExecutionSpecAttribute> attrs = new HashMap<String, ExecutionSpecAttribute>();
+ for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
+ Node specAttrNode = nit.nextNode();
+ if (specAttrNode
+ .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
+ String type = specAttrNode.getProperty(SLC_TYPE)
+ .getString();
+ Object value = null;
+ if (specAttrNode.hasProperty(SLC_VALUE)) {
+ String valueStr = specAttrNode.getProperty(SLC_VALUE)
+ .getString();
+ value = PrimitiveUtils.convert(type, valueStr);
+ }
+ PrimitiveSpecAttribute specAttr = new PrimitiveSpecAttribute(
+ type, value);
+ attrs.put(specAttrNode.getName(), specAttr);
+ } else if (specAttrNode
+ .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
+ if (!specAttrNode.hasProperty(SLC_VALUE)) {
+ continue;
+ }
+ Integer value = (int) specAttrNode.getProperty(SLC_VALUE)
+ .getLong();
+ RefSpecAttribute specAttr = new RefSpecAttribute();
+ NodeIterator children = specAttrNode.getNodes();
+ int index = 0;
+ String id = null;
+ while (children.hasNext()) {
+ Node child = children.nextNode();
+ if (index == value)
+ id = child.getName();
+ index++;
+ }
+ specAttr.setValue(id);
+ attrs.put(specAttrNode.getName(), specAttr);
+ }
+ // throw new SlcException("Unsupported spec attribute "
+ // + specAttrNode);
+ }
+ return attrs;
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot read spec attributes from " + node,
+ e);
+ }
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+/** <b>Experimental</b> A structured set of OSGi bundles. */
+public interface BundleRegister {
+ /**
+ * @param pkg
+ * the Java package
+ * @param version
+ * the version, can be only major.minor or null
+ * @return the bundle providing this package or null if none was found
+ */
+ public String bundleProvidingPackage(String pkg, String version);
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.util.Collection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextEvent;
+import org.eclipse.gemini.blueprint.context.event.OsgiBundleApplicationContextListener;
+import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextClosedEvent;
+import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextFailedEvent;
+import org.eclipse.gemini.blueprint.context.event.OsgiBundleContextRefreshedEvent;
+import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
+import org.eclipse.gemini.blueprint.util.OsgiFilterUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.util.Assert;
+
+/** Wraps low-level access to a {@link BundleContext} */
+@SuppressWarnings("deprecation")
+public class BundlesManager implements BundleContextAware, FrameworkListener,
+ InitializingBean, DisposableBean,
+ OsgiBundleApplicationContextListener<OsgiBundleApplicationContextEvent> {
+ private final static Log log = LogFactory.getLog(BundlesManager.class);
+
+ private BundleContext bundleContext;
+
+ private Long defaultTimeout = 60 * 1000l;
+ private Long pollingPeriod = 200l;
+
+ // Refresh sync objects
+ private final Object refreshedPackageSem = new Object();
+ private Boolean packagesRefreshed = false;
+
+ public BundlesManager() {
+ }
+
+ public BundlesManager(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ /**
+ * Stop the module, update it, refresh it and restart it. All synchronously.
+ */
+ public void upgradeSynchronous(OsgiBundle osgiBundle) {
+ try {
+ Bundle bundle = findRelatedBundle(osgiBundle);
+
+ long begin = System.currentTimeMillis();
+
+ long bStop = begin;
+ stopSynchronous(bundle);
+
+ long bUpdate = System.currentTimeMillis();
+ updateSynchronous(bundle);
+
+ // Refresh in case there are fragments
+ long bRefresh = System.currentTimeMillis();
+ refreshSynchronous(bundle);
+
+ long bStart = System.currentTimeMillis();
+ startSynchronous(bundle);
+
+ long aStart = System.currentTimeMillis();
+ if (log.isTraceEnabled()) {
+ log.debug("OSGi upgrade performed in " + (aStart - begin)
+ + "ms for bundle " + osgiBundle);
+ log.debug(" stop \t: " + (bUpdate - bStop) + "ms");
+ log.debug(" update\t: " + (bRefresh - bUpdate) + "ms");
+ log.debug(" refresh\t: " + (bStart - bRefresh) + "ms");
+ log.debug(" start\t: " + (aStart - bStart) + "ms");
+ log.debug(" TOTAL\t: " + (aStart - begin) + "ms");
+ }
+
+ long bAppContext = System.currentTimeMillis();
+ String filter = "(Bundle-SymbolicName=" + bundle.getSymbolicName()
+ + ")";
+ // Wait for application context to be ready
+ // TODO: use service tracker
+ Collection<ServiceReference<ApplicationContext>> srs = getServiceRefSynchronous(
+ ApplicationContext.class, filter);
+ ServiceReference<ApplicationContext> sr = srs.iterator().next();
+ long aAppContext = System.currentTimeMillis();
+ long end = aAppContext;
+
+ if (log.isTraceEnabled()) {
+ log.debug("Application context refresh performed in "
+ + (aAppContext - bAppContext) + "ms for bundle "
+ + osgiBundle);
+ }
+
+ if (log.isDebugEnabled())
+ log.debug("Bundle '" + bundle.getSymbolicName()
+ + "' upgraded and ready " + " (upgrade performed in "
+ + (end - begin) + "ms).");
+
+ if (log.isTraceEnabled()) {
+ ApplicationContext applicationContext = (ApplicationContext) bundleContext
+ .getService(sr);
+ int beanDefCount = applicationContext.getBeanDefinitionCount();
+ log.debug(" " + beanDefCount + " beans in app context of "
+ + bundle.getSymbolicName()
+ + ", average init time per bean=" + (end - begin)
+ / beanDefCount + "ms");
+ }
+
+ bundleContext.ungetService(sr);
+
+ } catch (Exception e) {
+ throw new SlcException("Cannot update bundle " + osgiBundle, e);
+ }
+ }
+
+ /** Updates bundle synchronously. */
+ protected void updateSynchronous(Bundle bundle) throws BundleException {
+ bundle.update();
+ boolean waiting = true;
+
+ long begin = System.currentTimeMillis();
+ do {
+ int state = bundle.getState();
+ if (state == Bundle.INSTALLED || state == Bundle.ACTIVE
+ || state == Bundle.RESOLVED)
+ waiting = false;
+
+ sleepWhenPolling();
+ checkTimeout(begin, "Update of bundle " + bundle.getSymbolicName()
+ + " timed out. Bundle state = " + bundle.getState());
+ } while (waiting);
+
+ if (log.isTraceEnabled())
+ log.debug("Bundle " + bundle.getSymbolicName() + " updated.");
+ }
+
+ /** Starts bundle synchronously. Does nothing if already started. */
+ protected void startSynchronous(Bundle bundle) throws BundleException {
+ int originalState = bundle.getState();
+ if (originalState == Bundle.ACTIVE)
+ return;
+
+ bundle.start();
+ boolean waiting = true;
+
+ long begin = System.currentTimeMillis();
+ do {
+ if (bundle.getState() == Bundle.ACTIVE)
+ waiting = false;
+
+ sleepWhenPolling();
+ checkTimeout(begin, "Start of bundle " + bundle.getSymbolicName()
+ + " timed out. Bundle state = " + bundle.getState());
+ } while (waiting);
+
+ if (log.isTraceEnabled())
+ log.debug("Bundle " + bundle.getSymbolicName() + " started.");
+ }
+
+ /** Stops bundle synchronously. Does nothing if already started. */
+ protected void stopSynchronous(Bundle bundle) throws BundleException {
+ int originalState = bundle.getState();
+ if (originalState != Bundle.ACTIVE)
+ return;
+
+ bundle.stop();
+ boolean waiting = true;
+
+ long begin = System.currentTimeMillis();
+ do {
+ if (bundle.getState() != Bundle.ACTIVE
+ && bundle.getState() != Bundle.STOPPING)
+ waiting = false;
+
+ sleepWhenPolling();
+ checkTimeout(begin, "Stop of bundle " + bundle.getSymbolicName()
+ + " timed out. Bundle state = " + bundle.getState());
+ } while (waiting);
+
+ if (log.isTraceEnabled())
+ log.debug("Bundle " + bundle.getSymbolicName() + " stopped.");
+ }
+
+ /** Refresh bundle synchronously. Does nothing if already started. */
+ protected void refreshSynchronous(Bundle bundle) throws BundleException {
+ ServiceReference<PackageAdmin> packageAdminRef = bundleContext
+ .getServiceReference(PackageAdmin.class);
+ PackageAdmin packageAdmin = (PackageAdmin) bundleContext
+ .getService(packageAdminRef);
+ Bundle[] bundles = { bundle };
+
+ long begin = System.currentTimeMillis();
+ synchronized (refreshedPackageSem) {
+ packagesRefreshed = false;
+ packageAdmin.refreshPackages(bundles);
+ try {
+ refreshedPackageSem.wait(defaultTimeout);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ if (!packagesRefreshed) {
+ long now = System.currentTimeMillis();
+ throw new SlcException("Packages not refreshed after "
+ + (now - begin) + "ms");
+ } else {
+ packagesRefreshed = false;
+ }
+ }
+
+ if (log.isTraceEnabled())
+ log.debug("Bundle " + bundle.getSymbolicName() + " refreshed.");
+ }
+
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+ synchronized (refreshedPackageSem) {
+ packagesRefreshed = true;
+ refreshedPackageSem.notifyAll();
+ }
+ }
+ }
+
+ public <S> Collection<ServiceReference<S>> getServiceRefSynchronous(
+ Class<S> clss, String filter) throws InvalidSyntaxException {
+ if (log.isTraceEnabled())
+ log.debug("Filter: '" + filter + "'");
+ Collection<ServiceReference<S>> sfs = null;
+ boolean waiting = true;
+ long begin = System.currentTimeMillis();
+ do {
+ sfs = bundleContext.getServiceReferences(clss, filter);
+
+ if (sfs != null)
+ waiting = false;
+
+ sleepWhenPolling();
+ checkTimeout(begin, "Search of services " + clss + " with filter "
+ + filter + " timed out.");
+ } while (waiting);
+
+ return sfs;
+ }
+
+ protected void checkTimeout(long begin, String msg) {
+ long now = System.currentTimeMillis();
+ if (now - begin > defaultTimeout)
+ throw new SlcException(msg + " (timeout after " + (now - begin)
+ + "ms)");
+
+ }
+
+ protected void sleepWhenPolling() {
+ try {
+ Thread.sleep(pollingPeriod);
+ } catch (InterruptedException e) {
+ throw new SlcException("Polling interrupted");
+ }
+ }
+
+ /** Creates and open a new service tracker. */
+ public <S> ServiceTracker<S, S> newTracker(Class<S> clss) {
+ ServiceTracker<S, S> st = new ServiceTracker<S, S>(bundleContext, clss,
+ null);
+ st.open();
+ return st;
+ }
+
+ public <T> T getSingleService(Class<T> clss, String filter,
+ Boolean synchronous) {
+ if (filter != null)
+ Assert.isTrue(OsgiFilterUtils.isValidFilter(filter), "valid filter");
+ Collection<ServiceReference<T>> sfs;
+ try {
+ if (synchronous)
+ sfs = getServiceRefSynchronous(clss, filter);
+ else
+ sfs = bundleContext.getServiceReferences(clss, filter);
+ } catch (InvalidSyntaxException e) {
+ throw new SlcException("Cannot retrieve service reference for "
+ + filter, e);
+ }
+
+ if (sfs == null || sfs.size() == 0)
+ return null;
+ else if (sfs.size() > 1)
+ throw new SlcException("More than one execution flow found for "
+ + filter);
+ return (T) bundleContext.getService(sfs.iterator().next());
+ }
+
+ public <T> T getSingleServiceStrict(Class<T> clss, String filter,
+ Boolean synchronous) {
+ T service = getSingleService(clss, filter, synchronous);
+ if (service == null)
+ throw new SlcException("No execution flow found for " + filter);
+ else
+ return service;
+ }
+
+ public OsgiBundle findRelatedBundle(String moduleName, String moduleVersion) {
+ OsgiBundle osgiBundle = new OsgiBundle(moduleName, moduleVersion);
+ if (osgiBundle.getVersion() == null) {
+ Bundle bundle = findRelatedBundle(osgiBundle);
+ osgiBundle = new OsgiBundle(bundle);
+ }
+ return osgiBundle;
+ }
+
+ /**
+ * @param osgiBundle
+ * cannot be null
+ * @return the related bundle or null if not found
+ * @throws SlcException
+ * if osgiBundle argument is null
+ */
+ public Bundle findRelatedBundle(OsgiBundle osgiBundle) {
+ if (osgiBundle == null)
+ throw new SlcException("OSGi bundle cannot be null");
+
+ Bundle bundle = null;
+ if (osgiBundle.getInternalBundleId() != null) {
+ bundle = bundleContext.getBundle(osgiBundle.getInternalBundleId());
+ Assert.isTrue(
+ osgiBundle.getName().equals(bundle.getSymbolicName()),
+ "symbolic name consistent");
+ if (osgiBundle.getVersion() != null)
+ Assert.isTrue(
+ osgiBundle.getVersion().equals(
+ bundle.getHeaders().get(
+ Constants.BUNDLE_VERSION)),
+ "version consistent");
+ } else if (osgiBundle.getVersion() == null
+ || osgiBundle.getVersion().equals("0.0.0")) {
+ bundle = OsgiBundleUtils.findBundleBySymbolicName(bundleContext,
+ osgiBundle.getName());
+ } else {// scan all bundles
+ bundles: for (Bundle b : bundleContext.getBundles()) {
+ if (b.getSymbolicName() == null) {
+ log.warn("Bundle " + b + " has no symbolic name defined.");
+ continue bundles;
+ }
+
+ if (b.getSymbolicName().equals(osgiBundle.getName())) {
+ if (osgiBundle.getVersion() == null) {
+ bundle = b;
+ break bundles;
+ }
+
+ if (b.getHeaders().get(Constants.BUNDLE_VERSION)
+ .equals(osgiBundle.getVersion())) {
+ bundle = b;
+ osgiBundle.setInternalBundleId(b.getBundleId());
+ break bundles;
+ }
+ }
+ }
+ }
+ return bundle;
+ }
+
+ /** Find a single bundle based on a symbolic name pattern. */
+ public OsgiBundle findFromPattern(String pattern) {
+ OsgiBundle osgiBundle = null;
+ for (Bundle b : bundleContext.getBundles()) {
+ if (b.getSymbolicName().contains(pattern)) {
+ osgiBundle = new OsgiBundle(b);
+ break;
+ }
+ }
+ return osgiBundle;
+ }
+
+ public OsgiBundle getBundle(Long bundleId) {
+ Bundle bundle = bundleContext.getBundle(bundleId);
+ return new OsgiBundle(bundle);
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ bundleContext.addFrameworkListener(this);
+ }
+
+ public void destroy() throws Exception {
+ bundleContext.removeFrameworkListener(this);
+ }
+
+ public void setDefaultTimeout(Long defaultTimeout) {
+ this.defaultTimeout = defaultTimeout;
+ }
+
+ /**
+ * Use with caution since it may interfer with some cached information
+ * within this object
+ */
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ public void setPollingPeriod(Long pollingPeriod) {
+ this.pollingPeriod = pollingPeriod;
+ }
+
+ public void onOsgiApplicationEvent(OsgiBundleApplicationContextEvent event) {
+ if (event instanceof OsgiBundleContextRefreshedEvent) {
+ log.debug("App context refreshed: " + event);
+ } else if (event instanceof OsgiBundleContextFailedEvent) {
+ log.debug("App context failed: " + event);
+ }
+ if (event instanceof OsgiBundleContextClosedEvent) {
+ log.debug("App context closed: " + event);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.Constants;
+
+/** <b>Experimental</b> */
+public class FileSystemBundleRegister implements BundleRegister {
+ private final static Log log = LogFactory
+ .getLog(FileSystemBundleRegister.class);
+ private Properties packagesBundles = null;
+
+ public String bundleProvidingPackage(String pkg, String version) {
+ if (packagesBundles == null)
+ return null;
+ return packagesBundles.getProperty(pkg);
+ }
+
+ protected void scan(File baseDirectory) {
+ long begin = System.currentTimeMillis();
+ int bundleCount = 0;
+ int packageCount = 0;
+
+ packagesBundles = new Properties();
+
+ File[] files = baseDirectory.listFiles();
+ for (File file : files) {
+ if (file.isDirectory()) {
+
+ } else {
+ JarFile jarFile = null;
+ try {
+ jarFile = new JarFile(file);
+ Manifest manifest = jarFile.getManifest();
+ String symbolicName = manifest.getMainAttributes()
+ .getValue(Constants.BUNDLE_SYMBOLICNAME);
+ String exportPackage = manifest.getMainAttributes()
+ .getValue(Constants.EXPORT_PACKAGE);
+
+ // List exported packages
+ Set<String> exportedPackages = exportPackageToPackageNames(exportPackage);
+
+ for (String exportedPackage : exportedPackages) {
+ packagesBundles.put(exportedPackage, symbolicName);
+ packageCount++;
+ if (log.isTraceEnabled())
+ log.trace("Register " + exportedPackage + "="
+ + symbolicName);
+ }
+ bundleCount++;
+ } catch (Exception e) {
+ log.warn("Cannot scan " + file, e);
+ if (log.isTraceEnabled())
+ e.printStackTrace();
+ } finally {
+ IOUtils.closeQuietly(jarFile);
+ }
+ }
+ }
+ if (log.isDebugEnabled())
+ log.debug("Scanned " + bundleCount + " bundles with "
+ + packageCount + " packages in "
+ + (System.currentTimeMillis() - begin) + " ms");
+ }
+
+ protected Set<String> exportPackageToPackageNames(String exportPackage) {
+ Set<String> exportedPackages = new HashSet<String>();
+ if (exportPackage == null)
+ return exportedPackages;
+ char[] arr = exportPackage.toCharArray();
+
+ StringBuffer currentPkg = new StringBuffer("");
+ boolean skip = false;
+ boolean inQuote = false;
+ for (char c : arr) {
+ if (c == ' ' || c == '\n') {
+ // ignore
+ } else if (c == ';') {
+ if (!skip)
+ skip = true;
+ } else if (c == ',') {
+ if (skip && !inQuote) {
+ skip = false;
+ // add new package
+ exportedPackages.add(currentPkg.toString());
+ currentPkg = new StringBuffer("");
+ }
+ } else if (c == '\"') {
+ inQuote = inQuote ? false : true;
+ } else {
+ if (!skip)
+ currentPkg.append(c);
+ }
+ }
+
+ return exportedPackages;
+ }
+
+ public static void main(String[] args) {
+ FileSystemBundleRegister fsbr = new FileSystemBundleRegister();
+ fsbr.scan(new File(
+ "/home/mbaudier/dev/src/slc/dist/org.argeo.slc.sdk/target/lib"));
+
+ }
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.Ordered;
+
+/** Publishes beans of the application context as OSGi services. */
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+public class MultipleServiceExporterPostProcessor implements
+ ApplicationListener, Ordered {
+ private final static Log log = LogFactory
+ .getLog(MultipleServiceExporterPostProcessor.class);
+
+ private List<Class> interfaces = new ArrayList<Class>();
+
+ private int order = Ordered.LOWEST_PRECEDENCE;
+
+ private BundleContext bundleContext = null;
+
+ // private Class osgiServiceFactoryClass = OsgiServiceFactoryBean.class;
+ // private Boolean useServiceProviderContextClassLoader = false;
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ Map<String, Object> beans = new HashMap<String, Object>();
+ if (event instanceof ContextRefreshedEvent) {
+ if (bundleContext != null) {
+ for (Class clss : interfaces) {
+ ApplicationContext ac = ((ContextRefreshedEvent) event)
+ .getApplicationContext();
+ beans.putAll(ac.getBeansOfType(clss, false, false));
+ }
+
+ int count = 0;
+ for (String beanName : beans.keySet()) {
+ Object bean = beans.get(beanName);
+ List<String> classes = new ArrayList<String>();
+ for (Class clss : interfaces) {
+ if (clss.isAssignableFrom(bean.getClass())) {
+ classes.add(clss.getName());
+ }
+ }
+ Properties props = new Properties();
+ Bundle bundle = bundleContext.getBundle();
+ props.put(Constants.BUNDLE_SYMBOLICNAME,
+ bundle.getSymbolicName());
+ props.put(Constants.BUNDLE_VERSION, bundle.getVersion());
+ // retrocompatibility with pre-1.0:
+ props.put("org.eclipse.gemini.blueprint.bean.name", beanName);
+ bundleContext.registerService(
+ classes.toArray(new String[classes.size()]), bean,
+ new Hashtable(props));
+ count++;
+ }
+ if (log.isTraceEnabled())
+ log.trace("Published " + count + " " + interfaces
+ + " as OSGi services from bundle "
+ + bundleContext.getBundle().getSymbolicName() + " "
+ + bundleContext.getBundle().getVersion());
+ // note: the services will be automatically unregistered when
+ // the bundle will be stopped
+ }
+ }
+ }
+
+ // public void postProcessBeanFactory(
+ // ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ // if (!(beanFactory instanceof BeanDefinitionRegistry)) {
+ // throw new SlcException("Can only work on "
+ // + BeanDefinitionRegistry.class);
+ // }
+ //
+ // long begin = System.currentTimeMillis();
+ //
+ // // Merge all beans implementing these interfaces
+ // Set<String> beanNames = new HashSet<String>();
+ // for (Class clss : interfaces) {
+ // String[] strs = beanFactory.getBeanNamesForType(clss, true, false);
+ // beanNames.addAll(Arrays.asList(strs));
+ // }
+ //
+ // // Register service factory beans for them
+ // for (String beanName : beanNames) {
+ // MutablePropertyValues mpv = new MutablePropertyValues();
+ // mpv.addPropertyValue("interfaces", interfaces.toArray());
+ // mpv.addPropertyValue("targetBeanName", beanName);
+ // if (useServiceProviderContextClassLoader)
+ // mpv.addPropertyValue("contextClassLoader",
+ // ExportContextClassLoader.SERVICE_PROVIDER);
+ // RootBeanDefinition bd = new RootBeanDefinition(
+ // osgiServiceFactoryClass, mpv);
+ //
+ // String exporterBeanName = "osgiService." + beanName;
+ // if (log.isTraceEnabled())
+ // log.debug("Registering OSGi service exporter "
+ // + exporterBeanName);
+ // ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(
+ // exporterBeanName, bd);
+ // }
+ //
+ // long end = System.currentTimeMillis();
+ // if (log.isTraceEnabled())
+ // log.debug("Multiple services exported in " + (end - begin)
+ // + " ms in bundle.");
+ //
+ // }
+
+ public void setInterfaces(List<Class> interfaces) {
+ this.interfaces = interfaces;
+ }
+
+ // public void setOsgiServiceFactoryClass(Class osgiServiceFactoryClass) {
+ // this.osgiServiceFactoryClass = osgiServiceFactoryClass;
+ // }
+
+ public int getOrder() {
+ return order;
+ }
+
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ // public void setUseServiceProviderContextClassLoader(
+ // Boolean useServiceProviderContextClassLoader) {
+ // this.useServiceProviderContextClassLoader =
+ // useServiceProviderContextClassLoader;
+ // }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import org.argeo.slc.DefaultNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.core.build.ResourceDistribution;
+import org.argeo.slc.deploy.DeploymentData;
+import org.argeo.slc.deploy.Module;
+import org.argeo.slc.deploy.ModuleDescriptor;
+import org.argeo.slc.deploy.TargetData;
+import org.argeo.slc.execution.RealizedFlow;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.springframework.core.io.Resource;
+
+/** A deployed OSGi bundle. */
+public class OsgiBundle extends DefaultNameVersion implements Module {
+ private ResourceDistribution distribution;
+
+ private Long internalBundleId;
+
+ private String title;
+ private String description;
+
+ public OsgiBundle() {
+
+ }
+
+ public OsgiBundle(String name, String version) {
+ super(name, version);
+ }
+
+ public OsgiBundle(NameVersion nameVersion) {
+ super(nameVersion);
+ }
+
+ public OsgiBundle(Bundle bundle) {
+ super(bundle.getSymbolicName(), getVersionSafe(bundle));
+ internalBundleId = bundle.getBundleId();
+ }
+
+ /**
+ * Initialize from a {@link RealizedFlow}.
+ *
+ * @deprecated introduce an unnecessary dependency. TODO: create a separate
+ * helper.
+ */
+ public OsgiBundle(RealizedFlow realizedFlow) {
+ super(realizedFlow.getModuleName(), realizedFlow.getModuleVersion());
+ }
+
+ /** Utility to avoid NPE. */
+ private static String getVersionSafe(Bundle bundle) {
+ Object versionObj = bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+ if (versionObj != null)
+ return versionObj.toString();
+ else
+ return null;
+ }
+
+ /** Unique deployed system id. TODO: use internal bundle id when available? */
+ public String getDeployedSystemId() {
+ return getName() + ":" + getVersion();
+ }
+
+ /**
+ * OSGi bundle are self-contained and do not require additional deployment
+ * data.
+ *
+ * @return always null
+ */
+ public DeploymentData getDeploymentData() {
+ return null;
+ }
+
+ /** The related distribution. */
+ public Distribution getDistribution() {
+ return distribution;
+ }
+
+ /**
+ * The related distribution, a jar file with OSGi metadata referenced by a
+ * {@link Resource}.
+ */
+ public ResourceDistribution getResourceDistribution() {
+ return distribution;
+ }
+
+ /** TODO: reference the {@link OsgiRuntime} as target data? */
+ public TargetData getTargetData() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setResourceDistribution(ResourceDistribution distribution) {
+ this.distribution = distribution;
+ }
+
+ /**
+ * Bundle ID used by the OSGi runtime. To be used for optimization when
+ * looking in the bundle context. Can therefore be null.
+ */
+ public Long getInternalBundleId() {
+ return internalBundleId;
+ }
+
+ /** Only package access for the time being. e.g. from {@link BundlesManager} */
+ void setInternalBundleId(Long internalBundleId) {
+ this.internalBundleId = internalBundleId;
+ }
+
+ /** Value of the <code>Bundle-Name</code> directive. */
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String label) {
+ this.title = label;
+ }
+
+ /** Value of the <code>Bundle-Description</code> directive. */
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public ModuleDescriptor getModuleDescriptor() {
+ ModuleDescriptor moduleDescriptor = new ModuleDescriptor();
+ moduleDescriptor.setName(getName());
+ moduleDescriptor.setVersion(getVersion());
+ moduleDescriptor.setDescription(description);
+ moduleDescriptor.setTitle(title);
+ return moduleDescriptor;
+ }
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.core.execution.AbstractSpringExecutionModule;
+import org.argeo.slc.execution.ExecutionContext;
+
+@Deprecated
+public class OsgiExecutionModule extends AbstractSpringExecutionModule {
+ private final static Log log = LogFactory.getLog(OsgiExecutionModule.class);
+
+ public OsgiExecutionModule() {
+ log.error("######## ERROR - DEPRECATED APPROACH USED ########");
+ log.error(OsgiExecutionModule.class.getName() + " is deprecated. ");
+ log
+ .error("It will be removed in the next release. Remove its bean definition.");
+ log
+ .error("And replace: <service interface=\"org.argeo.slc.execution.ExecutionModule\" ref=\"executionModule\" />");
+ log
+ .error("by: <beans:import resource=\"classpath:org/argeo/slc/osgi/execution/spring.xml\" /> ");
+ log.error("in osgi.xml.\n\n");
+ }
+
+ public void setExecutionContext(ExecutionContext executionContext) {
+ // do nothing, just for compatibility
+ }
+
+ /*
+ * private BundleContext bundleContext;
+ *
+ * @Override public void execute(ExecutionFlowDescriptor
+ * executionFlowDescriptor) { if (descriptorConverter != null)
+ * executionContext.addVariables(descriptorConverter
+ * .convertValues(executionFlowDescriptor));
+ *
+ * ExecutionFlow flow = findExecutionFlow(getName(), getVersion(),
+ * executionFlowDescriptor.getName()); flow.run(); }
+ *
+ * @Override protected Map<String, ExecutionFlow> listFlows() { String
+ * filter = "(org.argeo.slc.execution.module.name=" + getName() + ")";
+ * ServiceReference[] sfs; try { sfs =
+ * bundleContext.getServiceReferences(ExecutionFlow.class .getName(),
+ * filter); } catch (InvalidSyntaxException e) { throw new SlcException(
+ * "Cannot retrieve service reference for flow " + filter, e); }
+ *
+ * Map<String, ExecutionFlow> flows = new HashMap<String, ExecutionFlow>();
+ * for (ServiceReference sf : sfs) { ExecutionFlow flow = (ExecutionFlow)
+ * bundleContext.getService(sf); flows.put(flow.getName(), flow); } return
+ * flows; }
+ *
+ * public String getName() { return
+ * bundleContext.getBundle().getSymbolicName(); }
+ *
+ * public String getVersion() { return
+ * bundleContext.getBundle().getHeaders().get("Bundle-Version") .toString();
+ * }
+ *
+ * public void setBundleContext(BundleContext bundleContext) {
+ * this.bundleContext = bundleContext; }
+ *
+ * protected ExecutionFlow findExecutionFlow(String moduleName, String
+ * moduleVersion, String flowName) { String filter =
+ * "(&(org.argeo.slc.execution.module.name=" + moduleName +
+ * ")(org.argeo.slc.execution.flow.name=" + flowName + "))";
+ * log.debug("OSGi filter: " + filter);
+ *
+ * Assert.isTrue(OsgiFilterUtils.isValidFilter(filter), "valid filter");
+ * ServiceReference[] sfs; try { sfs =
+ * bundleContext.getServiceReferences(ExecutionFlow.class .getName(),
+ * filter); } catch (InvalidSyntaxException e) { throw new
+ * SlcException("Cannot retrieve service reference for " + filter, e); }
+ *
+ * if (sfs == null || sfs.length == 0) throw new
+ * SlcException("No execution flow found for " + filter); else if
+ * (sfs.length > 1) throw new
+ * SlcException("More than one execution flow found for " + filter); return
+ * (ExecutionFlow) bundleContext.getService(sfs[0]); }
+ */
+
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.DefaultNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.AbstractExecutionModulesManager;
+import org.argeo.slc.core.execution.DefaultExecutionFlowDescriptorConverter;
+import org.argeo.slc.deploy.Module;
+import org.argeo.slc.deploy.ModuleDescriptor;
+import org.argeo.slc.execution.ExecutionContext;
+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.ExecutionModulesListener;
+import org.argeo.slc.execution.RealizedFlow;
+import org.eclipse.gemini.blueprint.service.importer.OsgiServiceLifecycleListener;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.launch.Framework;
+import org.springframework.context.ApplicationContext;
+
+/** Execution modules manager implementation based on an OSGi runtime. */
+public class OsgiExecutionModulesManager extends
+ AbstractExecutionModulesManager implements
+ OsgiServiceLifecycleListener, BundleListener {
+
+ private final static Log log = LogFactory
+ .getLog(OsgiExecutionModulesManager.class);
+
+ private BundlesManager bundlesManager;
+ private Map<OsgiBundle, ExecutionContext> executionContexts = new HashMap<OsgiBundle, ExecutionContext>();
+ private Map<OsgiBundle, ExecutionFlowDescriptorConverter> executionFlowDescriptorConverters = new HashMap<OsgiBundle, ExecutionFlowDescriptorConverter>();
+ private Map<OsgiBundle, Set<ExecutionFlow>> executionFlows = new HashMap<OsgiBundle, Set<ExecutionFlow>>();
+ private ExecutionFlowDescriptorConverter defaultDescriptorConverter = new DefaultExecutionFlowDescriptorConverter();
+
+ private List<ExecutionModulesListener> executionModulesListeners = new ArrayList<ExecutionModulesListener>();
+
+ private Boolean registerFlowsToJmx = false;
+
+ public void init() throws Exception {
+ bundlesManager.getBundleContext().addBundleListener(this);
+
+ final String module = System.getProperty(UNIQUE_LAUNCH_MODULE_PROPERTY);
+ final String flow = System.getProperty(UNIQUE_LAUNCH_FLOW_PROPERTY);
+ if (module != null) {
+ // launch a flow and stops
+ new Thread("Unique Flow") {
+ @Override
+ public void run() {
+ executeFlowAndExit(module, null, flow);
+ }
+ }.start();
+ }
+ }
+
+ public void destroy() {
+ bundlesManager.getBundleContext().removeBundleListener(this);
+ }
+
+ /** Executes a single flow and <b>stops the JVM</b> */
+ protected void executeFlowAndExit(final String module,
+ final String version, final String flow) {
+ if (log.isDebugEnabled())
+ log.debug("Launch unique flow " + flow + " from module " + module);
+ try {
+ OsgiBundle osgiBundle = bundlesManager.findFromPattern(module);
+ if (osgiBundle == null)
+ throw new SlcException("No OSGi bundle found for " + module);
+ // Bundle moduleBundle =
+ // bundlesManager.findRelatedBundle(osgiBundle);
+ start(osgiBundle);
+
+ RealizedFlow lastLaunch = findRealizedFlow(module, flow);
+ if (lastLaunch == null)
+ throw new SlcException("Cannot find launch for " + module + " "
+ + flow);
+ execute(lastLaunch);
+ } catch (Exception e) {
+ log.error(
+ "Error in unique flow " + flow + " from module " + module,
+ e);
+ } finally {
+ if (log.isDebugEnabled())
+ log.debug("Shutdown OSGi runtime...");
+ Framework framework = (Framework) bundlesManager.getBundleContext()
+ .getBundle(0);
+ try {
+ // shutdown framework
+ framework.stop();
+ // wait 1 min for shutdown
+ framework.waitForStop(60 * 1000);
+ // close VM
+ System.exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ }
+
+ // public void startExectionModule(String moduleName, String moduleVersion)
+ // {
+ // try {
+ // ServiceReference[] sr = bundlesManager.getServiceRefSynchronous(
+ // ApplicationContext.class.getName(),
+ // "org.springframework.context.service.name=" + moduleName);
+ // // bundlesManager.startSynchronous(moduleBundle);
+ // if (sr == null || sr.length == 0)
+ // throw new SlcException(
+ // "Cannot find execution module application context "
+ // + moduleName);
+ // } catch (InvalidSyntaxException e) {
+ // throw new SlcException("Cannot start exeuction module "
+ // + moduleName, e);
+ // }
+ // }
+
+ public synchronized ExecutionModuleDescriptor getExecutionModuleDescriptor(
+ String moduleName, String version) {
+ ExecutionModuleDescriptor md = new ExecutionModuleDescriptor();
+ OsgiBundle osgiBundle = null;
+ DefaultNameVersion nameVersion = new DefaultNameVersion(moduleName,
+ version);
+ bundles: for (Iterator<OsgiBundle> iterator = executionContexts
+ .keySet().iterator(); iterator.hasNext();) {
+ OsgiBundle ob = iterator.next();
+ if (nameVersion.getVersion() != null) {
+ if (ob.equals(nameVersion)) {
+ osgiBundle = ob;
+ break bundles;
+ }
+ } else {
+ if (ob.getName().equals(nameVersion.getName())) {
+ osgiBundle = ob;
+ break bundles;
+ }
+ }
+ }
+ if (osgiBundle == null)
+ throw new SlcException("No execution module registered for "
+ + nameVersion);
+ md.setName(osgiBundle.getName());
+ md.setVersion(osgiBundle.getVersion());
+ md.setTitle(osgiBundle.getTitle());
+ md.setDescription(osgiBundle.getDescription());
+
+ ExecutionFlowDescriptorConverter executionFlowDescriptorConverter = getExecutionFlowDescriptorConverter(
+ moduleName, version);
+ if (executionFlowDescriptorConverter == null)
+ throw new SlcException("No flow converter found.");
+ executionFlowDescriptorConverter.addFlowsToDescriptor(md,
+ listFlows(moduleName, version));
+ return md;
+ }
+
+ public synchronized List<ExecutionModuleDescriptor> listExecutionModules() {
+ List<ExecutionModuleDescriptor> descriptors = new ArrayList<ExecutionModuleDescriptor>();
+
+ for (Iterator<OsgiBundle> iterator = executionContexts.keySet()
+ .iterator(); iterator.hasNext();) {
+ OsgiBundle osgiBundle = iterator.next();
+ ExecutionModuleDescriptor md = new ExecutionModuleDescriptor();
+ setMetadataFromBundle(md,
+ bundlesManager.findRelatedBundle(osgiBundle));
+ descriptors.add(md);
+ }
+ return descriptors;
+ }
+
+ protected synchronized Map<String, ExecutionFlow> listFlows(
+ String moduleName, String moduleVersion) {
+
+ Map<String, ExecutionFlow> flows = new HashMap<String, ExecutionFlow>();
+ OsgiBundle key = bundlesManager.findRelatedBundle(moduleName,
+ moduleVersion);
+ if (!executionFlows.containsKey(key))
+ return flows;
+ Set<ExecutionFlow> flowsT = executionFlows.get(key);
+ for (ExecutionFlow flow : flowsT)
+ flows.put(flow.getName(), flow);
+ return flows;
+ }
+
+ protected ExecutionFlow findExecutionFlow(String moduleName,
+ String moduleVersion, String flowName) {
+ String filter = moduleVersion == null || moduleVersion.equals("0.0.0") ? "(&(Bundle-SymbolicName="
+ + moduleName
+ + ")(org.eclipse.gemini.blueprint.bean.name="
+ + flowName + "))"
+ : "(&(Bundle-SymbolicName=" + moduleName + ")(Bundle-Version="
+ + moduleVersion
+ + ")(org.eclipse.gemini.blueprint.bean.name="
+ + flowName + "))";
+ return bundlesManager.getSingleServiceStrict(ExecutionFlow.class,
+ filter, true);
+ }
+
+ protected ExecutionContext findExecutionContext(String moduleName,
+ String moduleVersion) {
+ String filter = moduleFilter(moduleName, moduleVersion);
+ return bundlesManager.getSingleServiceStrict(ExecutionContext.class,
+ filter, true);
+ }
+
+ protected ExecutionFlowDescriptorConverter findExecutionFlowDescriptorConverter(
+ String moduleName, String moduleVersion) {
+ String filter = moduleFilter(moduleName, moduleVersion);
+ return bundlesManager.getSingleService(
+ ExecutionFlowDescriptorConverter.class, filter, false);
+ }
+
+ /** Only based on symbolic name if version is null or "0.0.0" */
+ protected String moduleFilter(String moduleName, String moduleVersion) {
+ return moduleVersion == null || moduleVersion.equals("0.0.0") ? "(Bundle-SymbolicName="
+ + moduleName + ")"
+ : "(&(Bundle-SymbolicName=" + moduleName + ")(Bundle-Version="
+ + moduleVersion + "))";
+
+ }
+
+ /**
+ * Builds a minimal realized flow, based on the provided information
+ * (typically from the command line).
+ *
+ * @param module
+ * a bundle id, or a pattern contained in a bundle symbolic name
+ * @param module
+ * the execution flow name
+ * @return a minimal realized flow, to be used in an execution
+ */
+ public RealizedFlow findRealizedFlow(String module, String executionName) {
+ // First check whether we have a bundleId
+ Long bundleId = null;
+ try {
+ bundleId = Long.parseLong(module);
+ } catch (NumberFormatException e) {
+ // silent
+ }
+
+ // Look for bundle names containing pattern
+ OsgiBundle bundle = null;
+ if (bundleId != null) {
+ bundle = bundlesManager.getBundle(bundleId);
+ } else {
+ bundle = bundlesManager.findFromPattern(module);
+ }
+
+ if (bundle != null) {
+ RealizedFlow launch = new RealizedFlow();
+ launch.setModuleName(bundle.getName());
+ launch.setModuleVersion(bundle.getVersion());
+ ExecutionFlowDescriptor descriptor = new ExecutionFlowDescriptor();
+ descriptor.setName(executionName);
+ launch.setFlowDescriptor(descriptor);
+ return launch;
+ } else {
+ log.warn("Could not find any execution module matching these requirements.");
+ return null;
+ }
+ }
+
+ public void upgrade(NameVersion nameVersion) {
+ OsgiBundle osgiBundle = new OsgiBundle(nameVersion);
+ bundlesManager.upgradeSynchronous(osgiBundle);
+ }
+
+ protected synchronized ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter(
+ String moduleName, String moduleVersion) {
+ return findExecutionFlowDescriptorConverter(moduleName, moduleVersion);
+ // OsgiBundle osgiBundle = new OsgiBundle(moduleName, moduleVersion);
+ // return getExecutionFlowDescriptorConverter(osgiBundle);
+ }
+
+ protected synchronized ExecutionFlowDescriptorConverter getExecutionFlowDescriptorConverter(
+ OsgiBundle osgiBundle) {
+ if (executionFlowDescriptorConverters.containsKey(osgiBundle))
+ return executionFlowDescriptorConverters.get(osgiBundle);
+ else
+ return defaultDescriptorConverter;
+ }
+
+ public ModuleDescriptor getModuleDescriptor(String moduleName,
+ String version) {
+ return getExecutionModuleDescriptor(moduleName, version);
+ }
+
+ public List<ModuleDescriptor> listModules() {
+ Bundle[] bundles = bundlesManager.getBundleContext().getBundles();
+ List<ModuleDescriptor> lst = new ArrayList<ModuleDescriptor>();
+ for (Bundle bundle : bundles) {
+ ModuleDescriptor moduleDescriptor = new ModuleDescriptor();
+ setMetadataFromBundle(moduleDescriptor, bundle);
+ lst.add(moduleDescriptor);
+ }
+ return lst;
+ }
+
+ public void start(NameVersion nameVersion) {
+ try {
+ Bundle bundle = bundlesManager.findRelatedBundle(new OsgiBundle(
+ nameVersion));
+ if (bundle == null)
+ throw new SlcException("Could not find bundle for "
+ + nameVersion);
+
+ bundlesManager.startSynchronous(bundle);
+ if (isSpringInstrumented(bundle)) {
+ // Wait for Spring application context to be ready
+ String filter = "(Bundle-SymbolicName="
+ + bundle.getSymbolicName() + ")";
+ try {
+ bundlesManager.getServiceRefSynchronous(
+ ApplicationContext.class, filter);
+ } catch (Exception e) {
+ // stop if application context not found
+ bundle.stop();
+ throw e;
+ }
+ }
+ } catch (Exception e) {
+ throw new SlcException("Cannot start " + nameVersion, e);
+ }
+ }
+
+ /** Do it calmly in order to avoid NPE */
+ private Boolean isSpringInstrumented(Bundle bundle) {
+ Dictionary<?, ?> headers = bundle.getHeaders();
+ if (headers != null && headers.get("Spring-Context") != null)
+ return true;
+ Enumeration<?> springEntryPaths = bundle
+ .getEntryPaths("/META-INF/spring");
+ if (springEntryPaths != null && springEntryPaths.hasMoreElements())
+ return true;
+ return false;
+ }
+
+ public void stop(NameVersion nameVersion) {
+ try {
+ Bundle bundle = bundlesManager.findRelatedBundle(new OsgiBundle(
+ nameVersion));
+ bundlesManager.stopSynchronous(bundle);
+ } catch (BundleException e) {
+ throw new SlcException("Cannot stop " + nameVersion, e);
+ }
+ }
+
+ protected void setMetadataFromBundle(ModuleDescriptor md, Bundle bundle) {
+ Bundle bdl = bundle;
+ if (bdl == null) {
+ if (md.getName() == null || md.getVersion() == null)
+ throw new SlcException("Name and version not available.");
+
+ Bundle[] bundles = bundlesManager.getBundleContext().getBundles();
+ for (Bundle b : bundles) {
+ if (b.getSymbolicName().equals(md.getName())
+ && md.getVersion().equals(
+ getHeaderSafe(b, Constants.BUNDLE_VERSION))) {
+ bdl = b;
+ break;
+ }
+ }
+
+ }
+
+ if (bdl == null)
+ throw new SlcException("Cannot find bundle.");
+
+ md.setName(bdl.getSymbolicName());
+ md.setVersion(getHeaderSafe(bdl, Constants.BUNDLE_VERSION));
+ md.setTitle(getHeaderSafe(bdl, Constants.BUNDLE_NAME));
+ md.setDescription(getHeaderSafe(bdl, Constants.BUNDLE_DESCRIPTION));
+
+ // copy manifets header to meta data
+ Dictionary<?, ?> headers = bundle.getHeaders();
+ Enumeration<?> keys = headers.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ Object value = headers.get(key);
+ if (value != null)
+ md.getMetadata().put(key.toString(), value.toString());
+ }
+
+ // check if started
+ if (bundle.getState() == Bundle.ACTIVE
+ || bundle.getState() == Bundle.STARTING)
+ md.setStarted(true);
+ else
+ md.setStarted(false);
+ }
+
+ private String getHeaderSafe(Bundle bundle, Object key) {
+ Object obj = bundle.getHeaders().get(key);
+ if (obj == null)
+ return null;
+ else
+ return obj.toString();
+ }
+
+ /*
+ * REGISTRATION
+ */
+
+ /** Registers an execution context. */
+ public synchronized void register(ExecutionContext executionContext,
+ Map<String, String> properties) {
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ Bundle bundle = bundlesManager.findRelatedBundle(osgiBundle);
+ osgiBundle.setTitle(getHeaderSafe(bundle, Constants.BUNDLE_NAME));
+ osgiBundle.setDescription(getHeaderSafe(bundle,
+ Constants.BUNDLE_DESCRIPTION));
+ executionContexts.put(osgiBundle, executionContext);
+ if (log.isTraceEnabled())
+ log.trace("Registered execution context from " + osgiBundle);
+ // Notify
+ ModuleDescriptor md = osgiBundle.getModuleDescriptor();
+ md.setStarted(true);
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionModuleAdded(md);
+ }
+
+ /** Unregisters an execution context. */
+ public synchronized void unregister(ExecutionContext executionContext,
+ Map<String, String> properties) {
+ // FIXME why are properties null?
+ if (properties == null)
+ return;
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ if (executionContexts.containsKey(osgiBundle)) {
+ executionContexts.remove(osgiBundle);
+ if (log.isTraceEnabled())
+ log.trace("Removed execution context from " + osgiBundle);
+ // Notify
+ ModuleDescriptor md = osgiBundle.getModuleDescriptor();
+ md.setStarted(false);
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionModuleRemoved(md);
+ }
+ }
+
+ /** Registers an execution flow. */
+ public synchronized void register(ExecutionFlow executionFlow,
+ Map<String, String> properties) {
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ if (!executionFlows.containsKey(osgiBundle)) {
+ executionFlows.put(osgiBundle, new HashSet<ExecutionFlow>());
+ }
+ executionFlows.get(osgiBundle).add(executionFlow);
+ if (log.isTraceEnabled())
+ log.trace("Registered " + executionFlow + " from " + osgiBundle);
+
+ // notifications
+ if (registerFlowsToJmx)
+ registerMBean(osgiBundle, executionFlow);
+ ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionFlowAdded(osgiBundle.getModuleDescriptor(),
+ efdc.getExecutionFlowDescriptor(executionFlow));
+ }
+
+ /** Unregisters an execution flow. */
+ public synchronized void unregister(ExecutionFlow executionFlow,
+ Map<String, String> properties) {
+ // FIXME why are properties null?
+ if (properties == null)
+ return;
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ if (executionFlows.containsKey(osgiBundle)) {
+ Set<ExecutionFlow> flows = executionFlows.get(osgiBundle);
+ flows.remove(executionFlow);
+ if (log.isTraceEnabled())
+ log.trace("Removed " + executionFlow + " from " + osgiBundle);
+ if (flows.size() == 0) {
+ executionFlows.remove(osgiBundle);
+ if (log.isTraceEnabled())
+ log.trace("Removed flows set from " + osgiBundle);
+ }
+
+ // notifications
+ if (registerFlowsToJmx)
+ unregisterMBean(osgiBundle, executionFlow);
+ ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionFlowRemoved(osgiBundle.getModuleDescriptor(),
+ efdc.getExecutionFlowDescriptor(executionFlow));
+ }
+ }
+
+ /** Registers an execution module listener. */
+ public synchronized void register(
+ ExecutionModulesListener executionModulesListener,
+ Map<String, String> properties) {
+ // sync with current state
+ for (OsgiBundle osgiBundle : executionContexts.keySet()) {
+ executionModulesListener.executionModuleAdded(osgiBundle
+ .getModuleDescriptor());
+ }
+ for (OsgiBundle osgiBundle : executionFlows.keySet()) {
+ ExecutionFlowDescriptorConverter efdc = getExecutionFlowDescriptorConverter(osgiBundle);
+ for (ExecutionFlow executionFlow : executionFlows.get(osgiBundle))
+ executionModulesListener.executionFlowAdded(
+ osgiBundle.getModuleDescriptor(),
+ efdc.getExecutionFlowDescriptor(executionFlow));
+ }
+ executionModulesListeners.add(executionModulesListener);
+ }
+
+ /** Unregisters an execution module listener. */
+ public synchronized void unregister(
+ ExecutionModulesListener executionModulesListener,
+ Map<String, String> properties) {
+ executionModulesListeners.remove(executionModulesListener);
+ }
+
+ /*
+ * INTERFACE IMPLEMENTATIONS
+ */
+
+ public void bundleChanged(BundleEvent evt) {
+ Bundle bundle = evt.getBundle();
+ if (bundle.getHeaders().get(
+ ExecutionModuleDescriptor.SLC_EXECUTION_MODULE) != null) {
+ OsgiBundle osgiBundle = new OsgiBundle(bundle);
+ if (evt.getType() == BundleEvent.INSTALLED)
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionModuleAdded(osgiBundle
+ .getModuleDescriptor());
+ else if (evt.getType() == BundleEvent.UNINSTALLED)
+ for (ExecutionModulesListener listener : executionModulesListeners)
+ listener.executionModuleRemoved(osgiBundle
+ .getModuleDescriptor());
+ }
+
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ public synchronized void bind(Object service, Map properties)
+ throws Exception {
+ if (service instanceof ExecutionFlowDescriptorConverter) {
+ ExecutionFlowDescriptorConverter executionFlowDescriptorConverter = (ExecutionFlowDescriptorConverter) service;
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ executionFlowDescriptorConverters.put(osgiBundle,
+ executionFlowDescriptorConverter);
+ if (log.isTraceEnabled())
+ log.debug("Registered execution flow descriptor converter from "
+ + osgiBundle);
+ } else {
+ // ignore
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public synchronized void unbind(Object service, Map properties)
+ throws Exception {
+ if (service instanceof ExecutionFlowDescriptorConverter) {
+ OsgiBundle osgiBundle = asOsgiBundle(properties);
+ if (executionFlowDescriptorConverters.containsKey(osgiBundle)) {
+ executionFlowDescriptorConverters.remove(osgiBundle);
+ if (log.isTraceEnabled())
+ log.debug("Removed execution flow descriptor converter from "
+ + osgiBundle);
+ }
+ } else {
+ // ignore
+ }
+ }
+
+ /*
+ * JMX
+ */
+ protected MBeanServer getMBeanServer() {
+ return ManagementFactory.getPlatformMBeanServer();
+ }
+
+ public void registerMBean(Module module, ExecutionFlow executionFlow) {
+ try {
+ StandardMBean mbean = new StandardMBean(executionFlow,
+ ExecutionFlow.class);
+ getMBeanServer().registerMBean(mbean,
+ flowMBeanName(module, executionFlow));
+ } catch (Exception e) {
+ String msg = "Cannot register execution flow " + executionFlow
+ + " as mbean";
+ throw new SlcException(msg, e);
+ }
+ }
+
+ public void unregisterMBean(Module module, ExecutionFlow executionFlow) {
+ try {
+ getMBeanServer().unregisterMBean(
+ flowMBeanName(module, executionFlow));
+ } catch (Exception e) {
+ String msg = "Cannot unregister execution flow " + executionFlow
+ + " as mbean";
+ throw new SlcException(msg, e);
+ }
+ }
+
+ protected ObjectName flowMBeanName(Module module,
+ ExecutionFlow executionFlow) {
+ String executionModulesPrefix = "SLCExecutionModules";
+ // String path = executionFlow.getPath();
+ String name = executionFlow.getName();
+ // if (path == null && name.indexOf('/') >= 0) {
+ // path = name.substring(0, name.lastIndexOf('/'));
+ // name = name.substring(name.lastIndexOf('/'));
+ // }
+
+ StringBuffer buf = new StringBuffer(executionModulesPrefix + ":"
+ + "module=" + module.getName() + " [" + module.getVersion()
+ + "],");
+
+ // if (path != null && !path.equals("")) {
+ // int depth = 0;
+ // for (String token : path.split("/")) {
+ // if (!token.equals("")) {
+ // buf.append("path").append(depth).append('=');
+ // // in order to have directories first
+ // buf.append('/');
+ // buf.append(token).append(',');
+ // depth++;
+ // }
+ // }
+ // }
+ buf.append("name=").append(name);
+ try {
+ return new ObjectName(buf.toString());
+ } catch (Exception e) {
+ throw new SlcException("Cannot generate object name based on "
+ + buf, e);
+ }
+ }
+
+ /*
+ * UTILITIES
+ */
+ @SuppressWarnings("rawtypes")
+ private OsgiBundle asOsgiBundle(Map properties) {
+ String bundleSymbolicName = checkAndGet(Constants.BUNDLE_SYMBOLICNAME,
+ properties);
+ String bundleVersion = checkAndGet(Constants.BUNDLE_VERSION, properties);
+ return new OsgiBundle(bundleSymbolicName, bundleVersion);
+ }
+
+ @SuppressWarnings("rawtypes")
+ private String checkAndGet(Object key, Map properties) {
+ if (!properties.containsKey(key) || properties.get(key) == null)
+ throw new SlcException(key + " not set in " + properties);
+ else
+ return properties.get(key).toString();
+ }
+
+ public void setBundlesManager(BundlesManager bundlesManager) {
+ this.bundlesManager = bundlesManager;
+ }
+
+ public void setDefaultDescriptorConverter(
+ ExecutionFlowDescriptorConverter defaultDescriptorConverter) {
+ this.defaultDescriptorConverter = defaultDescriptorConverter;
+ }
+
+ public void setRegisterFlowsToJmx(Boolean registerFlowsToJmx) {
+ this.registerFlowsToJmx = registerFlowsToJmx;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.FileExecutionResources;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.eclipse.gemini.blueprint.io.OsgiBundleResource;
+import org.osgi.framework.BundleContext;
+import org.springframework.core.io.Resource;
+
+/** Write access to resources in an OSGi context */
+public class OsgiExecutionResources extends FileExecutionResources implements
+ BundleContextAware {
+ private final static Log log = LogFactory
+ .getLog(OsgiExecutionResources.class);
+
+ private BundleContext bundleContext;
+
+ @Override
+ protected File fileFromResource(Resource resource) {
+ File file = super.fileFromResource(resource);
+ if (file != null)
+ return file;
+
+ if (!(resource instanceof OsgiBundleResource))
+ return null;
+
+ OsgiBundleResource osgiBundleResource = (OsgiBundleResource) resource;
+ try {
+ return osgiBundleResource.getFile();
+ } catch (IOException e) {
+ if (log.isTraceEnabled())
+ log.trace("Resource " + resource
+ + " is not available on the file system: " + e);
+ }
+
+ // TODO: ability to access resources in other bundles
+ String location = bundleContext.getBundle().getLocation();
+ String base = null;
+ if (location.startsWith("reference:file:"))
+ base = location.substring("reference:file:".length());
+ else if (location.startsWith("initial@reference:file:")) {
+ // TODO: Equinox specific?
+ String relPath = location.substring("initial@reference:file:"
+ .length());
+ // if (relPath.startsWith("../"))// relative to the framework jar
+ // relPath = relPath.substring("../".length());
+ // String framework =
+ // System.getProperty("osgi.framework").substring(
+ // "file:".length());
+ // log.debug(framework);
+ String installArea = System.getProperty("osgi.install.area")
+ .substring("file:".length());
+ // log.debug(installArea);
+ base = installArea + '/' + relPath;
+ // int sepIndex = framework.lastIndexOf(File.separatorChar);
+ // framework = framework.substring(0, sepIndex);
+ // base = framework + '/' + relPath;
+ } else {
+ return null;
+ }
+
+ String path = base + '/' + osgiBundleResource.getPathWithinContext();
+ try {
+ file = new File(path).getCanonicalFile();
+ } catch (IOException e) {
+ throw new SlcException("Cannot determine canonical path for "
+ + path, e);
+ }
+
+ if (!file.exists())
+ throw new SlcException(file
+ + " was retrieved in bundle located at '" + location
+ + "' for resource " + resource + " but it does not exist");
+
+ if (log.isTraceEnabled())
+ log.debug("OSGi local resource: " + file + " from " + resource);
+ return file;
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.StreamReadable;
+import org.argeo.slc.UnsupportedException;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.core.build.VersionedResourceDistribution;
+import org.argeo.slc.deploy.DeploymentData;
+import org.argeo.slc.deploy.DynamicRuntime;
+import org.argeo.slc.deploy.TargetData;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+public class OsgiRuntime implements BundleContextAware, ResourceLoaderAware,
+ DynamicRuntime<OsgiBundle> {
+ private String uuid = UUID.randomUUID().toString();
+ private BundleContext bundleContext;
+ private ResourceLoader resourceLoader;
+
+ public List<OsgiBundle> listModules() {
+ List<OsgiBundle> modules = new ArrayList<OsgiBundle>();
+ Bundle[] bundles = bundleContext.getBundles();
+ for (Bundle bundle : bundles) {
+ OsgiBundle osgiBundle = new OsgiBundle(bundle);
+ modules.add(osgiBundle);
+ String location = bundle.getLocation();
+ if (location != null) {
+ Resource resource = resourceLoader.getResource(location);
+ osgiBundle
+ .setResourceDistribution(new VersionedResourceDistribution(
+ osgiBundle.getName(), osgiBundle.getVersion(),
+ resource));
+ }
+ }
+ return modules;
+ }
+
+ public OsgiBundle installModule(Distribution distribution) {
+ if (!(distribution instanceof StreamReadable))
+ throw new UnsupportedException("distribution", distribution);
+
+ StreamReadable sr = (StreamReadable) distribution;
+ Bundle bundle;
+ try {
+ bundle = bundleContext.installBundle(sr.toString(), sr
+ .getInputStream());
+ } catch (BundleException e) {
+ throw new SlcException(
+ "Cannot install OSGi bundle " + distribution, e);
+ }
+ return new OsgiBundle(bundle);
+ }
+
+ public void updateModule(NameVersion nameVersion) {
+ Bundle bundle = findBundle(nameVersion);
+ try {
+ bundle.update();
+ } catch (BundleException e) {
+ throw new SlcException("Cannot update " + bundle, e);
+ }
+ }
+
+ public void uninstallModule(NameVersion nameVersion) {
+ Bundle bundle = findBundle(nameVersion);
+ try {
+ bundle.uninstall();
+ } catch (BundleException e) {
+ throw new SlcException("Cannot uninstall " + bundle, e);
+ }
+ }
+
+ public void startModule(NameVersion nameVersion) {
+ Bundle bundle = findBundle(nameVersion);
+ try {
+ bundle.start();
+ // TODO: use bundle manager
+ } catch (BundleException e) {
+ throw new SlcException("Cannot uninstall " + bundle, e);
+ }
+ }
+
+ protected Bundle findBundle(NameVersion nameVersion) {
+ Bundle[] bundles = bundleContext.getBundles();
+ for (Bundle bundle : bundles) {
+ OsgiBundle osgiBundle = new OsgiBundle(bundle);
+ if (osgiBundle.equals(nameVersion)) {
+ return bundle;
+ }
+ }
+ throw new SlcException("Could not find bundle " + nameVersion);
+ }
+
+ public void shutdown() {
+ // FIXME use framework
+ throw new UnsupportedException();
+ }
+
+ public String getDeployedSystemId() {
+ return uuid;
+ }
+
+ public DeploymentData getDeploymentData() {
+ throw new UnsupportedException();
+ }
+
+ public Distribution getDistribution() {
+ throw new UnsupportedException();
+ }
+
+ public TargetData getTargetData() {
+ throw new UnsupportedException();
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.DefaultNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.UnsupportedException;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.build.ModularDistribution;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.springframework.beans.factory.InitializingBean;
+
+public abstract class AbstractOsgiModularDistribution implements
+ ModularDistribution, BundleContextAware, InitializingBean {
+ private final static Log log = LogFactory
+ .getLog(AbstractOsgiModularDistribution.class);
+
+ private BundleContext bundleContext;
+ private EclipseUpdateSite eclipseUpdateSite;
+
+ /** Initialized by the object itself. */
+ private SortedMap<NameVersion, Distribution> distributions = new TreeMap<NameVersion, Distribution>();
+
+ protected abstract void fillDistributions(
+ SortedMap<NameVersion, Distribution> distributions)
+ throws Exception;
+
+ public Distribution getModuleDistribution(String moduleName,
+ String moduleVersion) {
+ return distributions.get(new DefaultNameVersion(moduleName,
+ moduleVersion));
+ }
+
+ public String getDistributionId() {
+ return bundleContext.getBundle().getSymbolicName()
+ + "-"
+ + bundleContext.getBundle().getHeaders()
+ .get(Constants.BUNDLE_VERSION);
+ }
+
+ public Set<NameVersion> listModulesNameVersions() {
+ return distributions.keySet();
+ }
+
+ public Iterator<NameVersion> nameVersions() {
+ return distributions.keySet().iterator();
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ fillDistributions(distributions);
+ if (log.isDebugEnabled())
+ log.debug("Distribution " + getName() + ":" + getVersion()
+ + " loaded (" + distributions.size() + " modules)");
+ }
+
+ protected String findVersion(String name) {
+ Set<String> versions = new HashSet<String>();
+ for (NameVersion key : distributions.keySet()) {
+ if (key.getName().equals(name))
+ versions.add(key.getVersion());
+ }
+
+ if (versions.size() == 0)
+ throw new SlcException("Cannot find version for name " + name);
+ else if (versions.size() > 1)
+ throw new SlcException("Found more than one version for name "
+ + name + ": " + versions);
+ else
+ return versions.iterator().next();
+
+ }
+
+ public Object getModulesDescriptor(String descriptorType) {
+ if (descriptorType.equals("eclipse"))
+ return writeEclipseUpdateSite();
+ else
+ throw new UnsupportedException("descriptorType", descriptorType);
+ }
+
+ protected Set<NameVersion> writePlainUrlList() {
+ return distributions.keySet();
+ }
+
+ protected String writeEclipseUpdateSite() {
+ if (eclipseUpdateSite == null)
+ throw new SlcException("No eclipse update site declared.");
+
+ StringBuffer buf = new StringBuffer("");
+ buf.append("<site>");
+
+ List<EclipseUpdateSiteCategory> usedCategories = new ArrayList<EclipseUpdateSiteCategory>();
+ for (EclipseUpdateSiteFeature feature : eclipseUpdateSite.getFeatures()) {
+
+ String featureId = feature.getName();
+ String featureVersion = findVersion(featureId);
+ buf.append("<feature");
+ buf.append(" url=\"features/").append(featureId).append('_')
+ .append(featureVersion).append(".jar\"");
+ buf.append(" id=\"").append(featureId).append("\"");
+ buf.append(" version=\"").append(featureVersion).append("\"");
+ buf.append(">\n");
+
+ for (EclipseUpdateSiteCategory category : feature.getCategories()) {
+ usedCategories.add(category);
+ buf.append(" <category name=\"").append(category.getName())
+ .append("\"/>\n");
+ }
+ buf.append("</feature>\n\n");
+ }
+
+ for (EclipseUpdateSiteCategory category : usedCategories) {
+ buf.append("<category-def");
+ buf.append(" name=\"").append(category.getName()).append("\"");
+ buf.append(" label=\"").append(category.getLabel()).append("\"");
+ buf.append(">\n");
+ buf.append(" <description>").append(category.getDescription())
+ .append("</description>\n");
+ buf.append("</category-def>\n\n");
+ }
+
+ buf.append("</site>");
+ return buf.toString();
+ }
+
+ public String getName() {
+ return bundleContext.getBundle().getSymbolicName();
+ }
+
+ public String getVersion() {
+ return bundleContext.getBundle().getHeaders()
+ .get(Constants.BUNDLE_VERSION).toString();
+ }
+
+ @Override
+ public String toString() {
+ return new DefaultNameVersion(this).toString();
+ }
+
+ public void setEclipseUpdateSite(EclipseUpdateSite eclipseUpdateSite) {
+ this.eclipseUpdateSite = eclipseUpdateSite;
+ }
+
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.SortedMap;
+import java.util.StringTokenizer;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.DefaultNameVersion;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.core.build.VersionedResourceDistribution;
+import org.osgi.framework.Constants;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.ResourceLoader;
+
+public class BundleModularDistribution extends AbstractOsgiModularDistribution
+ implements ResourceLoaderAware {
+ private ResourceLoader resourceLoader;
+
+ private String libDirectory = "/lib";
+
+ protected void fillDistributions(
+ SortedMap<NameVersion, Distribution> distributions)
+ throws Exception {
+ Enumeration<URL> urls = (Enumeration<URL>) getBundleContext()
+ .getBundle().findEntries(libDirectory, "*.jar", false);
+ while (urls.hasMoreElements()) {
+ URL url = urls.nextElement();
+ JarInputStream in = null;
+ try {
+ in = new JarInputStream(url.openStream());
+ Manifest mf = in.getManifest();
+ String name = mf.getMainAttributes().getValue(
+ Constants.BUNDLE_SYMBOLICNAME);
+ // Skip additional specs such as
+ // ; singleton:=true
+ if (name.indexOf(';') > -1) {
+ name = new StringTokenizer(name, " ;").nextToken();
+ }
+
+ String version = mf.getMainAttributes().getValue(
+ Constants.BUNDLE_VERSION);
+ DefaultNameVersion nameVersion = new DefaultNameVersion(name,
+ version);
+ distributions.put(nameVersion,
+ new VersionedResourceDistribution(name, version,
+ resourceLoader.getResource(url.toString())));
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+ }
+
+ public void setLibDirectory(String libDirectory) {
+ this.libDirectory = libDirectory;
+ }
+
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+ /*
+ * @SuppressWarnings(value = { "unchecked" }) protected URL
+ * findModule(String moduleName, String version) { Enumeration<URL> urls =
+ * (Enumeration<URL>) bundleContext.getBundle() .findEntries(libDirectory,
+ * moduleName + "*", false);
+ *
+ * if (!urls.hasMoreElements()) throw new SlcException("Cannot find module "
+ * + moduleName);
+ *
+ * URL url = urls.nextElement();
+ *
+ * // TODO: check version as well if (urls.hasMoreElements()) throw new
+ * SlcException("More than one module with name " + moduleName); return url;
+ * }
+ */
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EclipseUpdateSite {
+ private List<EclipseUpdateSiteFeature> features = new ArrayList<EclipseUpdateSiteFeature>();
+
+ public List<EclipseUpdateSiteFeature> getFeatures() {
+ return features;
+ }
+
+ public void setFeatures(List<EclipseUpdateSiteFeature> features) {
+ this.features = features;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+public class EclipseUpdateSiteCategory {
+ private String name;
+ private String label;
+ private String description;
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EclipseUpdateSiteFeature {
+ private String name;
+ private List<EclipseUpdateSiteCategory> categories = new ArrayList<EclipseUpdateSiteCategory>();
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<EclipseUpdateSiteCategory> getCategories() {
+ return categories;
+ }
+
+ public void setCategories(List<EclipseUpdateSiteCategory> categories) {
+ this.categories = categories;
+ }
+
+}
--- /dev/null
+/*
+ * 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.osgi.build;
+
+import java.net.URL;
+import java.util.SortedMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.core.build.VersionedResourceDistribution;
+import org.argeo.slc.osgi.OsgiBundle;
+import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
+import org.osgi.framework.Bundle;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+public class OsgiRuntimeModularDistribution extends
+ AbstractOsgiModularDistribution implements ResourceLoaderAware {
+ private final static Log log = LogFactory
+ .getLog(OsgiRuntimeModularDistribution.class);
+
+ private ResourceLoader resourceLoader;
+
+ protected void fillDistributions(
+ SortedMap<NameVersion, Distribution> distributions)
+ throws Exception {
+
+ String frameworkUrl = System.getProperty("osgi.framework");
+ String frameworkBaseUrl = null;
+ if (frameworkUrl != null)
+ frameworkBaseUrl = frameworkUrl.substring(0, frameworkUrl
+ .lastIndexOf('/'));
+ bundles: for (Bundle bundle : getBundleContext().getBundles()) {
+ OsgiBundle osgiBundle = new OsgiBundle(bundle);
+
+ String originalLocation = bundle.getLocation();
+
+ if (OsgiBundleUtils.isSystemBundle(bundle)) {
+ continue bundles;
+ }
+
+ String location = originalLocation;
+ if (originalLocation.startsWith("reference:file:"))
+ location = originalLocation.substring("reference:".length());
+
+ if (frameworkBaseUrl != null
+ && originalLocation.startsWith("initial@reference:file:")) {
+ location = frameworkBaseUrl
+ + '/'
+ + originalLocation.substring("initial@reference:file:"
+ .length());
+ }
+
+ try {
+ URL url = new URL(location);
+ Resource res = resourceLoader.getResource(url.toString());
+ distributions.put(osgiBundle,
+ new VersionedResourceDistribution(osgiBundle, res));
+
+ if (log.isTraceEnabled())
+ log.debug("Added url " + url + " from original location "
+ + originalLocation);
+ } catch (Exception e) {
+ log.warn("Cannot interpret location " + location
+ + " of bundle " + bundle + ": " + e);
+ }
+ }
+ }
+
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+}
--- /dev/null
+/*
+ * 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.osgi.deploy;
+
+import org.argeo.slc.core.deploy.DefaultResourceSet;
+import org.eclipse.gemini.blueprint.context.BundleContextAware;
+import org.eclipse.gemini.blueprint.io.OsgiBundleResourceLoader;
+import org.eclipse.gemini.blueprint.io.OsgiBundleResourcePatternResolver;
+import org.eclipse.gemini.blueprint.util.OsgiBundleUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * Retrieves ressources from an OSGi bundle either the active one or another one
+ * referenced by its symbolic name.
+ */
+public class OsgiResourceSet extends DefaultResourceSet implements
+ BundleContextAware {
+ private BundleContext bundleContext;
+ private Bundle bundle = null;
+ private String bundleSymbolicName = null;
+
+ private OsgiBundleResourceLoader osgiBundleResourceLoader = null;
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ osgiBundleResourceLoader = new OsgiBundleResourceLoader(getBundle());
+ if (getResourcePatternResolver() == null)
+ setResourcePatternResolver(new OsgiBundleResourcePatternResolver(
+ osgiBundleResourceLoader));
+ super.afterPropertiesSet();
+ }
+
+ public Bundle getBundle() {
+ if (bundle != null)
+ return bundle;
+ else if (bundleSymbolicName != null)// do not cache
+ return OsgiBundleUtils.findBundleBySymbolicName(bundleContext,
+ bundleSymbolicName);
+ else
+ // containing bundle
+ return bundleContext.getBundle();
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public ResourceLoader getResourceLoaderToUse() {
+ return osgiBundleResourceLoader;
+ }
+
+ public void setBundle(Bundle bundle) {
+ this.bundle = bundle;
+ }
+
+ public void setBundleSymbolicName(String bundleSymbolicName) {
+ this.bundleSymbolicName = bundleSymbolicName;
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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. -->
+<!-- Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org> 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. -->
+
+<beans xmlns:osgi="http://www.springframework.org/schema/osgi"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+ <osgi:service interface="org.argeo.slc.execution.ExecutionContext"
+ ref="executionContext" />
+ <osgi:service
+ interface="org.argeo.slc.execution.ExecutionFlowDescriptorConverter"
+ ref="executionFlowDescriptorConverter" />
+
+ <osgi:reference id="callbackHandler"
+ interface="javax.security.auth.callback.CallbackHandler" cardinality="0..1" />
+
+ <bean class="org.argeo.slc.osgi.MultipleServiceExporterPostProcessor">
+ <property name="interfaces">
+ <list>
+ <value><![CDATA[org.argeo.slc.execution.ExecutionFlow]]></value>
+ </list>
+ </property>
+ <property name="bundleContext" ref="bundleContext" />
+ </bean>
+
+ <bean id="osgiExecutionResources" class="org.argeo.slc.osgi.OsgiExecutionResources">
+ <property name="executionContext" ref="executionContext" />
+ </bean>
+</beans>
\ No newline at end of file
--- /dev/null
+/*
+ * 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.spring;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.node.NodeConstants;
+import org.argeo.slc.SlcException;
+
+/** Provides base method for executing code with system authorization. */
+abstract class AbstractSystemExecution {
+ private final static Log log = LogFactory.getLog(AbstractSystemExecution.class);
+ private final Subject subject = new Subject();
+
+ /** Authenticate the calling thread */
+ protected void authenticateAsSystem() {
+ ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
+ lc.login();
+ } catch (LoginException e) {
+ throw new SlcException("Cannot login as system", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(origClassLoader);
+ }
+ if (log.isTraceEnabled())
+ log.trace("System authenticated");
+ }
+
+ protected void deauthenticateAsSystem() {
+ ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject);
+ lc.logout();
+ } catch (LoginException e) {
+ throw new SlcException("Cannot logout as system", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(origClassLoader);
+ }
+ }
+
+ protected Subject getSubject() {
+ return subject;
+ }
+}
--- /dev/null
+/*
+ * 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.spring;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+import org.eclipse.gemini.blueprint.context.DependencyInitializationAwareBeanPostProcessor;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.support.AbstractBeanFactory;
+import org.springframework.beans.factory.support.SecurityContextProvider;
+import org.springframework.beans.factory.support.SimpleSecurityContextProvider;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Executes with a system authentication the instantiation and initialization
+ * methods of the application context where it has been defined.
+ */
+public class AuthenticatedApplicationContextInitialization extends
+ AbstractSystemExecution implements
+ DependencyInitializationAwareBeanPostProcessor, ApplicationContextAware {
+ /** If non empty, restricts to these beans */
+ private List<String> beanNames = new ArrayList<String>();
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (beanNames.size() == 0 || beanNames.contains(beanName))
+ authenticateAsSystem();
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (beanNames.size() == 0 || beanNames.contains(beanName))
+ deauthenticateAsSystem();
+ return bean;
+ }
+
+ public void setBeanNames(List<String> beanNames) {
+ this.beanNames = beanNames;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ if (applicationContext.getAutowireCapableBeanFactory() instanceof AbstractBeanFactory) {
+ final AbstractBeanFactory beanFactory = ((AbstractBeanFactory) applicationContext
+ .getAutowireCapableBeanFactory());
+ // retrieve subject's access control context
+ // and set it as the bean factory security context
+ Subject.doAs(getSubject(), new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ SecurityContextProvider scp = new SimpleSecurityContextProvider(
+ AccessController.getContext());
+ beanFactory.setSecurityContextProvider(scp);
+ return null;
+ }
+ });
+ }
+ }
+}
<version.argeo-commons-legacy>2.1.86-SNAPSHOT</version.argeo-commons-legacy>
</properties>
<modules>
- <!-- Runtime -->
<module>org.argeo.slc.api</module>
- <module>org.argeo.slc.core</module>
+
+ <!-- Runtime -->
+ <module>org.argeo.slc.spring</module>
<module>org.argeo.slc.unit</module>
<module>org.argeo.slc.support</module>
<module>org.argeo.slc.repo</module>