]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java
Modular distributions
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / ExecutionScope.java
1 package org.argeo.slc.core.execution;
2
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 import org.argeo.slc.SlcException;
6 import org.argeo.slc.UnsupportedException;
7 import org.argeo.slc.execution.ExecutionContext;
8 import org.argeo.slc.execution.ExecutionFlow;
9 import org.argeo.slc.execution.ExecutionSpec;
10 import org.argeo.slc.execution.ExecutionStack;
11 import org.springframework.beans.factory.ObjectFactory;
12 import org.springframework.beans.factory.config.Scope;
13
14 public class ExecutionScope implements Scope {
15 private final static Log log = LogFactory.getLog(ExecutionScope.class);
16
17 private final ThreadLocal<ExecutionStack> executionStack = new ThreadLocal<ExecutionStack>();
18 public final ThreadLocal<String> executionStackBeanName = new ThreadLocal<String>();
19
20 private final ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
21 private final ThreadLocal<String> executionContextBeanName = new ThreadLocal<String>();
22
23 public Object get(String name, ObjectFactory objectFactory) {
24 if (log.isTraceEnabled())
25 log.debug("Get execution scoped bean " + name);
26
27 // shortcuts
28 if (executionStackBeanName.get() != null
29 && name.equals(executionStackBeanName.get())) {
30 return executionStack.get();
31 }
32
33 if (executionContextBeanName.get() != null
34 && name.equals(executionContextBeanName.get())) {
35 return executionContext.get();
36 }
37
38 // execution context must be defined first
39 if (executionContext.get() == null) {
40 Object obj = objectFactory.getObject();
41 if (obj instanceof ExecutionContext) {
42 return dealWithSpecialScopedObject(name, executionContext,
43 executionContextBeanName, (ExecutionContext) obj);
44 } else {
45 // TODO: use execution context wrapper
46 throw new SlcException("No execution context has been defined.");
47 }
48 }
49
50 // for other scoped objects, an executions stack must be available
51 if (executionStack.get() == null) {
52 Object obj = objectFactory.getObject();
53 if (obj instanceof ExecutionStack) {
54 return dealWithSpecialScopedObject(name, executionStack,
55 executionStackBeanName, (ExecutionStack) obj);
56 } else {
57 throw new SlcException("No execution stack has been defined.");
58 }
59 }
60
61 // see if the execution stack already knows the object
62 Object obj = executionStack.get().findScopedObject(name);
63 if (obj == null) {
64 obj = objectFactory.getObject();
65 if (obj instanceof ExecutionContext)
66 throw new SlcException(
67 "Only one execution context can be defined per thread");
68 if (obj instanceof ExecutionStack)
69 throw new SlcException(
70 "Only one execution stack can be defined per thread");
71
72 checkForbiddenClasses(obj);
73
74 executionStack.get().addScopedObject(name, obj);
75 }
76 return obj;
77
78 }
79
80 protected <T> T dealWithSpecialScopedObject(String name,
81 ThreadLocal<T> threadLocal,
82 ThreadLocal<String> threadLocalBeanName, T newObj) {
83
84 T obj = threadLocal.get();
85 if (obj == null) {
86 obj = newObj;
87 threadLocal.set(obj);
88 threadLocalBeanName.set(name);
89 if (log.isTraceEnabled()) {
90 log.debug(obj.getClass() + " instantiated. (beanName=" + name
91 + ")");
92 }
93 return obj;
94 } else {
95 throw new SlcException("Only one scoped " + obj.getClass()
96 + " can be defined per thread");
97 }
98
99 }
100
101 protected void checkForbiddenClasses(Object obj) {
102 Class<?> clss = obj.getClass();
103 if (ExecutionFlow.class.isAssignableFrom(clss)
104 || ExecutionSpec.class.isAssignableFrom(clss)) {
105 throw new UnsupportedException("Execution scoped object", clss);
106 }
107 }
108
109 public String getConversationId() {
110 // TODO: is it the most relevant?
111 return executionContext.get().getUuid();
112 }
113
114 public void registerDestructionCallback(String name, Runnable callback) {
115 // TODO: implement it
116 // throw new UnsupportedOperationException();
117 }
118
119 public Object remove(String name) {
120 if (log.isDebugEnabled())
121 log.debug("Remove object " + name);
122 throw new UnsupportedOperationException();
123 }
124
125 }