]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/ExecutionContext.java
d6b69af8485494dbd18cf66e693af489af1ce515
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.simple / src / main / java / org / argeo / slc / core / execution / ExecutionContext.java
1 package org.argeo.slc.core.execution;
2
3 import java.util.HashMap;
4 import java.util.Map;
5 import java.util.Stack;
6 import java.util.UUID;
7
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;
15
16 public class ExecutionContext {
17 private final static Log log = LogFactory.getLog(ExecutionContext.class);
18
19 private final static ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
20
21 private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
22
23 // TODO: make it thread safe?
24 private final Map<String, Object> variables = new HashMap<String, Object>();
25
26 private final String uuid = UUID.randomUUID().toString();
27
28 public static Map<String, Object> getVariables() {
29 if (executionContext.get() == null)
30 return null;
31 return executionContext.get().variables;
32 }
33
34 public void addVariables(Map<? extends String, ? extends Object> variablesToAdd) {
35 variables.putAll(variablesToAdd);
36 }
37
38 public static ExecutionContext getCurrent() {
39 return executionContext.get();
40 }
41
42 public static String getExecutionUuid() {
43 if (executionContext.get() == null)
44 return null;
45 return executionContext.get().getUuid();
46 }
47
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);
53 }
54
55 /**
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
59 */
60 public static ExecutionContext unregisterExecutionContext() {
61 ExecutionContext current = executionContext.get();
62 if(current == null) {
63 throw new SlcException("No Context registered.");
64 }
65 executionContext.remove();
66 return current;
67 }
68
69 public static void enterFlow(ExecutionFlow executionFlow) {
70 Stack<ExecutionFlowRuntime> stack = executionContext.get().stack;
71
72 ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
73 stack.push(runtime);
74
75 if (log.isDebugEnabled())
76 log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
77 + getCurrentStackUuid() + ", depth=" + stack.size());
78
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.");
89 }
90 }
91
92 }
93
94 public static Object getVariable(String key) {
95 Object obj = getWithCheck().findVariable(key);
96 if (obj == null)
97 throw new SlcException("Variable '" + key + "' not found.");
98 return obj;
99 }
100
101 protected Object findVariable(String key) {
102 Object obj = null;
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);
106 break;
107 }
108 }
109
110 // Look into global execution variables
111 if (obj == null) {
112 if (variables.containsKey(key))
113 obj = variables.get(key);
114 }
115
116 return obj;
117 }
118
119 private static String depthSpaces(int depth) {
120 StringBuffer buf = new StringBuffer(depth * 2);
121 for (int i = 0; i < depth; i++)
122 buf.append(" ");
123 return buf.toString();
124 }
125
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());
131
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);
137
138 leftEf.getScopedObjects().clear();
139 leftEf.getLocalVariables().clear();
140
141 }
142
143 public static String getCurrentStackUuid() {
144 return getWithCheck().stack.peek().uuid;
145 }
146
147 // public static ExecutionFlow getCurrentFlow() {
148 // return getWithCheck().stack.peek().executionFlow;
149 // }
150
151 public static Boolean isExecuting() {
152 return executionContext.get() != null;
153 }
154
155 protected static ExecutionContext getWithCheck() {
156 if (executionContext.get() == null)
157 throw new SlcException("No execution context");
158 return executionContext.get();
159 }
160
161 public static Object findOrAddScopedObject(String name,
162 ObjectFactory objectFactory) {
163 ExecutionContext executionContext = getWithCheck();
164 Object obj = executionContext.findScopedObject(name);
165 if (obj == null) {
166 obj = objectFactory.getObject();
167 executionContext.stack.peek().getScopedObjects().put(name, obj);
168 }
169 return obj;
170 }
171
172 /** return null if not found */
173 protected Object findScopedObject(String key) {
174 Object obj = null;
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);
178 break;
179 }
180 }
181 return obj;
182 }
183
184 public String getUuid() {
185 return uuid;
186 }
187
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();
193
194 public ExecutionFlowRuntime(ExecutionFlow executionFlow) {
195 this.executionFlow = executionFlow;
196 }
197
198 public ExecutionFlow getExecutionFlow() {
199 return executionFlow;
200 }
201
202 public Map<String, Object> getScopedObjects() {
203 return scopedObjects;
204 }
205
206 public String getUuid() {
207 return uuid;
208 }
209
210 public Map<String, Object> getLocalVariables() {
211 return localVariables;
212 }
213
214 }
215 }