]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.core/src/org/argeo/slc/core/execution/ExecutionScope.java
Disable trace logging
[gpl/argeo-slc.git] / org.argeo.slc.core / src / org / argeo / slc / core / execution / ExecutionScope.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.argeo.slc.core.execution;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.argeo.slc.SlcException;
21 import org.argeo.slc.UnsupportedException;
22 import org.argeo.slc.execution.ExecutionContext;
23 import org.argeo.slc.execution.ExecutionFlow;
24 import org.argeo.slc.execution.ExecutionSpec;
25 import org.argeo.slc.execution.ExecutionStack;
26 import org.springframework.beans.factory.ObjectFactory;
27 import org.springframework.beans.factory.config.Scope;
28
29 /**
30 * When Spring beans are instantiated with this scope, the same instance is
31 * reused across an execution.
32 */
33 public class ExecutionScope implements Scope {
34 private final static Log log = LogFactory.getLog(ExecutionScope.class);
35
36 private final ThreadLocal<ExecutionStack> executionStack = new ThreadLocal<ExecutionStack>();
37 public final ThreadLocal<String> executionStackBeanName = new ThreadLocal<String>();
38
39 private final ThreadLocal<ExecutionContext> executionContext = new ThreadLocal<ExecutionContext>();
40 private final ThreadLocal<String> executionContextBeanName = new ThreadLocal<String>();
41
42 public Object get(String name, ObjectFactory<?> objectFactory) {
43 if (log.isTraceEnabled())
44 log.debug("Get execution scoped bean " + name);
45
46 // shortcuts
47 if (executionStackBeanName.get() != null
48 && name.equals(executionStackBeanName.get())) {
49 return executionStack.get();
50 }
51
52 if (executionContextBeanName.get() != null
53 && name.equals(executionContextBeanName.get())) {
54 return executionContext.get();
55 }
56
57 // execution context must be defined first
58 if (executionContext.get() == null) {
59 Object obj = objectFactory.getObject();
60 if (obj instanceof ExecutionContext) {
61 return dealWithSpecialScopedObject(name, executionContext,
62 executionContextBeanName, (ExecutionContext) obj);
63 } else {
64 // TODO: use execution context wrapper
65 throw new SlcException("No execution context has been defined.");
66 }
67 }
68
69 // for other scoped objects, an executions stack must be available
70 if (executionStack.get() == null) {
71 Object obj = objectFactory.getObject();
72 if (obj instanceof ExecutionStack) {
73 return dealWithSpecialScopedObject(name, executionStack,
74 executionStackBeanName, (ExecutionStack) obj);
75 } else {
76 throw new SlcException("No execution stack has been defined.");
77 }
78 }
79
80 // see if the execution stack already knows the object
81 Object obj = executionStack.get().findScopedObject(name);
82 if (obj == null) {
83 obj = objectFactory.getObject();
84 if (obj instanceof ExecutionContext)
85 throw new SlcException(
86 "Only one execution context can be defined per thread");
87 if (obj instanceof ExecutionStack)
88 throw new SlcException(
89 "Only one execution stack can be defined per thread");
90
91 checkForbiddenClasses(obj);
92
93 executionStack.get().addScopedObject(name, obj);
94 }
95 return obj;
96
97 }
98
99 protected <T> T dealWithSpecialScopedObject(String name,
100 ThreadLocal<T> threadLocal,
101 ThreadLocal<String> threadLocalBeanName, T newObj) {
102
103 T obj = threadLocal.get();
104 if (obj == null) {
105 obj = newObj;
106 threadLocal.set(obj);
107 threadLocalBeanName.set(name);
108 if (log.isTraceEnabled()) {
109 log.debug(obj.getClass() + " instantiated. (beanName=" + name
110 + ")");
111 }
112 return obj;
113 } else {
114 throw new SlcException("Only one scoped " + obj.getClass()
115 + " can be defined per thread");
116 }
117
118 }
119
120 protected void checkForbiddenClasses(Object obj) {
121 Class<?> clss = obj.getClass();
122 if (ExecutionFlow.class.isAssignableFrom(clss)
123 || ExecutionSpec.class.isAssignableFrom(clss)) {
124 throw new UnsupportedException("Execution scoped object", clss);
125 }
126 }
127
128 public String getConversationId() {
129 // TODO: is it the most relevant?
130 return executionContext.get().getUuid();
131 }
132
133 public void registerDestructionCallback(String name, Runnable callback) {
134 if (Thread.currentThread() instanceof ExecutionThread) {
135 ExecutionThread executionThread = (ExecutionThread) Thread
136 .currentThread();
137 executionThread.registerDestructionCallback(name, callback);
138 }
139 }
140
141 public Object remove(String name) {
142 if (log.isDebugEnabled())
143 log.debug("Remove object " + name);
144 throw new UnsupportedOperationException();
145 }
146
147 public Object resolveContextualObject(String key) {
148 return executionContext.get().getVariable(key);
149 }
150
151 }