1 package org
.argeo
.slc
.core
.execution
;
3 import java
.util
.HashMap
;
5 import java
.util
.Stack
;
8 import org
.apache
.commons
.logging
.Log
;
9 import org
.apache
.commons
.logging
.LogFactory
;
10 import org
.argeo
.slc
.SlcException
;
11 import org
.argeo
.slc
.execution
.ExecutionFlow
;
12 import org
.argeo
.slc
.execution
.ExecutionSpecAttribute
;
13 import org
.argeo
.slc
.process
.SlcExecution
;
14 import org
.springframework
.beans
.factory
.ObjectFactory
;
16 public class ExecutionContext
{
17 private final static Log log
= LogFactory
.getLog(ExecutionContext
.class);
19 private final static ThreadLocal
<ExecutionContext
> executionContext
= new ThreadLocal
<ExecutionContext
>();
21 private final Stack
<ExecutionFlowRuntime
> stack
= new Stack
<ExecutionFlowRuntime
>();
23 // TODO: make it thread safe?
24 private final Map
<String
, Object
> variables
= new HashMap
<String
, Object
>();
26 private final String uuid
= UUID
.randomUUID().toString();
28 public static Map
<String
, Object
> getVariables() {
29 if (executionContext
.get() == null)
31 return executionContext
.get().variables
;
34 public void addVariables(Map
<?
extends String
, ?
extends Object
> variablesToAdd
) {
35 variables
.putAll(variablesToAdd
);
38 public static ExecutionContext
getCurrent() {
39 return executionContext
.get();
42 public static String
getExecutionUuid() {
43 if (executionContext
.get() == null)
45 return executionContext
.get().getUuid();
48 public static void registerExecutionContext(ExecutionContext context
) {
49 if (executionContext
.get() != null)
50 throw new SlcException("Context #" + executionContext
.get().uuid
51 + " already registered.");
52 executionContext
.set(context
);
56 * Unregisters the ExecutionContext for the current Thread
57 * @throws a SlcException if no ExecutionContext was registered for the Thread
58 * @return the unregistered ExecutionContext
60 public static ExecutionContext
unregisterExecutionContext() {
61 ExecutionContext current
= executionContext
.get();
63 throw new SlcException("No Context registered.");
65 executionContext
.remove();
69 public static void enterFlow(ExecutionFlow executionFlow
) {
70 Stack
<ExecutionFlowRuntime
> stack
= executionContext
.get().stack
;
72 ExecutionFlowRuntime runtime
= new ExecutionFlowRuntime(executionFlow
);
75 if (log
.isDebugEnabled())
76 log
.debug(depthSpaces(stack
.size()) + "=> " + executionFlow
+ " #"
77 + getCurrentStackUuid() + ", depth=" + stack
.size());
79 Map
<String
, ExecutionSpecAttribute
> specAttrs
= executionFlow
80 .getExecutionSpec().getAttributes();
81 for (String key
: specAttrs
.keySet()) {
82 //ExecutionSpecAttribute esa = specAttrs.get(key);
83 if (executionFlow
.isSetAsParameter(key
)) {
84 runtime
.getLocalVariables().put(key
,
85 executionFlow
.getParameter(key
));
86 if (log
.isTraceEnabled())
87 log
.trace(depthSpaces(stack
.size()) + "Add '" + key
88 + "' as local variable.");
94 public static Object
getVariable(String key
) {
95 Object obj
= getWithCheck().findVariable(key
);
97 throw new SlcException("Variable '" + key
+ "' not found.");
101 protected Object
findVariable(String key
) {
103 for (int i
= stack
.size() - 1; i
>= 0; i
--) {
104 if (stack
.get(i
).getLocalVariables().containsKey(key
)) {
105 obj
= stack
.get(i
).getLocalVariables().get(key
);
110 // Look into global execution variables
112 if (variables
.containsKey(key
))
113 obj
= variables
.get(key
);
119 private static String
depthSpaces(int depth
) {
120 StringBuffer buf
= new StringBuffer(depth
* 2);
121 for (int i
= 0; i
< depth
; i
++)
123 return buf
.toString();
126 public static void leaveFlow(ExecutionFlow executionFlow
) {
127 Stack
<ExecutionFlowRuntime
> stack
= executionContext
.get().stack
;
128 if (log
.isDebugEnabled())
129 log
.debug(depthSpaces(stack
.size()) + "<= " + executionFlow
+ " #"
130 + getCurrentStackUuid() + ", depth=" + stack
.size());
132 ExecutionFlowRuntime leftEf
= stack
.pop();
133 if (!leftEf
.getExecutionFlow().getName()
134 .equals(executionFlow
.getName()))
135 throw new SlcException("Asked to leave " + executionFlow
136 + " but last is " + leftEf
);
138 leftEf
.getScopedObjects().clear();
139 leftEf
.getLocalVariables().clear();
143 public static String
getCurrentStackUuid() {
144 return getWithCheck().stack
.peek().uuid
;
147 // public static ExecutionFlow getCurrentFlow() {
148 // return getWithCheck().stack.peek().executionFlow;
151 public static Boolean
isExecuting() {
152 return executionContext
.get() != null;
155 protected static ExecutionContext
getWithCheck() {
156 if (executionContext
.get() == null)
157 throw new SlcException("No execution context");
158 return executionContext
.get();
161 public static Object
findOrAddScopedObject(String name
,
162 ObjectFactory objectFactory
) {
163 ExecutionContext executionContext
= getWithCheck();
164 Object obj
= executionContext
.findScopedObject(name
);
166 obj
= objectFactory
.getObject();
167 executionContext
.stack
.peek().getScopedObjects().put(name
, obj
);
172 /** return null if not found */
173 protected Object
findScopedObject(String key
) {
175 for (int i
= stack
.size() - 1; i
>= 0; i
--) {
176 if (stack
.get(i
).getScopedObjects().containsKey(key
)) {
177 obj
= stack
.get(i
).getScopedObjects().get(key
);
184 public String
getUuid() {
188 private static class ExecutionFlowRuntime
{
189 private final ExecutionFlow executionFlow
;
190 private final Map
<String
, Object
> scopedObjects
= new HashMap
<String
, Object
>();
191 private final Map
<String
, Object
> localVariables
= new HashMap
<String
, Object
>();
192 private final String uuid
= UUID
.randomUUID().toString();
194 public ExecutionFlowRuntime(ExecutionFlow executionFlow
) {
195 this.executionFlow
= executionFlow
;
198 public ExecutionFlow
getExecutionFlow() {
199 return executionFlow
;
202 public Map
<String
, Object
> getScopedObjects() {
203 return scopedObjects
;
206 public String
getUuid() {
210 public Map
<String
, Object
> getLocalVariables() {
211 return localVariables
;