1 package org
.argeo
.slc
.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
.process
.SlcExecution
;
12 import org
.springframework
.beans
.factory
.ObjectFactory
;
14 public class ExecutionContext
{
15 private final static Log log
= LogFactory
.getLog(ExecutionContext
.class);
17 private final static ThreadLocal
<ExecutionContext
> executionContext
= new ThreadLocal
<ExecutionContext
>();
19 private final Stack
<ExecutionFlowRuntime
> stack
= new Stack
<ExecutionFlowRuntime
>();
21 // TODO: make it thread safe?
22 private final Map
<String
, Object
> variables
= new HashMap
<String
, Object
>();
24 private final String uuid
= UUID
.randomUUID().toString();
26 public static Map
<String
, Object
> getVariables() {
27 if (executionContext
.get() == null)
29 return executionContext
.get().variables
;
32 public static ExecutionContext
getCurrent() {
33 return executionContext
.get();
36 public static String
getExecutionUuid() {
37 if (executionContext
.get() == null)
39 return executionContext
.get().getUuid();
42 public static void registerExecutionContext(ExecutionContext context
) {
43 if (executionContext
.get() != null)
44 throw new SlcException("Context #" + executionContext
.get().uuid
45 + " already registered.");
46 executionContext
.set(context
);
49 public static void enterFlow(ExecutionFlow executionFlow
) {
50 Stack
<ExecutionFlowRuntime
> stack
= executionContext
.get().stack
;
52 ExecutionFlowRuntime runtime
= new ExecutionFlowRuntime(executionFlow
);
55 if (log
.isDebugEnabled())
56 log
.debug(depthSpaces(stack
.size()) + "=> " + executionFlow
+ " #"
57 + getCurrentStackUuid() + ", depth=" + stack
.size());
59 Map
<String
, ExecutionSpecAttribute
> specAttrs
= executionFlow
60 .getExecutionSpec().getAttributes();
61 for (String key
: specAttrs
.keySet()) {
62 ExecutionSpecAttribute esa
= specAttrs
.get(key
);
63 if (esa
.getIsParameter()) {
64 runtime
.getLocalVariables().put(key
,
65 executionFlow
.getParameter(key
));
66 if (log
.isTraceEnabled())
67 log
.trace(depthSpaces(stack
.size()) + "Add '" + key
68 + "' as local variable.");
74 public static Object
getVariable(String key
) {
75 Object obj
= getWithCheck().findVariable(key
);
77 throw new SlcException("Variable '" + key
+ "' not found.");
81 protected Object
findVariable(String key
) {
83 for (int i
= stack
.size() - 1; i
>= 0; i
--) {
84 if (stack
.get(i
).getLocalVariables().containsKey(key
)) {
85 obj
= stack
.get(i
).getLocalVariables().get(key
);
90 // Look into global execution variables
92 if (variables
.containsKey(key
))
93 obj
= variables
.get(key
);
99 private static String
depthSpaces(int depth
) {
100 StringBuffer buf
= new StringBuffer(depth
* 2);
101 for (int i
= 0; i
< depth
; i
++)
103 return buf
.toString();
106 public static void leaveFlow(ExecutionFlow executionFlow
) {
107 Stack
<ExecutionFlowRuntime
> stack
= executionContext
.get().stack
;
108 if (log
.isDebugEnabled())
109 log
.debug(depthSpaces(stack
.size()) + "<= " + executionFlow
+ " #"
110 + getCurrentStackUuid() + ", depth=" + stack
.size());
112 ExecutionFlowRuntime leftEf
= stack
.pop();
113 if (!leftEf
.getExecutionFlow().getName()
114 .equals(executionFlow
.getName()))
115 throw new SlcException("Asked to leave " + executionFlow
116 + " but last is " + leftEf
);
118 leftEf
.getScopedObjects().clear();
119 leftEf
.getLocalVariables().clear();
123 public static String
getCurrentStackUuid() {
124 return getWithCheck().stack
.peek().uuid
;
127 // public static ExecutionFlow getCurrentFlow() {
128 // return getWithCheck().stack.peek().executionFlow;
131 public static Boolean
isExecuting() {
132 return executionContext
.get() != null;
135 protected static ExecutionContext
getWithCheck() {
136 if (executionContext
.get() == null)
137 throw new SlcException("No execution context");
138 return executionContext
.get();
141 public static Object
findOrAddScopedObject(String name
,
142 ObjectFactory objectFactory
) {
143 ExecutionContext executionContext
= getWithCheck();
144 Object obj
= executionContext
.findScopedObject(name
);
146 obj
= objectFactory
.getObject();
147 executionContext
.stack
.peek().getScopedObjects().put(name
, obj
);
152 /** return null if not found */
153 protected Object
findScopedObject(String key
) {
155 for (int i
= stack
.size() - 1; i
>= 0; i
--) {
156 if (stack
.get(i
).getScopedObjects().containsKey(key
)) {
157 obj
= stack
.get(i
).getScopedObjects().get(key
);
164 public String
getUuid() {
168 private static class ExecutionFlowRuntime
{
169 private final ExecutionFlow executionFlow
;
170 private final Map
<String
, Object
> scopedObjects
= new HashMap
<String
, Object
>();
171 private final Map
<String
, Object
> localVariables
= new HashMap
<String
, Object
>();
172 private final String uuid
= UUID
.randomUUID().toString();
174 public ExecutionFlowRuntime(ExecutionFlow executionFlow
) {
175 this.executionFlow
= executionFlow
;
178 public ExecutionFlow
getExecutionFlow() {
179 return executionFlow
;
182 public Map
<String
, Object
> getScopedObjects() {
183 return scopedObjects
;
186 public String
getUuid() {
190 public Map
<String
, Object
> getLocalVariables() {
191 return localVariables
;