X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;ds=sidebyside;f=runtime%2Forg.argeo.slc.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2FExecutionScope.java;fp=runtime%2Forg.argeo.slc.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2FExecutionScope.java;h=2cbd70897b93a39d4f68a8e21e745d4226d32ed6;hb=08aa02f96eb32a6e1f0cc001113df9311a618eb9;hp=a24046a99869a443f4fb024de4a5aff5875599e3;hpb=db59a5946d2d0196c31edadc9612094c1136121d;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java index a24046a99..2cbd70897 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/ExecutionScope.java @@ -1,104 +1,114 @@ package org.argeo.slc.core.execution; -import java.util.HashMap; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; import org.argeo.slc.execution.ExecutionContext; +import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.execution.ExecutionSpec; +import org.argeo.slc.execution.ExecutionStack; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.config.Scope; public class ExecutionScope implements Scope { private final static Log log = LogFactory.getLog(ExecutionScope.class); - private final ThreadLocal executionContext = new ThreadLocal(); + private final ThreadLocal executionStack = new ThreadLocal(); + public final ThreadLocal executionStackBeanName = new ThreadLocal(); - public final ThreadLocal executionContextBeanName = new ThreadLocal(); + private final ThreadLocal executionContext = new ThreadLocal(); + private final ThreadLocal executionContextBeanName = new ThreadLocal(); public Object get(String name, ObjectFactory objectFactory) { - if (log.isTraceEnabled()) - log.trace("Getting scoped bean " + name); + log.debug("Get execution scoped bean " + name); + + // shortcuts + if (executionStackBeanName.get() != null + && name.equals(executionStackBeanName.get())) { + return executionStack.get(); + } + + if (executionContextBeanName.get() != null + && name.equals(executionContextBeanName.get())) { + return executionContext.get(); + } - // check if an execution context is defined for this thread + // execution context must be defined first if (executionContext.get() == null) { - // if not, we expect objectFactory to produce an ExecutionContext Object obj = objectFactory.getObject(); if (obj instanceof ExecutionContext) { - // Check whether we are in an execution - // FIXME: do it more properly (not static) - // see https://www.argeo.org/bugzilla/show_bug.cgi?id=82 - if (!ExecutionAspect.inModuleExecution.get()) { - log - .error("An execution context is being instantiated outside a module execution." - + " Please check your references to execution contexts." - + " This may lead to unexpected behaviour and will be rejected in the future."); - //Thread.dumpStack(); - } - - // store the ExecutionContext in the ThreadLocal - executionContext.set((ExecutionContext) obj); - executionContextBeanName.set(name); - if (log.isDebugEnabled()) { - log.debug("Execution context #" - + executionContext.get().getUuid() - + " instantiated. (beanName=" - + executionContextBeanName.get() + ")"); - // Thread.dumpStack(); - } - return obj; + return dealWithSpecialScopedObject(name, executionContext, + executionContextBeanName, (ExecutionContext) obj); } else { - throw new SlcException( - "Expected an ExecutionContext, got an object of class " - + obj.getClass() - + " for bean " - + name - + ": make sure that you have porperly set scope=\"execution\" where required"); + // TODO: use execution context wrapper + throw new SlcException("No execution context has been defined."); } } - if (name.equals(executionContextBeanName.get())) { - return executionContext.get(); - } else { - // see if the executionContext already knows the object - Object obj = executionContext.get().findScopedObject(name); - if (obj == null) { - obj = objectFactory.getObject(); - if (!(obj instanceof ExecutionContext)) { - executionContext.get().addScopedObject(name, obj); - } else { - throw new SlcException( - "Only one ExecutionContext can be defined per Thread"); - } + // for other scoped objects, an executions stack must be available + if (executionStack.get() == null) { + Object obj = objectFactory.getObject(); + if (obj instanceof ExecutionStack) { + return dealWithSpecialScopedObject(name, executionStack, + executionStackBeanName, (ExecutionStack) obj); + } else { + throw new SlcException("No execution stack has been defined."); } - return obj; } - // if (ExecutionContext.getScopedObjects().containsKey(name)) { - // // returns cached instance - // Object obj = ExecutionContext.getScopedObjects().get(name); - // if (log.isTraceEnabled()) - // log.trace("Return cached scoped object " + obj); - // return obj; - // } else { - // // creates instance - // Object obj = objectFactory.getObject(); - // ExecutionContext.getScopedObjects().put(name, obj); - // if (log.isTraceEnabled()) - // log.trace("Created regular scoped object " + obj); - // return obj; - // } + // see if the execution stack already knows the object + Object obj = executionStack.get().findScopedObject(name); + if (obj == null) { + obj = objectFactory.getObject(); + if (obj instanceof ExecutionContext) + throw new SlcException( + "Only one execution context can be defined per thread"); + if (obj instanceof ExecutionStack) + throw new SlcException( + "Only one execution stack can be defined per thread"); + + checkForbiddenClasses(obj); + + executionStack.get().addScopedObject(name, obj); + } + return obj; + } - public String getConversationId() { + protected T dealWithSpecialScopedObject(String name, + ThreadLocal threadLocal, + ThreadLocal threadLocalBeanName, T newObj) { + + T obj = threadLocal.get(); + if (obj == null) { + obj = newObj; + threadLocal.set(obj); + threadLocalBeanName.set(name); + if (log.isDebugEnabled()) { + log.debug(obj.getClass() + " instantiated. (beanName=" + name + + ")"); + } + return obj; + } else { + throw new SlcException("Only one scoped " + obj.getClass() + + " can be defined per thread"); + } - return executionContext.get().getUuid(); } - public Boolean hasExecutionContext() { - return executionContext.get() != null; + protected void checkForbiddenClasses(Object obj) { + Class clss = obj.getClass(); + if (ExecutionFlow.class.isAssignableFrom(clss) + || ExecutionSpec.class.isAssignableFrom(clss)) { + throw new UnsupportedException("Execution scoped object", clss); + } + } + + public String getConversationId() { + // TODO: is it the most relevant? + return executionContext.get().getUuid(); } public void registerDestructionCallback(String name, Runnable callback) { @@ -107,7 +117,8 @@ public class ExecutionScope implements Scope { } public Object remove(String name) { - log.debug("Remove object " + name); + if (log.isDebugEnabled()) + log.debug("Remove object " + name); throw new UnsupportedOperationException(); }