]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
ExecutionContext transformed to interface; mapping from ExecutionContexts to Threads...
authorOlivier Capillon <olivier.capillon@gmail.com>
Thu, 12 Mar 2009 20:10:25 +0000 (20:10 +0000)
committerOlivier Capillon <olivier.capillon@gmail.com>
Thu, 12 Mar 2009 20:10:25 +0000 (20:10 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@2258 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
demo/site/org.argeo.slc.demo.basic/conf/main.xml
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java [new file with mode: 0644]
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionModule.java
runtime/org.argeo.slc.support.equinox/src/main/java/org/argeo/slc/execution/old/EfLauncher.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/AbstractSpringExecutionModule.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/DefaultModulesManager.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionAspect.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionContext.java [deleted file]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionFinishedEvent.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionParameterPostProcessor.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/Executor.java
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/SimpleSpringExecutionModule.java [new file with mode: 0644]
runtime/org.argeo.slc.support.simple/src/main/resources/org/argeo/slc/core/execution/spring.xml
runtime/org.argeo.slc.support.simple/src/test/java/org/argeo/slc/core/execution/DefaultModulesMangerTest.java
runtime/org.argeo.slc.support.simple/src/test/java/org/argeo/slc/core/execution/ExecutionFlowTest.java
runtime/org.argeo.slc.support.simple/src/test/resources/org/argeo/slc/core/execution/applicationContext.xml

index 046b36990a267161c64cc139bcba52c12e35e831..2f2ff243287567ccb33e9c8baced16b89bbbfe05 100644 (file)
@@ -7,8 +7,12 @@
        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
-       <bean id="executionModule" class="org.argeo.slc.osgi.OsgiExecutionModule" />\r
-\r
+       <bean id="executionModule" class="org.argeo.slc.osgi.OsgiExecutionModule" >\r
+               <property name="executionContext">\r
+                       <ref bean="executionContext" />\r
+               </property>     \r
+       </bean>\r
+               \r
        <bean id="main" parent="slcTemplate.simpleFlow">\r
                <property name="executionSpec">\r
                        <bean parent="slcTemplate.simpleSpec">\r
diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java
new file mode 100644 (file)
index 0000000..b5d467f
--- /dev/null
@@ -0,0 +1,25 @@
+package org.argeo.slc.execution;\r
+\r
+import java.util.Map;\r
+\r
+public interface ExecutionContext {\r
+       \r
+       /**\r
+        * @param name\r
+        * @return null if no object is found\r
+        */\r
+       public Object findScopedObject(String name);\r
+       \r
+       public void addScopedObject(String name, Object obj);\r
+       \r
+       public String getUuid();\r
+       \r
+       public void enterFlow(ExecutionFlow executionFlow);\r
+       \r
+       public void leaveFlow(ExecutionFlow executionFlow);\r
+       \r
+       public Object getVariable(String key);\r
+       \r
+       //TODO: replace with setVariable(String Key, Object value)\r
+       public void addVariables(Map<? extends String, ? extends Object> variablesToAdd);\r
+}\r
index fd197efc4ee2de9861f4896ce7b6729c389307db..4c51e2d55af453e3a1406adf65a106a8a5c00622 100644 (file)
@@ -6,6 +6,8 @@ public interface ExecutionModule {
        public String getName();
 
        public String getVersion();
+       
+       public ExecutionContext getExecutionContext();
 
        public ExecutionModuleDescriptor getDescriptor();
 
index b3937b78dc4bc73bd94808b945b06fa7d3f87f5a..3e93a7e1b7ac5db4e36160a204fb650e636b1301 100644 (file)
@@ -1,31 +1,21 @@
 package org.argeo.slc.execution.old;
 
 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.core.execution.ConsoleContextDescriber;
-import org.argeo.slc.core.execution.ExecutionContext;
 import org.argeo.slc.core.execution.ExecutionFinishedEvent;
 import org.argeo.slc.core.execution.NewExecutionEvent;
+import org.argeo.slc.execution.ExecutionContext;
 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 {
index 0d9770a453beff40feac0b2a668d635e42549c50..d51f63acb975eeb7e98201fdaab6be7e2027e757 100644 (file)
@@ -5,6 +5,7 @@ import java.util.Map;
 import java.util.TreeMap;
 
 import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionContext;
 import org.argeo.slc.execution.ExecutionFlow;
 import org.argeo.slc.execution.ExecutionFlowDescriptor;
 import org.argeo.slc.execution.ExecutionModule;
@@ -21,8 +22,19 @@ import org.springframework.util.Assert;
 
 public abstract class AbstractSpringExecutionModule implements ExecutionModule,
                ApplicationContextAware {
+       
        private ApplicationContext applicationContext;
 
+       private ExecutionContext executionContext;
+       
+       public ExecutionContext getExecutionContext() {
+               return executionContext;
+       }
+
+       public void setExecutionContext(ExecutionContext executionContext) {
+               this.executionContext = executionContext;
+       }
+
        public ExecutionModuleDescriptor getDescriptor() {
                ExecutionModuleDescriptor md = new ExecutionModuleDescriptor();
                md.setName(getName());
index 7da391a3796316697be997cedd10c944136e3b51..9bb6aae6442b6247e1a9daf9a9bb67825145e67a 100644 (file)
@@ -8,6 +8,7 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionContext;
 import org.argeo.slc.execution.ExecutionFlow;
 import org.argeo.slc.execution.ExecutionFlowDescriptor;
 import org.argeo.slc.execution.ExecutionModule;
@@ -51,6 +52,29 @@ public class DefaultModulesManager implements ExecutionModulesManager {
                this.executionModules = executionModules;
        }
 
+       protected Map<String, Object> convertValues(ExecutionFlowDescriptor executionFlowDescriptor) {
+               // convert the values of flow.getFlowDescriptor()
+               Map<String, Object> values = executionFlowDescriptor.getValues();
+               
+               Map<String, Object> convertedValues = new HashMap<String, Object>();
+               
+               for(String key : values.keySet()) {
+                       Object value = values.get(key);
+                       if(value instanceof PrimitiveValue) {
+                               PrimitiveValue primitiveValue = (PrimitiveValue) value;
+
+                               // TODO: check that the class of the the primitiveValue.value matches
+                               // the primitiveValue.type
+                               convertedValues.put(key, primitiveValue.getValue());
+                       }
+                       else if(value instanceof RefValue) {
+                               RefValue refValue = (RefValue) value;
+                               convertedValues.put(key, refValue.getLabel());
+                       }
+               }               
+               return convertedValues;
+       }
+       
        public void process(SlcExecution slcExecution) {
                log.info("##\n## Process SLC Execution " + slcExecution+"\n##");
 
@@ -58,31 +82,7 @@ public class DefaultModulesManager implements ExecutionModulesManager {
                        ExecutionModule module = getExecutionModule(flow.getModuleName(),
                                        flow.getModuleVersion());
                        if(module != null) {
-                               ExecutionContext executionContext = new ExecutionContext();
-                               
-                               // convert the values of flow.getFlowDescriptor()
-                               Map<String, Object> values = flow.getFlowDescriptor().getValues();
-                               
-                               Map<String, Object> convertedValues = new HashMap<String, Object>();
-                               
-                               for(String key : values.keySet()) {
-                                       Object value = values.get(key);
-                                       if(value instanceof PrimitiveValue) {
-                                               PrimitiveValue primitiveValue = (PrimitiveValue) value;
-
-                                               // TODO: check that the class of the the primitiveValue.value matches
-                                               // the primitiveValue.type
-                                               convertedValues.put(key, primitiveValue.getValue());
-                                       }
-                                       else if(value instanceof RefValue) {
-                                               RefValue refValue = (RefValue) value;
-                                               convertedValues.put(key, refValue.getLabel());
-                                       }
-                               }
-                               
-                               executionContext.addVariables(convertedValues);
-                               ExecutionThread thread = new ExecutionThread(executionContext, flow.getFlowDescriptor(),
-                                               module);
+                               ExecutionThread thread = new ExecutionThread(flow.getFlowDescriptor(), module);
                                thread.start();
                        }
                        else {
@@ -94,20 +94,18 @@ public class DefaultModulesManager implements ExecutionModulesManager {
 
        private class ExecutionThread extends Thread {
                private final ExecutionFlowDescriptor executionFlowDescriptor;
-               private final ExecutionContext executionContext;
                private final ExecutionModule executionModule;
 
-               public ExecutionThread(ExecutionContext executionContext,
-                               ExecutionFlowDescriptor executionFlowDescriptor,
+               public ExecutionThread(ExecutionFlowDescriptor executionFlowDescriptor,
                                ExecutionModule executionModule) {
-                       super("SLC Execution #" + executionContext.getUuid());
+                       super("SLC Execution #" /*+ executionContext.getUuid()*/);
                        this.executionFlowDescriptor = executionFlowDescriptor;
-                       this.executionContext = executionContext;
                        this.executionModule = executionModule;
                }
 
                public void run() {
-                       ExecutionContext.registerExecutionContext(executionContext);                            
+                       ExecutionContext executionContext = executionModule.getExecutionContext();
+                       executionContext.addVariables(convertValues(executionFlowDescriptor));
                        try {
                                executionModule.execute(executionFlowDescriptor);
                        } catch (Exception e) {
@@ -116,6 +114,5 @@ public class DefaultModulesManager implements ExecutionModulesManager {
                                                + " failed.", e);
                        }
                }
-       }       
-       
+       }               
 }
index aae2e80c60568e07626d59cedd4324d351141e18..a352c89ba834956425722e8659ac203a5f39e371 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.slc.core.execution;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.execution.ExecutionContext;
 import org.argeo.slc.execution.ExecutionFlow;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.ProceedingJoinPoint;
@@ -15,13 +16,23 @@ import org.aspectj.lang.annotation.Pointcut;
 public class ExecutionAspect {
        private static Log log = LogFactory.getLog(ExecutionAspect.class);
 
+       private ExecutionContext executionContext;
+       
+       public ExecutionContext getExecutionContext() {
+               return executionContext;
+       }
+
+       public void setExecutionContext(ExecutionContext executionContext) {
+               this.executionContext = executionContext;
+       }
+
        @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);
+               executionContext.enterFlow(executionFlow);
        }
 
        @After("flowExecution()")
@@ -29,10 +40,12 @@ public class ExecutionAspect {
                //log.debug("this " + jp.getThis().getClass());
                //log.debug("target " + jp.getTarget().getClass());
                ExecutionFlow executionFlow = (ExecutionFlow) jp.getTarget();
-               ExecutionContext.leaveFlow(executionFlow);
+               executionContext.leaveFlow(executionFlow);
        }
 
        @Pointcut("execution(void org.argeo.slc.execution.ExecutionFlow.execute())")
        public void flowExecution() {
        }
+       
+       
 }
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionContext.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionContext.java
deleted file mode 100644 (file)
index 61eb672..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-package org.argeo.slc.core.execution;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Stack;
-import java.util.UUID;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.execution.ExecutionFlow;
-import org.argeo.slc.execution.ExecutionSpecAttribute;
-import org.argeo.slc.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 void addVariables(Map<? extends String, ? extends Object> variablesToAdd) {
-               variables.putAll(variablesToAdd);
-       }
-
-       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);
-       }
-       
-       /**
-        * Unregisters the ExecutionContext for the current Thread
-        * @throws a SlcException if no ExecutionContext was registered for the Thread
-        * @return the unregistered ExecutionContext
-        */
-       public static ExecutionContext unregisterExecutionContext() {
-               ExecutionContext current = executionContext.get();
-               if(current == null) {
-                       throw new SlcException("No Context registered.");
-               }
-               executionContext.remove();
-               return current;
-       }
-
-       public static void enterFlow(ExecutionFlow executionFlow) {
-               Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
-
-               ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
-               stack.push(runtime);
-
-               if (log.isDebugEnabled())
-                       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 (executionFlow.isSetAsParameter(key)) {
-                               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;
-               
-               // Look if the variable is set in the global execution variables
-               // (i.e. the variable was overridden)
-               if (variables.containsKey(key))
-                       obj = variables.get(key);               
-               
-               // if the variable was not found, look in the stack starting at the
-               // upper flows
-               if (obj == null) {
-                       for (int i = 0; i < stack.size(); i++) {
-                               if (stack.get(i).getLocalVariables().containsKey(key)) {
-                                       obj = stack.get(i).getLocalVariables().get(key);
-                                       break;
-                               }
-                       }
-               }
-
-               return obj;
-       }
-
-       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.isDebugEnabled())
-                       log.debug(depthSpaces(stack.size()) + "<= " + executionFlow + " #"
-                                       + getCurrentStackUuid() + ", depth=" + stack.size());
-
-               ExecutionFlowRuntime leftEf = stack.pop();
-               if (!leftEf.getExecutionFlow().getName()
-                               .equals(executionFlow.getName()))
-                       throw new SlcException("Asked to leave " + executionFlow
-                                       + " but last is " + leftEf);
-
-               leftEf.getScopedObjects().clear();
-               leftEf.getLocalVariables().clear();
-
-       }
-
-       public 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;
-               }
-
-       }
-}
index 11f9b32783d64e04fd4224428ba4561b6b677189..fac5b5c66be23cf3031c1f534988f8591fa0b62c 100644 (file)
@@ -1,5 +1,6 @@
 package org.argeo.slc.core.execution;
 
+import org.argeo.slc.execution.ExecutionContext;
 import org.springframework.context.ApplicationEvent;
 
 public class ExecutionFinishedEvent extends ApplicationEvent {
index a95670b10a3fc93ccf1f52f0bf9f381fdd49c6da..c5d484bbfafbb190362c8cd900db5991c31d663e 100644 (file)
@@ -8,6 +8,7 @@ import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionContext;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.PropertyValue;
 import org.springframework.beans.PropertyValues;
@@ -17,9 +18,26 @@ import org.springframework.beans.factory.config.TypedStringValue;
 
 public class ExecutionParameterPostProcessor extends
                InstantiationAwareBeanPostProcessorAdapter {
+       
        private final static Log log = LogFactory
                        .getLog(ExecutionParameterPostProcessor.class);
 
+       private ExecutionContext executionContext;
+       
+       private ExecutionScope executionScope;
+       
+       public void setExecutionScope(ExecutionScope executionScope) {
+               this.executionScope = executionScope;
+       }
+
+       public ExecutionContext getExecutionContext() {
+               return executionContext;
+       }
+
+       public void setExecutionContext(ExecutionContext executionContext) {
+               this.executionContext = executionContext;
+       }
+
        private String placeholderPrefix = "@{";
        private String placeholderSuffix = "}";
        private String nullValue;
@@ -28,7 +46,7 @@ public class ExecutionParameterPostProcessor extends
        public PropertyValues postProcessPropertyValues(PropertyValues pvs,
                        PropertyDescriptor[] pds, Object bean, String beanName)
                        throws BeansException {
-               if (!ExecutionContext.isExecuting()){
+               if ((executionScope == null) || (!executionScope.hasExecutionContext())){
                                //&& !DefaultExecutionSpec.isInFlowInitialization()) {
                        //log.info("Skip parameter conversion for bean " + beanName);
                        return pvs;
@@ -97,14 +115,13 @@ public class ExecutionParameterPostProcessor extends
                @Override
                protected String resolvePlaceholder(String placeholder, Properties props) {
                        //log.info("Try convert placeholder " + placeholder);
-                       if (ExecutionContext.isExecuting())
-                               return ExecutionContext.getVariable(placeholder).toString();
+                       if ((executionScope != null) && (executionScope.hasExecutionContext()))
+                               return executionContext.getVariable(placeholder).toString();
                        else if (DefaultExecutionSpec.isInFlowInitialization())
                                return DefaultExecutionSpec.getInitializingFlowParameter(
                                                placeholder).toString();
                        else
                                return super.resolvePlaceholder(placeholder, props);
                }
-
        }
 }
index adbf18aed7d1903d477f83c4d50b31b2a8200329..05a60b73bd5e9db39073fed4cbc2fd54e05e3fdd 100644 (file)
@@ -1,20 +1,62 @@
 package org.argeo.slc.core.execution;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionContext;
 import org.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);
 
+       private final ThreadLocal<ExecutionContext> executionContext 
+                       = new ThreadLocal<ExecutionContext>();
+       
+       public final ThreadLocal<String> executionContextBeanName = new ThreadLocal<String>();
+       
        public Object get(String name, ObjectFactory objectFactory) {
 
                if (log.isTraceEnabled())
                        log.trace("Getting scoped bean " + name);
-               return ExecutionContext.findOrAddScopedObject(name, objectFactory);
-
+               
+               // check if an execution context is defined for this thread
+               if(executionContext.get() == null) {
+                       // if not, we expect objectFactory to produce an ExecutionContext
+                       Object obj = objectFactory.getObject();
+                       if(obj instanceof ExecutionContext) {
+                               // store the ExecutionContext in the ThreadLocal
+                               executionContext.set((ExecutionContext)obj);
+                               executionContextBeanName.set(name);
+                               return obj;
+                       }
+                       else {
+                               throw new SlcException("Expected an ExecutionContext, got an object of class "
+                                               + obj.getClass() + " for bean " + name);
+                       }                       
+               }
+               
+               if(name.equals(executionContextBeanName.get())) {
+                       return executionContext.get();
+               }
+               else {
+                       // see if the executionContext already knows the object 
+                       Object obj = executionContext.get().findScopedObject(name);
+                       if(obj == null) {
+                               obj = objectFactory.getObject();
+                               if(!(obj instanceof ExecutionContext)) {
+                                       executionContext.get().addScopedObject(name, obj);
+                               }
+                               else {
+                                       throw new SlcException("Only one ExecutionContext can be defined per Thread");
+                               }
+                       }
+                       return obj;
+               }
+               
                // if (ExecutionContext.getScopedObjects().containsKey(name)) {
                // // returns cached instance
                // Object obj = ExecutionContext.getScopedObjects().get(name);
@@ -32,8 +74,14 @@ public class ExecutionScope implements Scope {
        }
 
        public String getConversationId() {
-               return ExecutionContext.getCurrentStackUuid();
+               
+               return executionContext.get().getUuid();
+       }
+       
+       public Boolean hasExecutionContext() {
+               return executionContext.get() != null;
        }
+       
 
        public void registerDestructionCallback(String name, Runnable callback) {
                // TODO: implement it
index 92e2f5e306afb98322ad93202aeda1e2dd68ad4a..cc46fd97c5e78aa1ab37441b1c93b26484d751d9 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.slc.core.execution;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.execution.ExecutionContext;
 import org.argeo.slc.execution.ExecutionFlow;
 import org.argeo.slc.process.SlcExecution;
 import org.springframework.beans.BeansException;
@@ -19,7 +20,7 @@ public class Executor implements ApplicationListener, ApplicationContextAware {
                if (event instanceof NewExecutionEvent) {
                        SlcExecution slcExecution = ((NewExecutionEvent) event)
                                        .getSlcExecution();
-                       ExecutionContext executionContext = new ExecutionContext();
+                       MapExecutionContext executionContext = new MapExecutionContext();
                        ExecutionThread thread = new ExecutionThread(executionContext,
                                        slcExecution);
                        thread.start();
@@ -36,22 +37,22 @@ public class Executor implements ApplicationListener, ApplicationContextAware {
                private final SlcExecution slcExecution;
                private final ExecutionContext executionContext;
 
-               public ExecutionThread(ExecutionContext executionContext,
+               public ExecutionThread(MapExecutionContext executionContext,
                                SlcExecution slcExecution) {
                        super("SLC Execution #" + executionContext.getUuid());
                        this.slcExecution = slcExecution;
                        this.executionContext = executionContext;
                }
 
-               public void run() {
+               public void run() {/*
                        // Initialize from SlcExecution
-                       ExecutionContext.registerExecutionContext(executionContext);
-                       ExecutionContext.getVariables()
+                       MapExecutionContext.registerExecutionContext(executionContext);
+                       MapExecutionContext.getVariables()
                                        .putAll(slcExecution.getAttributes());
 
                        try {
                                log.info("Start execution #"
-                                               + ExecutionContext.getExecutionUuid());
+                                               + MapExecutionContext.getExecutionUuid());
                                String executionBean = slcExecution.getAttributes().get(
                                                "slc.flows");
                                ExecutionFlow main = (ExecutionFlow) applicationContext
@@ -64,7 +65,7 @@ public class Executor implements ApplicationListener, ApplicationContextAware {
                                applicationContext.publishEvent(new ExecutionFinishedEvent(
                                                this, executionContext));
                        }
-
+*/
                }
        }
 
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java
new file mode 100644 (file)
index 0000000..8c69d7c
--- /dev/null
@@ -0,0 +1,169 @@
+package org.argeo.slc.core.execution;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+import java.util.UUID;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.execution.ExecutionContext;
+import org.argeo.slc.execution.ExecutionFlow;
+import org.argeo.slc.execution.ExecutionSpecAttribute;
+import org.argeo.slc.process.SlcExecution;
+import org.springframework.beans.factory.ObjectFactory;
+
+public class MapExecutionContext implements ExecutionContext {
+       private final static Log log = LogFactory.getLog(MapExecutionContext.class);
+
+
+       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 Map<String, Object> getVariables() {
+               return variables;
+       }*/
+       
+       public void addVariables(Map<? extends String, ? extends Object> variablesToAdd) {
+               variables.putAll(variablesToAdd);
+       }
+
+       public void enterFlow(ExecutionFlow executionFlow) {
+               ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
+               stack.push(runtime);
+
+               if (log.isDebugEnabled())
+                       log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
+                                       + uuid + ", depth=" + stack.size());
+
+               Map<String, ExecutionSpecAttribute> specAttrs = executionFlow
+                               .getExecutionSpec().getAttributes();
+               for (String key : specAttrs.keySet()) {
+                       //ExecutionSpecAttribute esa = specAttrs.get(key);
+                       if (executionFlow.isSetAsParameter(key)) {
+                               runtime.getLocalVariables().put(key,
+                                               executionFlow.getParameter(key));
+                               if (log.isTraceEnabled())
+                                       log.trace(depthSpaces(stack.size()) + "Add '" + key
+                                                       + "' as local variable.");
+                       }
+               }
+
+       }
+
+       public Object getVariable(String key) {
+               Object obj = findVariable(key);
+               if (obj == null)
+                       throw new SlcException("Variable '" + key + "' not found.");
+               return obj;
+       }
+
+       protected Object findVariable(String key) {
+               Object obj = null;
+               
+               // Look if the variable is set in the global execution variables
+               // (i.e. the variable was overridden)
+               if (variables.containsKey(key))
+                       obj = variables.get(key);               
+               
+               // if the variable was not found, look in the stack starting at the
+               // upper flows
+               if (obj == null) {
+                       for (int i = 0; i < stack.size(); i++) {
+                               if (stack.get(i).getLocalVariables().containsKey(key)) {
+                                       obj = stack.get(i).getLocalVariables().get(key);
+                                       break;
+                               }
+                       }
+               }
+
+               return obj;
+       }
+
+       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 void leaveFlow(ExecutionFlow executionFlow) {
+               if (log.isDebugEnabled())
+                       log.debug(depthSpaces(stack.size()) + "<= " + executionFlow + " #"
+                                       + uuid + ", depth=" + stack.size());
+
+               ExecutionFlowRuntime leftEf = stack.pop();
+               if (!leftEf.getExecutionFlow().getName()
+                               .equals(executionFlow.getName()))
+                       throw new SlcException("Asked to leave " + executionFlow
+                                       + " but last is " + leftEf);
+
+               leftEf.getScopedObjects().clear();
+               leftEf.getLocalVariables().clear();
+
+       }
+
+/*     public Object findOrAddScopedObject(String name, ObjectFactory objectFactory) {
+               Object obj = findScopedObject(name);
+               if (obj == null) {
+                       obj = objectFactory.getObject();
+                       stack.peek().getScopedObjects().put(name, obj);
+               }
+               return obj;
+       }*/
+
+       
+       public void addScopedObject(String name, Object obj) {
+               //TODO: check that the object is not set yet ?
+               stack.peek().getScopedObjects().put(name, obj);
+       }
+       
+       /** return null if not found */
+       public Object findScopedObject(String name) {
+               Object obj = null;
+               for (int i = stack.size() - 1; i >= 0; i--) {
+                       if (stack.get(i).getScopedObjects().containsKey(name)) {
+                               obj = stack.get(i).getScopedObjects().get(name);
+                               break;
+                       }
+               }
+               return obj;
+       }
+
+       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;
+               }
+
+       }
+}
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/SimpleSpringExecutionModule.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/SimpleSpringExecutionModule.java
new file mode 100644 (file)
index 0000000..134c225
--- /dev/null
@@ -0,0 +1,24 @@
+package org.argeo.slc.core.execution;\r
+\r
+public class SimpleSpringExecutionModule extends AbstractSpringExecutionModule {\r
+\r
+       private String name;\r
+       private String version;\r
+       \r
+       public void setName(String name) {\r
+               this.name = name;\r
+       }\r
+\r
+       public void setVersion(String version) {\r
+               this.version = version;\r
+       }\r
+\r
+       public String getName() {\r
+               return name;\r
+       }\r
+\r
+       public String getVersion() {\r
+               return version;\r
+       }\r
+\r
+}\r
index 8a950fcf0b9a172b7fd100dbf9ff220b317359df..319fe8fbafe17c502896edb081e3f842021a7b27 100644 (file)
                <property name="scopes">
                        <map>
                                <entry key="execution">
-                                       <bean class="org.argeo.slc.core.execution.ExecutionScope" />
+                                       <ref local="executionScope"/>
                                </entry>
                        </map>
                </property>
        </bean>
 
+       <bean id="executionScope" class="org.argeo.slc.core.execution.ExecutionScope" />
+
        <bean
                class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
 
-       <bean class="org.argeo.slc.core.execution.ExecutionParameterPostProcessor" />
+       <bean id="executionContext" class="org.argeo.slc.core.execution.MapExecutionContext" scope="execution">
+               <aop:scoped-proxy />
+       </bean>
+
+       <bean class="org.argeo.slc.core.execution.ExecutionParameterPostProcessor" >
+               <property name="executionContext">
+                       <ref local="executionContext" />
+               </property>
+               <property name="executionScope">
+                       <ref local="executionScope"/>
+               </property>
+       </bean>
+       
        <bean class="org.argeo.slc.core.execution.InstantiationPostProcessor" />
-       <bean class="org.argeo.slc.core.execution.Executor" />
-       <bean class="org.argeo.slc.core.execution.ExecutionAspect"/>
+       
+       <!-- <bean class="org.argeo.slc.core.execution.Executor" /> -->
+       
+       <bean class="org.argeo.slc.core.execution.ExecutionAspect">
+               <property name="executionContext">
+                       <ref local="executionContext" />
+               </property>
+       </bean>
 
        <aop:aspectj-autoproxy />
 
index 9ada76d0f24fb2746792b9b48fb3225a8ce525e0..8a191fcf62dcd65b76e81b09e9ad0c55724bc59f 100644 (file)
@@ -41,7 +41,8 @@ public class DefaultModulesMangerTest extends AbstractSpringTestCase {
                \r
                // create a module\r
                ApplicationContext applicationContext = prepareExecution("applicationContext.xml");\r
-               ExecutionModule module = createExecutionModule(applicationContext);\r
+//             ExecutionModule module = createExecutionModule(applicationContext);\r
+               ExecutionModule module = (ExecutionModule) applicationContext.getBean("executionModule_1");\r
                \r
                // create an Execution Module Manager\r
                DefaultModulesManager manager = new DefaultModulesManager();\r
@@ -57,6 +58,7 @@ public class DefaultModulesMangerTest extends AbstractSpringTestCase {
                        public String getName() {return "dummyname";}\r
                        public String getVersion() {return "dummyversion";}                     \r
                };\r
+               module.setExecutionContext(new MapExecutionContext());\r
                module.setApplicationContext(applicationContext);\r
                return module;\r
        }\r
index 8b4669b11988bb04266253346ba2ebaebfa0c70a..d97a501ab4cc869223ef2b82601b1328f1571e0c 100644 (file)
@@ -53,12 +53,12 @@ public class ExecutionFlowTest extends AbstractSpringTestCase {
        }\r
        \r
        protected void initExecutionContext() {\r
-               // if an execution context was registered, unregister it\r
-               if(ExecutionContext.getCurrent() != null) {\r
-                       ExecutionContext.unregisterExecutionContext();\r
+/*             // if an execution context was registered, unregister it\r
+               if(MapExecutionContext.getCurrent() != null) {\r
+                       MapExecutionContext.unregisterExecutionContext();\r
                }\r
                // register a new ExecutionContext\r
-               ExecutionContext.registerExecutionContext(new ExecutionContext());              \r
+               MapExecutionContext.registerExecutionContext(new MapExecutionContext());                */\r
        }\r
        \r
        protected ConfigurableApplicationContext prepareExecution(String applicationContextSuffix) {\r
index e5922698e38a5f3bc23ada152aad7c0e06c25d3f..c39339c55378207428b8089c23f27becb1d4f5f8 100644 (file)
@@ -7,6 +7,14 @@
 \r
        <import resource="imports.xml" /> \r
 \r
+       <bean id="executionModule_1" class="org.argeo.slc.core.execution.SimpleSpringExecutionModule" >\r
+               <property name="executionContext">\r
+                       <ref bean="executionContext" />\r
+               </property>     \r
+               <property name="name" value="dummyname" />\r
+               <property name="version" value="dummyversion" />\r
+       </bean>\r
\r
        <bean id="main" parent="slcTemplate.simpleFlow">\r
                <property name="executionSpec">\r
                        <bean parent="slcTemplate.simpleSpec">\r