1 package org
.argeo
.slc
.core
.execution
;
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
;
14 public class ExecutionScope
implements Scope
{
15 private final static Log log
= LogFactory
.getLog(ExecutionScope
.class);
17 private final ThreadLocal
<ExecutionStack
> executionStack
= new ThreadLocal
<ExecutionStack
>();
18 public final ThreadLocal
<String
> executionStackBeanName
= new ThreadLocal
<String
>();
20 private final ThreadLocal
<ExecutionContext
> executionContext
= new ThreadLocal
<ExecutionContext
>();
21 private final ThreadLocal
<String
> executionContextBeanName
= new ThreadLocal
<String
>();
23 public Object
get(String name
, ObjectFactory objectFactory
) {
24 if (log
.isTraceEnabled())
25 log
.debug("Get execution scoped bean " + name
);
28 if (executionStackBeanName
.get() != null
29 && name
.equals(executionStackBeanName
.get())) {
30 return executionStack
.get();
33 if (executionContextBeanName
.get() != null
34 && name
.equals(executionContextBeanName
.get())) {
35 return executionContext
.get();
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
);
45 // TODO: use execution context wrapper
46 throw new SlcException("No execution context has been defined.");
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
);
57 throw new SlcException("No execution stack has been defined.");
61 // see if the execution stack already knows the object
62 Object obj
= executionStack
.get().findScopedObject(name
);
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");
72 checkForbiddenClasses(obj
);
74 executionStack
.get().addScopedObject(name
, obj
);
80 protected <T
> T
dealWithSpecialScopedObject(String name
,
81 ThreadLocal
<T
> threadLocal
,
82 ThreadLocal
<String
> threadLocalBeanName
, T newObj
) {
84 T obj
= threadLocal
.get();
88 threadLocalBeanName
.set(name
);
89 if (log
.isTraceEnabled()) {
90 log
.debug(obj
.getClass() + " instantiated. (beanName=" + name
95 throw new SlcException("Only one scoped " + obj
.getClass()
96 + " can be defined per thread");
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
);
109 public String
getConversationId() {
110 // TODO: is it the most relevant?
111 return executionContext
.get().getUuid();
114 public void registerDestructionCallback(String name
, Runnable callback
) {
115 // TODO: implement it
116 // throw new UnsupportedOperationException();
119 public Object
remove(String name
) {
120 if (log
.isDebugEnabled())
121 log
.debug("Remove object " + name
);
122 throw new UnsupportedOperationException();