--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>argeo.slc.executionflow</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.1.v200811281800]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[true]]></enableImports>
+ <configs>
+ <config>src/slc/conf/main.xml</config>
+ <config>src/slc/conf/testCases/basic-001.xml</config>
+ <config>src/slc/conf/testCases/basic-002.xml</config>
+ <config>src/slc/conf/basic.xml</config>
+ <config>src/slc/conf/common.xml</config>
+ <config>src/slc/conf/test.xml</config>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
--- /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>0.11.3-SNAPSHOT</version>
+ <relativePath>../../org.argeo.slc</relativePath>
+ </parent>
+ <groupId>org.argeo.slc.sandbox</groupId>
+ <artifactId>org.argeo.slc.sandbox.executionflow</artifactId>
+ <name>SLC Sandbox Execution Flow</name>
+ <packaging>jar</packaging>
+ <properties></properties>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+
+
+ <dependency>
+ <groupId>org.argeo.slc.runtime</groupId>
+ <artifactId>org.argeo.slc.support.simple</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>com.springsource.org.aspectj.runtime</artifactId>
+ <version>1.6.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.aspectj</groupId>
+ <artifactId>com.springsource.org.aspectj.weaver</artifactId>
+ <version>1.6.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>com.springsource.org.codehaus.groovy</artifactId>
+ <version>1.5.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.beanshell</groupId>
+ <artifactId>com.springsource.bsh</artifactId>
+ <version>2.0.0.b4</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sourceforge.cglib</groupId>
+ <artifactId>com.springsource.net.sf.cglib</artifactId>
+ <version>2.1.3</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+package org.argeo.slc.execution;
+
+public abstract class AbstractSpecAttribute implements ExecutionSpecAttribute {
+ private Boolean isParameter = true;
+
+ public Boolean getIsParameter() {
+ return isParameter;
+ }
+
+ public void setIsParameter(Boolean isParameter) {
+ this.isParameter = isParameter;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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 {
+ private final static Log log = LogFactory
+ .getLog(ConsoleContextDescriber.class);
+
+ 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
+package org.argeo.slc.execution;
+
+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
+package org.argeo.slc.execution;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.logging.Log4jUtils;
+import org.argeo.slc.process.SlcExecution;
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionParser;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+public class EfLauncher implements ApplicationListener {
+ private final Log log;
+
+ private boolean running = false;
+
+ public EfLauncher() {
+ Properties userProperties = new Properties();
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream("src/slc/conf/slc.properties");
+ userProperties.load(in);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+
+ // Set as System properties
+ for (Object obj : userProperties.keySet()) {
+ String key = obj.toString();
+ System.setProperty(key, userProperties.getProperty(key));
+ }
+
+ // Logging
+ System.setProperty("log4j.defaultInitOverride", "true");
+
+ Log4jUtils.initLog4j(null);
+ log = LogFactory.getLog(EfLauncher.class);
+ }
+
+ public void launch(String script) {
+ // describe(script);
+
+ GenericApplicationContext context = new GenericApplicationContext();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
+ reader.loadBeanDefinitions(script);
+ // FileSystemXmlApplicationContext context = new
+ // FileSystemXmlApplicationContext(
+ // script);
+ context.addApplicationListener(this);
+ context.refresh();
+ context.start();
+ log.debug("Context initialized");
+
+ SlcExecution slcExecution = new SlcExecution();
+ slcExecution.getAttributes().put("slc.flows", "main");
+
+ running = true;
+ context.publishEvent(new NewExecutionEvent(this, slcExecution));
+
+ synchronized (this) {
+ while (running)
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ }
+
+ public synchronized boolean isRunning() {
+ return running;
+ }
+
+ public synchronized void setRunning(boolean running) {
+ this.running = running;
+ }
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ExecutionFinishedEvent) {
+ ExecutionContext executionContext = ((ExecutionFinishedEvent) event)
+ .getExecutionContext();
+ log.debug("Execution " + executionContext.getUuid()
+ + " finished, stopping launcher...");
+ synchronized (this) {
+ running = false;
+ notifyAll();
+ }
+ }
+
+ }
+
+ public static void main(String[] args) {
+ String script = "file:src/slc/conf/main.xml";
+ new EfLauncher().launch(script);
+ }
+
+ private static void describe(String script) {
+ SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
+ reader.loadBeanDefinitions(script);
+ new ConsoleContextDescriber().describeContext(registry);
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+
+@Aspect
+public class ExecutionAspect {
+ private static Log log = LogFactory.getLog(ExecutionAspect.class);
+
+ @Before("flowExecution()")
+ public void beforeFlow(JoinPoint jp) throws Throwable {
+ //log.debug("this " + jp.getThis().getClass());
+ //log.debug("target " + jp.getTarget().getClass());
+ // Thread.dumpStack();
+ ExecutionFlow executionFlow = (ExecutionFlow) jp.getTarget();
+ ExecutionContext.enterFlow(executionFlow);
+ }
+
+ @After("flowExecution()")
+ public void afterFlow(JoinPoint jp) throws Throwable {
+ //log.debug("this " + jp.getThis().getClass());
+ //log.debug("target " + jp.getTarget().getClass());
+ ExecutionFlow executionFlow = (ExecutionFlow) jp.getTarget();
+ ExecutionContext.leaveFlow(executionFlow);
+ }
+
+ @Pointcut("execution(void org.argeo.slc.execution.ExecutionFlow.execute())")
+ public void flowExecution() {
+ }
+}
--- /dev/null
+package org.argeo.slc.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.process.SlcExecution;
+import org.springframework.beans.factory.ObjectFactory;
+
+public class ExecutionContext {
+ private final static Log log = LogFactory.getLog(ExecutionContext.class);
+
+ private final static ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
+
+ private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
+
+ // TODO: make it thread safe?
+ private final Map<String, Object> variables = new HashMap<String, Object>();
+
+ private final String uuid = UUID.randomUUID().toString();
+
+ public static Map<String, Object> getVariables() {
+ if (executionContext.get() == null)
+ return null;
+ return executionContext.get().variables;
+ }
+
+ public static ExecutionContext getCurrent() {
+ return executionContext.get();
+ }
+
+ public static String getExecutionUuid() {
+ if (executionContext.get() == null)
+ return null;
+ return executionContext.get().getUuid();
+ }
+
+ public static void registerExecutionContext(ExecutionContext context) {
+ if (executionContext.get() != null)
+ throw new SlcException("Context #" + executionContext.get().uuid
+ + " already registered.");
+ executionContext.set(context);
+ }
+
+ public static void enterFlow(ExecutionFlow executionFlow) {
+ Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
+
+ ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
+ stack.push(runtime);
+
+ if (log.isTraceEnabled())
+ log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
+ + getCurrentStackUuid() + ", depth=" + stack.size());
+
+ Map<String, ExecutionSpecAttribute> specAttrs = executionFlow
+ .getExecutionSpec().getAttributes();
+ for (String key : specAttrs.keySet()) {
+ ExecutionSpecAttribute esa = specAttrs.get(key);
+ if (esa.getIsParameter()) {
+ runtime.getLocalVariables().put(key,
+ executionFlow.getParameter(key));
+ if (log.isTraceEnabled())
+ log.trace(depthSpaces(stack.size()) + "Add '" + key
+ + "' as local variable.");
+ }
+ }
+
+ }
+
+ public static Object getVariable(String key) {
+ Object obj = getWithCheck().findVariable(key);
+ if (obj == null)
+ throw new SlcException("Variable '" + key + "' not found.");
+ return obj;
+ }
+
+ protected Object findVariable(String key) {
+ Object obj = null;
+ for (int i = stack.size() - 1; i >= 0; i--) {
+ if (stack.get(i).getLocalVariables().containsKey(key)) {
+ obj = stack.get(i).getLocalVariables().get(key);
+ break;
+ }
+ }
+
+ // Look into global execution variables
+ if (obj == null) {
+ if (variables.containsKey(key))
+ obj = variables.get(key);
+ }
+
+ return obj;
+ }
+
+ private static String depthSpaces(int depth) {
+ StringBuffer buf = new StringBuffer(depth * 2);
+ for (int i = 0; i < depth; i++)
+ buf.append(" ");
+ return buf.toString();
+ }
+
+ public static void leaveFlow(ExecutionFlow executionFlow) {
+ Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
+ if (log.isTraceEnabled())
+ log.debug(depthSpaces(stack.size()) + "<= " + executionFlow + " #"
+ + getCurrentStackUuid() + ", depth=" + stack.size());
+
+ ExecutionFlowRuntime leftEf = stack.pop();
+ if (!leftEf.getExecutionFlow().getUuid()
+ .equals(executionFlow.getUuid()))
+ throw new SlcException("Asked to leave " + executionFlow
+ + " but last is " + leftEf);
+
+ leftEf.getScopedObjects().clear();
+ leftEf.getLocalVariables().clear();
+
+ }
+
+ public static String getCurrentStackUuid() {
+ return getWithCheck().stack.peek().uuid;
+ }
+
+ // public static ExecutionFlow getCurrentFlow() {
+ // return getWithCheck().stack.peek().executionFlow;
+ // }
+
+ public static Boolean isExecuting() {
+ return executionContext.get() != null;
+ }
+
+ protected static ExecutionContext getWithCheck() {
+ if (executionContext.get() == null)
+ throw new SlcException("No execution context");
+ return executionContext.get();
+ }
+
+ public static Object findOrAddScopedObject(String name,
+ ObjectFactory objectFactory) {
+ ExecutionContext executionContext = getWithCheck();
+ Object obj = executionContext.findScopedObject(name);
+ if (obj == null) {
+ obj = objectFactory.getObject();
+ executionContext.stack.peek().getScopedObjects().put(name, obj);
+ }
+ return obj;
+ }
+
+ /** return null if not found */
+ protected Object findScopedObject(String key) {
+ Object obj = null;
+ for (int i = stack.size() - 1; i >= 0; i--) {
+ if (stack.get(i).getScopedObjects().containsKey(key)) {
+ obj = stack.get(i).getScopedObjects().get(key);
+ break;
+ }
+ }
+ return obj;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ private 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;
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.springframework.context.ApplicationEvent;
+
+public class ExecutionFinishedEvent extends ApplicationEvent {
+ static final long serialVersionUID = 012;
+
+ private final ExecutionContext executionContext;
+
+ public ExecutionFinishedEvent(Object source, ExecutionContext executionContext) {
+ super(source);
+ this.executionContext = executionContext;
+ }
+
+ public ExecutionContext getExecutionContext() {
+ return executionContext;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.Map;
+
+import org.argeo.slc.process.Executable;
+
+public interface ExecutionFlow extends Executable{
+ public Object getParameter(String name);
+ public ExecutionSpec getExecutionSpec();
+ public String getUuid();
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.slc.process.Executable;
+
+public class ExecutionFlowFactory {
+ private List<Executable> executables = new ArrayList<Executable>();
+
+
+ public ExecutionFlow createExecutionFlow(Map<String, Object> attributes){
+ SimpleExecutionFlow executionFlow = new SimpleExecutionFlow();
+ executionFlow.setExecutables(executables);
+ return executionFlow;
+ }
+
+
+ public void setExecutables(List<Executable> executables) {
+ this.executables = executables;
+ }
+
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+
+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.PropertyValue;
+import org.springframework.beans.PropertyValues;
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.beans.factory.config.TypedStringValue;
+
+public class ExecutionParameterPostProcessor extends
+ InstantiationAwareBeanPostProcessorAdapter {
+ private final static Log log = LogFactory
+ .getLog(ExecutionParameterPostProcessor.class);
+
+ private String placeholderPrefix = "@{";
+ private String placeholderSuffix = "}";
+ private String nullValue;
+
+ @Override
+ public PropertyValues postProcessPropertyValues(PropertyValues pvs,
+ PropertyDescriptor[] pds, Object bean, String beanName)
+ throws BeansException {
+ if (!ExecutionContext.isExecuting())
+ return pvs;
+
+// ExecutionFlow currentFlow = ExecutionContext.getCurrentFlow();
+//
+// Properties props = new Properties();
+// Map<String, Object> attributes = currentFlow.getAttributes();
+// Map<String, ExecutionSpecAttribute> specAttributes = currentFlow
+// .getExecutionSpec().getAttributes();
+//
+// for (String key : specAttributes.keySet()) {
+// ExecutionSpecAttribute obj = specAttributes.get(key);
+// if (!(obj instanceof RefSpecAttribute)) {
+// if (!attributes.containsKey(key))
+// throw new SlcException("Specified attribute " + key
+// + " is not set in " + currentFlow);
+//
+// props.setProperty(key, attributes.get(key).toString());
+// // if (log.isTraceEnabled())
+// // log.trace("Use attribute " + key);
+// }
+// }
+
+ Properties props = new Properties();
+ CustomPpc ppc = new CustomPpc(props);
+
+ for (PropertyValue pv : pvs.getPropertyValues()) {
+ if (pv.getValue() instanceof TypedStringValue) {
+ TypedStringValue tsv = (TypedStringValue) pv.getValue();
+ String originalValue = tsv.getValue();
+ String convertedValue = ppc.process(originalValue);
+ tsv.setValue(convertedValue);
+ if (log.isTraceEnabled()) {
+ if (!originalValue.equals(convertedValue))
+ log.trace("Converted field '" + pv.getName() + "': '"
+ + originalValue + "' to '" + convertedValue
+ + "' in bean " + beanName);
+ }
+ } else {
+ // if (log.isTraceEnabled())
+ // log.trace(beanName + "[" + pv.getName() + "]: "
+ // + pv.getValue().getClass());
+ }
+ }
+
+ return pvs;
+ }
+
+ public void setPlaceholderPrefix(String placeholderPrefix) {
+ this.placeholderPrefix = placeholderPrefix;
+ }
+
+ public void setPlaceholderSuffix(String placeholderSuffix) {
+ this.placeholderSuffix = placeholderSuffix;
+ }
+
+ public void setNullValue(String nullValue) {
+ this.nullValue = nullValue;
+ }
+
+ private class CustomPpc extends PropertyPlaceholderConfigurer {
+ private final Properties props;
+
+ public CustomPpc(Properties props) {
+ super();
+ this.props = props;
+ setPlaceholderPrefix(placeholderPrefix);
+ setPlaceholderSuffix(placeholderSuffix);
+ setSystemPropertiesMode(SYSTEM_PROPERTIES_MODE_NEVER);
+ }
+
+ public String process(String strVal) {
+ String value = parseStringValue(strVal, this.props,
+ new HashSet<String>());
+ return (value.equals(nullValue) ? null : value);
+ }
+
+ @Override
+ protected String resolvePlaceholder(String placeholder, Properties props) {
+ if (ExecutionContext.isExecuting())
+ return ExecutionContext.getVariable(placeholder).toString();
+ else if (SimpleExecutionSpec.isInFlowInitialization())
+ return SimpleExecutionSpec.getInitializingFlowParameter(
+ placeholder).toString();
+ else
+ return super.resolvePlaceholder(placeholder, props);
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class ExecutionRegister implements InitializingBean {
+ private final static Log log = LogFactory.getLog(ExecutionRegister.class);
+
+ @Autowired
+ private Set<ExecutionFlow> executionFlows;
+
+ @Autowired
+ private Set<ExecutionSpec> executionSpecs;
+
+ public void afterPropertiesSet() throws Exception {
+ log.debug("Register: " + executionSpecs.size() + " specs");
+ for (ExecutionSpec spec : executionSpecs) {
+ log.debug(spec);
+ Map<String, ExecutionSpecAttribute> attributes = spec
+ .getAttributes();
+ log.debug("Spec attributes: ");
+ for (String key : attributes.keySet()) {
+ log.debug(" " + key + "\t" + attributes.get(key));
+ }
+ }
+
+ log.debug("Register: " + executionFlows.size() + " flows");
+ for (ExecutionFlow flow : executionFlows) {
+ log.debug(flow);
+// Map<String, Object> attributes = flow.getAttributes();
+// log.debug("Specified parameters: ");
+// for (String key : flow.getExecutionSpec().getAttributes().keySet()) {
+// log.debug(" "
+// + key
+// + "\t"
+// + (attributes.containsKey(key) ? "SPECIFIED"
+// : "TO SPECIFY"));
+// }
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.springframework.beans.factory.ObjectFactory;
+import org.springframework.beans.factory.config.Scope;
+
+public class ExecutionScope implements Scope {
+ private final static Log log = LogFactory.getLog(ExecutionScope.class);
+
+ public Object get(String name, ObjectFactory objectFactory) {
+
+ if (log.isTraceEnabled())
+ log.trace("Getting scoped bean " + name);
+ return ExecutionContext.findOrAddScopedObject(name, objectFactory);
+
+ // if (ExecutionContext.getScopedObjects().containsKey(name)) {
+ // // returns cached instance
+ // Object obj = ExecutionContext.getScopedObjects().get(name);
+ // if (log.isTraceEnabled())
+ // log.trace("Return cached scoped object " + obj);
+ // return obj;
+ // } else {
+ // // creates instance
+ // Object obj = objectFactory.getObject();
+ // ExecutionContext.getScopedObjects().put(name, obj);
+ // if (log.isTraceEnabled())
+ // log.trace("Created regular scoped object " + obj);
+ // return obj;
+ // }
+ }
+
+ public String getConversationId() {
+ return ExecutionContext.getCurrentStackUuid();
+ }
+
+ public void registerDestructionCallback(String name, Runnable callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object remove(String name) {
+ log.debug("Remove object " + name);
+ throw new UnsupportedOperationException();
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.Map;
+
+public interface ExecutionSpec {
+ public Map<String, ExecutionSpecAttribute> getAttributes();
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+public interface ExecutionSpecAttribute {
+ public Object getValue();
+ public Boolean getIsParameter();
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.aop.TargetSource;
+
+public class ExecutionTargetSource implements TargetSource {
+ private final static Log log = LogFactory
+ .getLog(ExecutionTargetSource.class);
+
+ private final String name;
+ private final Class<?> targetClass;
+ private final ExecutionFlow executionFlow;
+
+ public ExecutionTargetSource(ExecutionFlow executionFlow,
+ Class<?> targetClass, String name) {
+ this.executionFlow = executionFlow;
+ this.targetClass = targetClass;
+ this.name = name;
+ }
+
+ public Object getTarget() throws Exception {
+ if (log.isTraceEnabled())
+ log.trace("Getting object " + name);
+ Object obj = executionFlow.getParameter(name);
+ if (log.isTraceEnabled())
+ log.trace("Target object " + obj);
+ return obj;
+ }
+
+ public Class getTargetClass() {
+ return targetClass;
+ }
+
+ public boolean isStatic() {
+ return false;
+ }
+
+ public void releaseTarget(Object target) throws Exception {
+ // TODO Auto-generated method stub
+
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.process.SlcExecution;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+
+public class Executor implements ApplicationListener, ApplicationContextAware {
+ private final static Log log = LogFactory.getLog(Executor.class);
+
+ private ApplicationContext applicationContext;
+
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof NewExecutionEvent) {
+ SlcExecution slcExecution = ((NewExecutionEvent) event)
+ .getSlcExecution();
+ ExecutionContext executionContext = new ExecutionContext();
+ ExecutionThread thread = new ExecutionThread(executionContext,
+ slcExecution);
+ thread.start();
+ }
+
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ private class ExecutionThread extends Thread {
+ private final SlcExecution slcExecution;
+ private final ExecutionContext executionContext;
+
+ public ExecutionThread(ExecutionContext executionContext,
+ SlcExecution slcExecution) {
+ super("SLC Execution #" + executionContext.getUuid());
+ this.slcExecution = slcExecution;
+ this.executionContext = executionContext;
+ }
+
+ public void run() {
+ // Initialize from SlcExecution
+ ExecutionContext.registerExecutionContext(executionContext);
+ ExecutionContext.getVariables()
+ .putAll(slcExecution.getAttributes());
+
+ try {
+ log.info("Start execution #"
+ + ExecutionContext.getExecutionUuid());
+ String executionBean = slcExecution.getAttributes().get(
+ "slc.flows");
+ ExecutionFlow main = (ExecutionFlow) applicationContext
+ .getBean(executionBean);
+ main.execute();
+ } catch (Exception e) {
+ log.error("Execution " + executionContext.getUuid()
+ + " failed.", e);
+ } finally {
+ applicationContext.publishEvent(new ExecutionFinishedEvent(
+ this, executionContext));
+ }
+
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
+
+public class InstantiationPostProcessor extends
+ InstantiationAwareBeanPostProcessorAdapter {
+ private final static Log log = LogFactory
+ .getLog(InstantiationPostProcessor.class);
+
+ @Override
+ public boolean postProcessAfterInstantiation(Object bean, String beanName)
+ throws BeansException {
+ if (bean instanceof ExecutionFlow)
+ SimpleExecutionSpec.flowInitializationStarted((ExecutionFlow) bean);
+ return true;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (bean instanceof ExecutionFlow)
+ SimpleExecutionSpec
+ .flowInitializationFinished((ExecutionFlow) bean);
+ return bean;
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import org.argeo.slc.process.SlcExecution;
+import org.springframework.context.ApplicationEvent;
+
+public class NewExecutionEvent extends ApplicationEvent {
+ static final long serialVersionUID = 012;
+
+ private final SlcExecution slcExecution;
+
+ public NewExecutionEvent(Object source, SlcExecution slcExecution) {
+ super(source);
+ this.slcExecution = slcExecution;
+ }
+
+ public SlcExecution getSlcExecution() {
+ return slcExecution;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+public class RefSpecAttribute extends AbstractSpecAttribute {
+ private Class targetClass;
+ private Object value = null;
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public Class getTargetClass() {
+ return targetClass;
+ }
+
+ public void setTargetClass(Class targetClass) {
+ this.targetClass = targetClass;
+ }
+
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.process.Executable;
+import org.argeo.slc.test.ExecutableTestRun;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.validation.MapBindingResult;
+
+public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean,
+ BeanNameAware {
+ private ExecutionSpec executionSpec = new SimpleExecutionSpec();
+ private String name = null;
+ private Map<String, Object> parameters = new HashMap<String, Object>();
+ private List<Executable> executables = new ArrayList<Executable>();
+
+ private final String uuid = UUID.randomUUID().toString();
+
+ public void execute() {
+ for (Executable executable : executables) {
+ executable.execute();
+ }
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ // Validate execution specs
+ if (executionSpec == null)
+ return;
+
+ MapBindingResult errors = new MapBindingResult(parameters, "execution#"
+ + getUuid());
+ for (String key : executionSpec.getAttributes().keySet()) {
+ ExecutionSpecAttribute executionSpecAttr = executionSpec
+ .getAttributes().get(key);
+ if (!parameters.containsKey(key)) {
+ Object defaultValue = executionSpecAttr.getValue();
+ if (defaultValue == null)
+ errors.rejectValue(key, "Not set and no default value");
+ else
+ parameters.put(key, defaultValue);
+ } else {// contains key
+ Object obj = parameters.get(key);
+ if (executionSpecAttr instanceof RefSpecAttribute) {
+ RefSpecAttribute rsa = (RefSpecAttribute) executionSpecAttr;
+ Class targetClass = rsa.getTargetClass();
+ if (!targetClass.isAssignableFrom(obj.getClass())) {
+ errors.reject(key
+ + " not compatible with target class "
+ + targetClass);
+ }
+ }
+ }
+ }
+
+ if (errors.hasErrors())
+ throw new SlcException("Could not prepare execution flow: "
+ + errors.toString());
+ }
+
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public void setExecutables(List<Executable> executables) {
+ this.executables = executables;
+ }
+
+ public void setExecutionSpec(ExecutionSpec executionSpec) {
+ this.executionSpec = executionSpec;
+ }
+
+ public void setParameters(Map<String, Object> attributes) {
+ this.parameters = attributes;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public ExecutionSpec getExecutionSpec() {
+ return executionSpec;
+ }
+
+ public Object getParameter(String name) {
+ if (parameters.containsKey(name)) {
+ return parameters.get(name);
+ } else {
+ if (executionSpec.getAttributes().containsKey(name)) {
+ ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
+ name);
+ if (esa.getValue() != null)
+ return esa.getValue();
+ } else {
+ throw new SlcException("Key " + name
+ + " is not define in the specifications of "
+ + toString());
+ }
+ }
+ throw new SlcException("Key " + name + " is not set as parameter in "
+ + toString());
+ }
+
+ public String toString() {
+ return new StringBuffer("Flow ").append(name).toString();// .append(" [#")
+ // .append(uuid).append(']').toString();
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.argeo.slc.SlcException;
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.factory.BeanNameAware;
+
+public class SimpleExecutionSpec implements ExecutionSpec, BeanNameAware {
+ private final static ThreadLocal<ExecutionFlow> initializingFlow = new ThreadLocal<ExecutionFlow>();
+
+ private Map<String, ExecutionSpecAttribute> attributes = new HashMap<String, ExecutionSpecAttribute>();
+
+ private String name = null;
+
+ public Map<String, ExecutionSpecAttribute> getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Map<String, ExecutionSpecAttribute> attributes) {
+ this.attributes = attributes;
+ }
+
+ public Object createRef(String name) {
+ ExecutionFlow flow = initializingFlow.get();
+ if (flow == null)
+ throw new SlcException("No flow is currently initializing."
+ + " Declare flow refs as inner beans or prototypes.");
+
+ RefSpecAttribute refSpecAttribute = (RefSpecAttribute) attributes
+ .get(name);
+ Class<?> targetClass = refSpecAttribute.getTargetClass();
+ ExecutionTargetSource targetSource = new ExecutionTargetSource(flow,
+ targetClass, name);
+ ProxyFactory proxyFactory = new ProxyFactory();
+ proxyFactory.setTargetClass(targetClass);
+ proxyFactory.setProxyTargetClass(true);
+ proxyFactory.setTargetSource(targetSource);
+
+ return proxyFactory.getProxy();
+ }
+
+ public void setBeanName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static void flowInitializationStarted(ExecutionFlow flow) {
+ initializingFlow.set(flow);
+ }
+
+ public static void flowInitializationFinished(ExecutionFlow flow) {
+ ExecutionFlow registeredFlow = initializingFlow.get();
+ if (registeredFlow == null)
+ throw new SlcException("No flow registered");
+ if (!flow.getUuid().equals(registeredFlow.getUuid()))
+ throw new SlcException("Current flow is " + flow);
+ initializingFlow.set(null);
+ }
+
+ public static Object getInitializingFlowParameter(String key) {
+ if (initializingFlow.get() == null)
+ throw new SlcException("No initializing flow available.");
+ return initializingFlow.get().getParameter(key);
+ }
+
+ public static Boolean isInFlowInitialization() {
+ return initializingFlow.get() != null;
+ }
+}
--- /dev/null
+package org.argeo.slc.execution;
+
+public class SimpleSpecAttribute extends AbstractSpecAttribute {
+ private Object value = null;
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+}
--- /dev/null
+package org.argeo.slc.execution.tasks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.process.Executable;
+
+public class Echo implements Executable {
+ private final static Log defaultLog = LogFactory.getLog(Echo.class);
+
+ private Log log;
+ private String message;
+
+ public void execute() {
+ log().info(message);
+ }
+
+ protected Log log() {
+ return log != null ? log : defaultLog;
+ }
+
+ public void setLog(Log log) {
+ this.log = log;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+}
--- /dev/null
+import org.argeo.slc.test.*;
+
+public class BasicExecutionFlow implements org.argeo.slc.executionflow.ExecutionFlow {
+
+ ExecutableTestRun firstSubTest = null;
+ ExecutableTestRun secondSubTest = null;
+
+ void execute(){
+ firstSubTest?.execute();
+ secondSubTest?.execute();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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="common.xml" />\r
+\r
+ <bean id="basic.executionSpec" class="org.argeo.slc.execution.SimpleExecutionSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testedComponentId">\r
+ <bean parent="specAttribute" p:value="100" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean parent="refAttribute" p:targetClass="org.argeo.slc.core.test.BasicTestData" />\r
+ </entry>\r
+ <entry key="testData2">\r
+ <bean parent="refAttribute" p:targetClass="org.argeo.slc.core.test.BasicTestData" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="basic.ref" factory-bean="basic.executionSpec"\r
+ factory-method="createRef" abstract="true" />\r
+\r
+ <bean id="basic.executionFlowTemplate" class="org.argeo.slc.execution.SimpleExecutionFlow"\r
+ abstract="true">\r
+ <property name="executionSpec" ref="basic.executionSpec" />\r
+ <property name="executables">\r
+ <list>\r
+ <ref bean="echo1" />\r
+ <bean parent="testRun">\r
+ <property name="testDefinition" ref="testDef" />\r
+ <property name="testData">\r
+ <bean parent="basic.ref">\r
+ <constructor-arg value="testData1" />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ <bean parent="testRun">\r
+ <property name="testDefinition" ref="testDef" />\r
+ <property name="testData" ref="ref1" />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="ref1" parent="basic.ref" scope="prototype">\r
+ <constructor-arg value="testData2" />\r
+ </bean>\r
+\r
+ <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition"\r
+ scope="prototype" />\r
+\r
+ <bean id="testResult" parent="slcDefault.test.basicSimpleTestResult" />\r
+\r
+ <bean id="testRun" class="org.argeo.slc.core.test.SimpleTestRun"\r
+ abstract="true">\r
+ <property name="testResult" ref="testResult" />\r
+ </bean>\r
+\r
+ <!--\r
+ <bean class="org.springframework.aop.framework.ProxyFactoryBean">\r
+ <property name="targetClass"\r
+ value="org.argeo.slc.core.test.BasicTestData" /> <property\r
+ name="targetSource"> <bean\r
+ class="org.argeo.slc.executionflow.ExecutionTargetSource"> <property\r
+ name="name" value="testData" /> <property name="targetClass"\r
+ value="org.argeo.slc.core.test.BasicTestData" /> </bean> </property>\r
+ <property name="proxyTargetClass" value="true" /> </bean>\r
+ -->\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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\r
+ resource="classpath:/org/argeo/slc/core/test/spring/applicationContext.xml" />\r
+\r
+ <bean id="specAttribute" class="org.argeo.slc.execution.SimpleSpecAttribute"\r
+ abstract="true" />\r
+\r
+ <bean id="refAttribute" class="org.argeo.slc.execution.RefSpecAttribute"\r
+ abstract="true" />\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"\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/context http://www.springframework.org/schema/context/spring-context-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="testCases/basic-001.xml" />\r
+ <import resource="testCases/basic-002.xml" />\r
+\r
+ <bean id="main" class="org.argeo.slc.execution.SimpleExecutionFlow">\r
+ <property name="executionSpec">\r
+ <bean class="org.argeo.slc.execution.SimpleExecutionSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="testKey">\r
+ <bean parent="specAttribute" p:value="660" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+ </property>\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="echo1" />\r
+ <ref bean="basic.001" />\r
+ <ref bean="basic.001" />\r
+ <ref bean="basic.002" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="echo1" parent="echoTemplate" scope="execution">\r
+ <property name="message" value="From main! @{testKey}, slc.flows=@{slc.flows}" />\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+\r
+ <bean id="echoTemplate" class="org.argeo.slc.execution.tasks.Echo"\r
+ abstract="true">\r
+ </bean>\r
+\r
+ <context:annotation-config />\r
+ <bean class="org.argeo.slc.execution.ExecutionRegister" />\r
+\r
+\r
+ <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">\r
+ <property name="scopes">\r
+ <map>\r
+ <entry key="execution">\r
+ <bean class="org.argeo.slc.execution.ExecutionScope" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean\r
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />\r
+ <bean class="org.argeo.slc.execution.ExecutionParameterPostProcessor" />\r
+ <bean class="org.argeo.slc.execution.InstantiationPostProcessor" />\r
+ <bean class="org.argeo.slc.execution.Executor" />\r
+\r
+ <bean class="org.argeo.slc.execution.ExecutionAspect"></bean>\r
+ <aop:aspectj-autoproxy />\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+log4j.rootLogger=WARN, console
+
+## Levels
+log4j.logger.org.argeo=DEBUG
+log4j.logger.org.argeo.slc.executionflow.ExecutionParameterPostProcessor=TRACE
+log4j.logger.org.argeo.slc.executionflow.ExecutionContext=TRACE
+
+## Appenders
+# console is set to be a ConsoleAppender.
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+
+# console uses PatternLayout.
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
+
+testCase=002
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:lang="http://www.springframework.org/schema/lang"\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
+ ">\r
+\r
+ <import\r
+ resource="classpath:/org/argeo/slc/core/test/spring/applicationContext.xml" />\r
+\r
+ <import resource="testCases/basic-001.xml" />\r
+ <import resource="testCases/basic-002.xml" />\r
+\r
+ <bean id="executionFlow.basic1" class="org.argeo.slc.executionflow.SimpleExecutionFlow">\r
+ <meta key="meta1" value="mata1Value" />\r
+ <qualifier>\r
+ <attribute key="qual1" value="qual1value" />\r
+ </qualifier>\r
+ <property name="executables">\r
+ <list>\r
+ <ref local="testGroovyImpl" />\r
+ <ref local="testBshImpl" />\r
+ <bean parent="testRun" p:testDefinition-ref="testDef"\r
+ p:testData-ref="testData-${testCase}" />\r
+ <bean parent="testRun" p:testDefinition-ref="testDef"\r
+ p:testData-ref="testData-${testCase}" />\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <lang:groovy id="executionFlow.groovy1" script-source="src/slc/conf/BasicExecutionFlow.groovy">\r
+ <lang:property name="firstSubTest">\r
+ <bean parent="testRun" p:testDefinition-ref="testDef"\r
+ p:testData-ref="testData-${testCase}" />\r
+ </lang:property>\r
+ </lang:groovy>\r
+\r
+ <bean id="testGroovyImpl" parent="testGroovy">\r
+ <property name="message" value="Hello World! Groovy" />\r
+ </bean>\r
+ <bean id="testBshImpl" parent="testBsh">\r
+ <property name="message" value="Hello World! Beanshell" />\r
+ </bean>\r
+\r
+ <bean id="testDef" class="org.argeo.slc.core.test.BasicTestDefinition"\r
+ scope="prototype" />\r
+\r
+ <bean\r
+ class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />\r
+\r
+ <bean id="testResult" parent="slcDefault.test.basicSimpleTestResult">\r
+ </bean>\r
+\r
+ <bean id="testRun" class="org.argeo.slc.core.test.SimpleTestRun"\r
+ abstract="true">\r
+ <property name="testResult" ref="testResult" />\r
+ </bean>\r
+\r
+ <lang:groovy id="testGroovyBean">\r
+ <lang:inline-script><![CDATA[\r
+ class Message {\r
+ String message = 'test'\r
+ \r
+ public String getMessage(){\r
+ return message;\r
+ }\r
+ }\r
+ ]]></lang:inline-script>\r
+ </lang:groovy>\r
+\r
+ <lang:groovy id="testGroovy">\r
+ <lang:inline-script><![CDATA[\r
+ class GroovyMessenger extends org.argeo.slc.core.test.SimpleTestRun {\r
+ \r
+ String message = 'test'\r
+ \r
+ void execute(){\r
+ println(message);\r
+ }\r
+ }\r
+ ]]></lang:inline-script>\r
+ </lang:groovy>\r
+\r
+ <lang:bsh id="testBsh" script-interfaces="org.argeo.slc.test.ExecutableTestRun">\r
+ <lang:inline-script><![CDATA[\r
+ setStrictJava(true);\r
+\r
+ class BshMessenger extends org.argeo.slc.core.test.SimpleTestRun {\r
+\r
+ String message = "test";\r
+\r
+ public void execute(){\r
+ System.out.println(message);\r
+ }\r
+ \r
+ public void setMessage(String message){\r
+ this.message = message;\r
+ }\r
+ }\r
+ ]]></lang:inline-script>\r
+ </lang:bsh>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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="../basic.xml" />\r
+\r
+ <bean id="basic.001" parent="basic.executionFlowTemplate">\r
+ <property name="parameters">\r
+ <map>\r
+ <entry key="testData1" value-ref="basic.001.testData" />\r
+ <entry key="testData2">\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@{testKey}" />\r
+ </bean>\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="basic.001.testData" class="org.argeo.slc.core.test.BasicTestData"\r
+ scope="execution">\r
+ <aop:scoped-proxy />\r
+ <property name="expected" value="tata100" />\r
+ <property name="reached" value="tata@{testedComponentId}" />\r
+ </bean>\r
+\r
+ <bean id="basic.001.testData2" class="org.argeo.slc.core.test.context.DefaultContextTestData">\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+\r
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+ <import resource="../basic.xml" />\r
+\r
+ <bean id="basic.002" parent="basic.executionFlowTemplate">\r
+ <property name="parameters">\r
+ <map>\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
+ </property>\r
+ </bean>\r
+</beans>
\ No newline at end of file