]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Introduce executor and event notifications
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 19 Feb 2009 15:14:02 +0000 (15:14 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 19 Feb 2009 15:14:02 +0000 (15:14 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@2156 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/execution/tasks/Echo.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/EfLauncher.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionContext.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFinishedEvent.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFlow.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionParameterPostProcessor.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionRegister.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionScope.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionTargetSource.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/Executor.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/InstantiationPostProcessor.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/NewExecutionEvent.java [new file with mode: 0644]
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionFlow.java
sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionSpec.java
sandbox/argeo.slc.executionflow/src/slc/conf/basic.xml
sandbox/argeo.slc.executionflow/src/slc/conf/main.xml
sandbox/argeo.slc.executionflow/src/slc/conf/slc.properties
sandbox/argeo.slc.executionflow/src/slc/conf/testCases/basic-001.xml

diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/execution/tasks/Echo.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/execution/tasks/Echo.java
new file mode 100644 (file)
index 0000000..e904153
--- /dev/null
@@ -0,0 +1,29 @@
+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;
+       }
+
+}
index f46b0fe45d8d63c3a5cfc1f35c52c6690d3e63de..ccdaf115777dcc9d379b1c9cff29f700a67e48a9 100644 (file)
@@ -11,6 +11,7 @@ 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;
@@ -18,43 +19,17 @@ 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 {
-       private static Log log;
+public class EfLauncher implements ApplicationListener {
+       private final Log log;
 
-       public static void main(String[] args) {
-               init();
-
-               String script = "src/slc/conf/main.xml";
-               //describe(script);
-
-               FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
-                               script);
-               // context.start();
-               log.info("Context initialized");
+       private boolean running = false;
 
-               ExecutionFlow main = (ExecutionFlow)context.getBean("main");
-               main.execute();
-               /*
-               Map<String, ExecutionFlow> eFlows = context
-                               .getBeansOfType(ExecutionFlow.class);
-               for (String name : eFlows.keySet()) {
-                       log.info("##\n## Execute ExecutionFlow " + name);
-                       ExecutionFlow eFlow = eFlows.get(name);
-                       eFlow.execute();
-                       
-               }*/
-       }
-       
-       private static void describe(String script){
-               SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
-               XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
-               reader.loadBeanDefinitions("file:" + script);
-               new ConsoleContextDescriber().describeContext(registry);
-       }
-
-       private static void init() {
+       public EfLauncher() {
                Properties userProperties = new Properties();
                FileInputStream in = null;
                try {
@@ -77,7 +52,80 @@ public class EfLauncher {
 
                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);
+
+               // ExecutionFlow main = (ExecutionFlow)context.getBean("main");
+               // main.execute();
+               /*
+                * Map<String, ExecutionFlow> eFlows = context
+                * .getBeansOfType(ExecutionFlow.class); for (String name :
+                * eFlows.keySet()) { log.info("##\n## Execute ExecutionFlow " + name);
+                * ExecutionFlow eFlow = eFlows.get(name); eFlow.execute();
+                * 
+                * }
+                */
+       }
+
+       private static void describe(String script) {
+               SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
+               XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
+               reader.loadBeanDefinitions(script);
+               new ConsoleContextDescriber().describeContext(registry);
+       }
 }
index ed411520c8c9cc21abc83099e15c1a0d2bd5c28c..751619e6a782f74afe8f56a15767055b4204dfc8 100644 (file)
 package org.argeo.slc.executionflow;
 
+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<ExecutionFlow> stack = new Stack<ExecutionFlow>();
+       private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
 
-       public static ExecutionFlow getCurrentFlow() {
+       // 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().stack.peek();
+               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 ExecutionFlow getCurrentFlow() {
+       // if (executionContext.get() == null)
+       // return null;
+       // return executionContext.get().stack.peek();
+       // }
+
        public static void enterFlow(ExecutionFlow executionFlow) {
-               if (executionContext.get() == null) {
-                       // TODO: deal with parallell flows
-                       executionContext.set(new ExecutionContext());
-               }
-               Stack<ExecutionFlow> stack = executionContext.get().stack;
-               stack.push(executionFlow);
-               if (log.isDebugEnabled())
-                       log.debug("Depth: " + stack.size() + ". Enter " + executionFlow);
+               Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
+               stack.push(new ExecutionFlowRuntime(executionFlow));
+               if (log.isTraceEnabled())
+                       log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
+                                       + getCurrentStackUuid() + ", depth=" + stack.size());
+       }
+
+       private static String depthSpaces(int depth) {
+               StringBuffer buf = new StringBuffer(depth * 2);
+               for (int i = 0; i < depth - 1; i++)
+                       buf.append("  ");
+               return buf.toString();
        }
 
        public static void leaveFlow(ExecutionFlow executionFlow) {
-               Stack<ExecutionFlow> stack = executionContext.get().stack;
-               if (log.isDebugEnabled())
-                       log.debug("Depth: " + stack.size() + ". Leave " + executionFlow);
-               ExecutionFlow leftEf = stack.pop();
+               Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
+               if (log.isTraceEnabled())
+                       log.debug(depthSpaces(stack.size()) + "<= " + executionFlow + " #"
+                                       + getCurrentStackUuid() + ", depth=" + stack.size());
+               ExecutionFlowRuntime leftEf = stack.pop();
                leftEf.getScopedObjects().clear();
-               if (!leftEf.getUuid().equals(executionFlow.getUuid())) {
+
+               if (!leftEf.getExecutionFlow().getUuid()
+                               .equals(executionFlow.getUuid())) {
                        throw new SlcException("Asked to leave " + executionFlow
                                        + " but last is " + leftEf);
                }
        }
+
+       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;
+       }
+
+       private 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 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;
+               }
+
+       }
 }
diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFinishedEvent.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFinishedEvent.java
new file mode 100644 (file)
index 0000000..3a133f6
--- /dev/null
@@ -0,0 +1,19 @@
+package org.argeo.slc.executionflow;
+
+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;
+       }
+
+}
index 0d4ae934e51b05d5496ee45163b14ba752edb778..5f8c9d7177f087972726d8a9765551c46d2c27de 100644 (file)
@@ -8,5 +8,4 @@ public interface ExecutionFlow extends Executable{
        public Map<String, Object> getAttributes();
        public ExecutionSpec getExecutionSpec();
        public String getUuid();
-       public Map<String, Object> getScopedObjects();
 }
index adeddaafb9231198ea541024b6ebf4a6a6b0c788..bc41feac8bd6dd9ed8adca3a3d41b6abaf235a31 100644 (file)
@@ -28,10 +28,11 @@ public class ExecutionParameterPostProcessor extends
        public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                        PropertyDescriptor[] pds, Object bean, String beanName)
                        throws BeansException {
-               ExecutionFlow currentFlow = ExecutionContext.getCurrentFlow();
-               if (currentFlow == null)
+               if (!ExecutionContext.isExecuting())
                        return pvs;
 
+               ExecutionFlow currentFlow = ExecutionContext.getCurrentFlow();
+
                Properties props = new Properties();
                Map<String, Object> attributes = currentFlow.getAttributes();
                Map<String, ExecutionSpecAttribute> specAttributes = currentFlow
@@ -45,8 +46,8 @@ public class ExecutionParameterPostProcessor extends
                                                        + " is not set in " + currentFlow);
 
                                props.setProperty(key, attributes.get(key).toString());
-//                             if (log.isTraceEnabled())
-//                                     log.trace("Use attribute " + key);
+                               // if (log.isTraceEnabled())
+                               // log.trace("Use attribute " + key);
                        }
                }
                CustomPpc ppc = new CustomPpc(props);
@@ -59,14 +60,14 @@ public class ExecutionParameterPostProcessor extends
                                tsv.setValue(convertedValue);
                                if (log.isTraceEnabled()) {
                                        if (!originalValue.equals(convertedValue))
-                                               log.trace("Converted " + beanName + "[" + pv.getName()
-                                                               + "]: " + originalValue + " to "
-                                                               + 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());
+                               // if (log.isTraceEnabled())
+                               // log.trace(beanName + "[" + pv.getName() + "]: "
+                               // + pv.getValue().getClass());
                        }
                }
 
@@ -97,7 +98,8 @@ public class ExecutionParameterPostProcessor extends
                }
 
                public String process(String strVal) {
-                       String value = parseStringValue(strVal, this.props, new HashSet<String>());
+                       String value = parseStringValue(strVal, this.props,
+                                       new HashSet<String>());
                        return (value.equals(nullValue) ? null : value);
                }
        }
diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionRegister.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionRegister.java
new file mode 100644 (file)
index 0000000..9766f1d
--- /dev/null
@@ -0,0 +1,47 @@
+package org.argeo.slc.executionflow;
+
+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"));
+                       }
+               }
+
+       }
+}
index e608744358e63c8a4a5ec17091774bc73cb357b4..ba081471198c96634da8d7ccc7517833b8f0890a 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.slc.executionflow;
 
 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;
 
@@ -11,33 +12,27 @@ public class ExecutionScope implements Scope {
        public Object get(String name, ObjectFactory objectFactory) {
 
                if (log.isTraceEnabled())
-                       log.info("Getting scoped bean " + name);
-               ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow();
-               // returns cached instance
-               if (executionFlow.getScopedObjects().containsKey(name)) {
-                       Object obj = executionFlow.getScopedObjects().get(name);
-                       if (log.isTraceEnabled())
-                               log.info("Return cached scoped object " + obj);
-                       return obj;
-               }
-               // creates instance
-               Object obj = objectFactory.getObject();
-               if (obj instanceof ExecutionFlow) {
-                       // add to itself (it is not yet the current flow)
-                       ((ExecutionFlow) obj).getScopedObjects().put(name, obj);
-                       if (log.isTraceEnabled())
-                               log.info("Cached flow object " + obj + " in itself");
-               } else {
-                       executionFlow.getScopedObjects().put(name, obj);
-                       if (log.isTraceEnabled())
-                               log.info("Created regular scoped object " + obj);
-               }
-               return obj;
+                       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() {
-               ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow();
-               return executionFlow.getUuid();
+               return ExecutionContext.getCurrentStackUuid();
        }
 
        public void registerDestructionCallback(String name, Runnable callback) {
index 3b0153787f6dd116b91534ebf4c300e6f876f487..b2e0f971b03b9605ee2dae485d155af13bd1e7bf 100644 (file)
@@ -1,21 +1,35 @@
 package org.argeo.slc.executionflow;
 
+import java.util.Map;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
 import org.springframework.aop.TargetSource;
 
 public class ExecutionTargetSource implements TargetSource {
        private final static Log log = LogFactory
                        .getLog(ExecutionTargetSource.class);
 
-       private String name;
-       private Class targetClass;
+       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);
-               ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow();
-               Object obj = executionFlow.getAttributes().get(name);
+               Map<String, Object> attributes = executionFlow.getAttributes();
+               if (!attributes.containsKey(name))
+                       throw new SlcException("Key " + name + " is not registered in "
+                                       + executionFlow);
+               Object obj = attributes.get(name);
                if (log.isTraceEnabled())
                        log.trace("Target object " + obj);
                return obj;
@@ -34,12 +48,4 @@ public class ExecutionTargetSource implements TargetSource {
 
        }
 
-       public void setName(String name) {
-               this.name = name;
-       }
-
-       public void setTargetClass(Class targetClass) {
-               this.targetClass = targetClass;
-       }
-
 }
diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/Executor.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/Executor.java
new file mode 100644 (file)
index 0000000..408e808
--- /dev/null
@@ -0,0 +1,68 @@
+package org.argeo.slc.executionflow;
+
+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();
+                       } finally {
+                               applicationContext.publishEvent(new ExecutionFinishedEvent(
+                                               this, executionContext));
+                       }
+
+               }
+       }
+
+}
diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/InstantiationPostProcessor.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/InstantiationPostProcessor.java
new file mode 100644 (file)
index 0000000..fde2304
--- /dev/null
@@ -0,0 +1,29 @@
+package org.argeo.slc.executionflow;
+
+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;
+       }
+}
diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/NewExecutionEvent.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/NewExecutionEvent.java
new file mode 100644 (file)
index 0000000..cf2c62b
--- /dev/null
@@ -0,0 +1,20 @@
+package org.argeo.slc.executionflow;
+
+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;
+       }
+
+}
index 747fa1652fd1623909be0a61cfc86fc30cf9c442..cb27e68401327d34e1342a0cf3408b9d9f9a4d53 100644 (file)
@@ -16,25 +16,16 @@ import org.springframework.validation.MapBindingResult;
 
 public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean,
                BeanNameAware {
-       // private static ThreadLocal<ExecutionFlow> executionFlow = new
-       // ThreadLocal<ExecutionFlow>();
-
        private ExecutionSpec executionSpec = new SimpleExecutionSpec();
        private String name = null;
        private Map<String, Object> attributes = new HashMap<String, Object>();
-       private Map<String, Object> scopedObjects = new HashMap<String, Object>();
        private List<Executable> executables = new ArrayList<Executable>();
 
        private final String uuid = UUID.randomUUID().toString();
 
        public void execute() {
-               try {
-                       // ExecutionContext.enterFlow(this);
-                       for (Executable executable : executables) {
-                               executable.execute();
-                       }
-               } finally {
-                       // ExecutionContext.leaveFlow(this);
+               for (Executable executable : executables) {
+                       executable.execute();
                }
        }
 
@@ -59,10 +50,11 @@ public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean,
                                if (executionSpecAttr instanceof RefSpecAttribute) {
                                        RefSpecAttribute rsa = (RefSpecAttribute) executionSpecAttr;
                                        Class targetClass = rsa.getTargetClass();
-                                       if (!targetClass.isAssignableFrom(obj.getClass()))
-                                               errors.rejectValue(key,
-                                                               "Not compatible with target class "
-                                                                               + targetClass);
+                                       if (!targetClass.isAssignableFrom(obj.getClass())) {
+                                               errors.reject(key
+                                                               + " not compatible with target class "
+                                                               + targetClass);
+                                       }
                                }
                        }
                }
@@ -96,16 +88,12 @@ public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean,
                return uuid;
        }
 
-       public Map<String, Object> getScopedObjects() {
-               return scopedObjects;
-       }
-
        public ExecutionSpec getExecutionSpec() {
                return executionSpec;
        }
 
        public String toString() {
-               return new StringBuffer("Flow ").append(name).append(" [#")
-                               .append(uuid).append(']').toString();
+               return new StringBuffer("Flow ").append(name).toString();// .append(" [#")
+               // .append(uuid).append(']').toString();
        }
 }
index c21ce22e9b14305ca36cf893c2a801dbe0c4c2e8..ce14efd592fb40e218b836bf67dbd92ab2020e2f 100644 (file)
@@ -3,11 +3,17 @@ package org.argeo.slc.executionflow;
 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>();
 
-public class SimpleExecutionSpec implements ExecutionSpec {
        private Map<String, ExecutionSpecAttribute> attributes = new HashMap<String, ExecutionSpecAttribute>();
 
+       private String name = null;
+
        public Map<String, ExecutionSpecAttribute> getAttributes() {
                return attributes;
        }
@@ -17,17 +23,42 @@ public class SimpleExecutionSpec implements ExecutionSpec {
        }
 
        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();
-               targetSource.setName(name);
-               targetSource.setTargetClass(targetClass);
+               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);
+       }
 }
index 19e9735afab48e39c1389177d5f1e80d9cb2acac..2684b06d5585fe9dfc9ffb5b0600d6350d2b8e71 100644 (file)
@@ -33,6 +33,7 @@
                <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>\r
                                <bean parent="testRun">\r
                                        <property name="testDefinition" ref="testDef" />\r
-                                       <property name="testData">\r
-                                               <bean parent="basic.ref">\r
-                                                       <constructor-arg value="testData2" />\r
-                                               </bean>\r
-                                       </property>\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
index e2c8dbea0634fe158ba9de8472c9801ee695a809..8c599f0c77d5fe40a090deda0fbab71c9ac326dd 100644 (file)
@@ -1,18 +1,31 @@
 <?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
+       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.executionflow.SimpleExecutionFlow">\r
+               <property name="executionSpec">\r
+                       <bean class="org.argeo.slc.executionflow.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
                </property>\r
        </bean>\r
 \r
+       <bean id="echo1" parent="echoTemplate" scope="execution">\r
+               <property name="message" value="From main! @{testKey}" />\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.executionflow.ExecutionRegister" />\r
+\r
+\r
        <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">\r
                <property name="scopes">\r
                        <map>\r
@@ -33,6 +59,8 @@
        <bean\r
                class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />\r
        <bean class="org.argeo.slc.executionflow.ExecutionParameterPostProcessor" />\r
+       <bean class="org.argeo.slc.executionflow.InstantiationPostProcessor" />\r
+       <bean class="org.argeo.slc.executionflow.Executor" />\r
 \r
        <bean class="org.argeo.slc.executionflow.ExecutionAspect"></bean>\r
        <aop:aspectj-autoproxy />\r
index 23475a1cd8ceb61d2e45cea821f26e24f188ae73..020db5c633cee2de269ea6b1d20f435a320f0d7c 100644 (file)
@@ -3,6 +3,7 @@ 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=DEBUG
 
 ## Appenders
 # console is set to be a ConsoleAppender.
index c35361bdb409cca43a602e8954b1f0e560767945..6a30f65a899ea9562c9734a1fd278734c5108f87 100644 (file)
@@ -9,15 +9,15 @@
 \r
        <import resource="../basic.xml" />\r
 \r
-       <bean id="basic.001" parent="basic.executionFlowTemplate" scope="execution">\r
-               <aop:scoped-proxy />\r
+       <bean id="basic.001" parent="basic.executionFlowTemplate">\r
                <property name="attributes">\r
                        <map>\r
                                <entry key="testData1" value-ref="basic.001.testData" />\r
                                <entry key="testData2">\r
-                                       <bean class="org.argeo.slc.core.test.BasicTestData">\r
-                                               <property name="expected" value="tata" />\r
-                                               <property name="reached" value="tata" />\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