2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org
.argeo
.slc
.core
.execution
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.argeo
.slc
.SlcException
;
22 import org
.argeo
.slc
.UnsupportedException
;
23 import org
.argeo
.slc
.execution
.ExecutionContext
;
24 import org
.argeo
.slc
.execution
.ExecutionFlow
;
25 import org
.argeo
.slc
.execution
.ExecutionSpec
;
26 import org
.argeo
.slc
.execution
.ExecutionStack
;
27 import org
.springframework
.beans
.factory
.ObjectFactory
;
28 import org
.springframework
.beans
.factory
.config
.Scope
;
30 public class ExecutionScope
implements Scope
{
31 private final static Log log
= LogFactory
.getLog(ExecutionScope
.class);
33 private final ThreadLocal
<ExecutionStack
> executionStack
= new ThreadLocal
<ExecutionStack
>();
34 public final ThreadLocal
<String
> executionStackBeanName
= new ThreadLocal
<String
>();
36 private final ThreadLocal
<ExecutionContext
> executionContext
= new ThreadLocal
<ExecutionContext
>();
37 private final ThreadLocal
<String
> executionContextBeanName
= new ThreadLocal
<String
>();
39 public Object
get(String name
, ObjectFactory objectFactory
) {
40 if (log
.isTraceEnabled())
41 log
.debug("Get execution scoped bean " + name
);
44 if (executionStackBeanName
.get() != null
45 && name
.equals(executionStackBeanName
.get())) {
46 return executionStack
.get();
49 if (executionContextBeanName
.get() != null
50 && name
.equals(executionContextBeanName
.get())) {
51 return executionContext
.get();
54 // execution context must be defined first
55 if (executionContext
.get() == null) {
56 Object obj
= objectFactory
.getObject();
57 if (obj
instanceof ExecutionContext
) {
58 return dealWithSpecialScopedObject(name
, executionContext
,
59 executionContextBeanName
, (ExecutionContext
) obj
);
61 // TODO: use execution context wrapper
62 throw new SlcException("No execution context has been defined.");
66 // for other scoped objects, an executions stack must be available
67 if (executionStack
.get() == null) {
68 Object obj
= objectFactory
.getObject();
69 if (obj
instanceof ExecutionStack
) {
70 return dealWithSpecialScopedObject(name
, executionStack
,
71 executionStackBeanName
, (ExecutionStack
) obj
);
73 throw new SlcException("No execution stack has been defined.");
77 // see if the execution stack already knows the object
78 Object obj
= executionStack
.get().findScopedObject(name
);
80 obj
= objectFactory
.getObject();
81 if (obj
instanceof ExecutionContext
)
82 throw new SlcException(
83 "Only one execution context can be defined per thread");
84 if (obj
instanceof ExecutionStack
)
85 throw new SlcException(
86 "Only one execution stack can be defined per thread");
88 checkForbiddenClasses(obj
);
90 executionStack
.get().addScopedObject(name
, obj
);
96 protected <T
> T
dealWithSpecialScopedObject(String name
,
97 ThreadLocal
<T
> threadLocal
,
98 ThreadLocal
<String
> threadLocalBeanName
, T newObj
) {
100 T obj
= threadLocal
.get();
103 threadLocal
.set(obj
);
104 threadLocalBeanName
.set(name
);
105 if (log
.isTraceEnabled()) {
106 log
.debug(obj
.getClass() + " instantiated. (beanName=" + name
111 throw new SlcException("Only one scoped " + obj
.getClass()
112 + " can be defined per thread");
117 protected void checkForbiddenClasses(Object obj
) {
118 Class
<?
> clss
= obj
.getClass();
119 if (ExecutionFlow
.class.isAssignableFrom(clss
)
120 || ExecutionSpec
.class.isAssignableFrom(clss
)) {
121 throw new UnsupportedException("Execution scoped object", clss
);
125 public String
getConversationId() {
126 // TODO: is it the most relevant?
127 return executionContext
.get().getUuid();
130 public void registerDestructionCallback(String name
, Runnable callback
) {
131 // TODO: implement it
132 // throw new UnsupportedOperationException();
135 public Object
remove(String name
) {
136 if (log
.isDebugEnabled())
137 log
.debug("Remove object " + name
);
138 throw new UnsupportedOperationException();