import org.apache.commons.logging.LogFactory;\r
import org.argeo.slc.SlcException;\r
import org.argeo.slc.execution.ExecutionFlow;\r
+import org.argeo.slc.execution.ExecutionSpecAttribute;\r
\r
public class InstantiationManager {\r
\r
- private final static Log log = LogFactory.getLog(InstantiationManager.class);\r
- \r
- private ThreadLocal<Stack<ExecutionFlow> > flowStack = new ThreadLocal<Stack<ExecutionFlow> >();\r
- \r
+ private final static Log log = LogFactory\r
+ .getLog(InstantiationManager.class);\r
+\r
+ private ThreadLocal<Stack<ExecutionFlow>> flowStack = new ThreadLocal<Stack<ExecutionFlow>>();\r
+\r
public Object createRef(String name) {\r
- \r
- if((flowStack.get() == null) || flowStack.get().empty()) {\r
+\r
+ if ((flowStack.get() == null) || flowStack.get().empty()) {\r
throw new SlcException("No flow is currently initializing."\r
+ " Declare ParameterRef as inner beans or prototypes.");\r
}\r
- \r
+\r
return getInitializingFlowParameter(name);\r
- } \r
- \r
+ }\r
+\r
public void flowInitializationStarted(ExecutionFlow flow, String flowName) {\r
if (log.isTraceEnabled())\r
log.trace("Start initialization of " + flow.hashCode() + " ("\r
+ flow + " - " + flow.getClass() + ")");\r
- \r
+\r
// set the flow name if it is DefaultExecutionFlow\r
- if(flow instanceof DefaultExecutionFlow) {\r
+ if (flow instanceof DefaultExecutionFlow) {\r
((DefaultExecutionFlow) flow).setBeanName(flowName);\r
}\r
- \r
-// log.info("# flowInitializationStarted " + flowName);\r
+\r
+ // log.info("# flowInitializationStarted " + flowName);\r
// create a stack for this thread if there is none\r
- if(flowStack.get() == null) {\r
+ if (flowStack.get() == null) {\r
flowStack.set(new Stack<ExecutionFlow>());\r
}\r
flowStack.get().push(flow);\r
if (registeredFlow != null) {\r
if (!flow.getName().equals(registeredFlow.getName()))\r
throw new SlcException("Current flow is " + flow);\r
-// log.info("# flowInitializationFinished " + flowName);\r
-// initializingFlow.set(null);\r
+ // log.info("# flowInitializationFinished " + flowName);\r
+ // initializingFlow.set(null);\r
}\r
- } \r
- \r
- public Object getInitializingFlowParameter(String key) {\r
+ }\r
+\r
+ protected ExecutionFlow findInitializingFlowWithParameter(String key) {\r
if ((flowStack.get() == null) || flowStack.get().empty())\r
throw new SlcException("No initializing flow available.");\r
- \r
+\r
// first look in the outer flow (that may override parameters)\r
- for(int i = 0; i < flowStack.get().size(); i++) {\r
- if(flowStack.get().elementAt(i).isSetAsParameter(key)) {\r
- return flowStack.get().elementAt(i).getParameter(key);\r
+ for (int i = 0; i < flowStack.get().size(); i++) {\r
+ if (flowStack.get().elementAt(i).isSetAsParameter(key)) {\r
+ return flowStack.get().elementAt(i);\r
}\r
}\r
throw new SlcException("Key " + key + " is not set as parameter in "\r
- + flowStack.get().firstElement().toString() + " (stack size="+flowStack.get().size()+")"); \r
+ + flowStack.get().firstElement().toString() + " (stack size="\r
+ + flowStack.get().size() + ")");\r
+\r
+ }\r
+\r
+ public Object getInitializingFlowParameter(String key) {\r
+ return findInitializingFlowWithParameter(key).getParameter(key);\r
+ }\r
+\r
+ public Class<?> getInitializingFlowParameterClass(String key) {\r
+ ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key)\r
+ .getExecutionSpec().getAttributes().get(key);\r
+ if (attr instanceof RefSpecAttribute)\r
+ return ((RefSpecAttribute) attr).getTargetClass();\r
+ else if (attr instanceof PrimitiveSpecAttribute)\r
+ return ((PrimitiveSpecAttribute) attr).getTypeAsClass();\r
+ else\r
+ return null;\r
}\r
\r
public Boolean isInFlowInitialization() {\r
return (flowStack.get() != null) && !flowStack.get().empty();\r
- } \r
+ }\r
}\r
--- /dev/null
+package org.argeo.slc.core.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.FactoryBean;
+
+public class ParameterRef implements FactoryBean {
+ private final static Log log = LogFactory.getLog(ParameterRef.class);
+
+ private InstantiationManager instantiationManager;
+ private String name;
+
+ /** Cached object. */
+ private Object object;
+
+ public ParameterRef() {
+ }
+
+ /** @deprecated for backward compatibility with pre v0.11.4 approach. */
+ public ParameterRef(String name) {
+ this.name = name;
+ }
+
+ public Object getObject() throws Exception {
+ if (log.isTraceEnabled())
+ log.debug("Parameter ref called for " + name);
+
+ if (object == null)
+ object = instantiationManager.getInitializingFlowParameter(name);
+ return object;
+ }
+
+ public Class<?> getObjectType() {
+ if (object == null)
+ return instantiationManager.getInitializingFlowParameterClass(name);
+ else
+ return object.getClass();
+ }
+
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public void setInstantiationManager(
+ InstantiationManager instantiationManager) {
+ this.instantiationManager = instantiationManager;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
package org.argeo.slc.core.execution;
+import org.argeo.slc.SlcException;
public class PrimitiveSpecAttribute extends AbstractSpecAttribute implements
PrimitiveAccessor {
return type;
}
+ public Class<?> getTypeAsClass() {
+ return typeAsClass(type);
+ }
+
public void setType(String type) {
this.type = type;
+
+ // check whether type is recognized.
+ // TODO: make validation cleaner
+ typeAsClass(type);
+ }
+
+ public static Class<?> typeAsClass(String type) {
+ if (TYPE_STRING.equals(type))
+ return String.class;
+ else if (TYPE_INTEGER.equals(type))
+ return Integer.class;
+ else if (TYPE_LONG.equals(type))
+ return Long.class;
+ else if (TYPE_FLOAT.equals(type))
+ return Float.class;
+ else if (TYPE_DOUBLE.equals(type))
+ return Double.class;
+ else if (TYPE_BOOLEAN.equals(type))
+ return Boolean.class;
+ else
+ throw new SlcException("Unrecognized type " + type);
}
}
private Resource writeTo = null;
private Log log;
- private String message;
+ private Object message;
public void run() {
log().info(message);
File file = writeTo.getFile();
if (log().isDebugEnabled())
log().debug("Write to " + file);
- FileUtils.writeStringToFile(file, message);
+ if (message != null)
+ FileUtils.writeStringToFile(file, message.toString());
} catch (IOException e) {
throw new SlcException("Could not write to " + writeTo, e);
}
return log != null ? log : defaultLog;
}
- public void setMessage(String message) {
+ public void setMessage(Object message) {
this.message = message;
}
parent.getExpectedValues());\r
synchronize(parent, expectedValuesCommon);\r
if (log.isDebugEnabled())\r
- log.debug("Synchonized context " + parent);\r
+ log.debug("Synchronized context " + parent);\r
\r
}\r
\r
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
- <bean id="parameterRef" factory-bean="instantiationManager"
+ <bean id="parameterRef" class="org.argeo.slc.core.execution.ParameterRef"
+ abstract="true">
+ <property name="instantiationManager" ref="instantiationManager" />
+ </bean>
+ <!--
+ <bean id="parameterRef" factory-bean="instantiationManager"
factory-method="createRef" abstract="true" />
-
+ -->
</beans>
\ No newline at end of file
--- /dev/null
+package org.argeo.slc.core.execution;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.springframework.beans.factory.InitializingBean;
+
+public class ExceptionIfInitCalledTwice implements Runnable, InitializingBean {
+ private final static Log log = LogFactory
+ .getLog(ExceptionIfInitCalledTwice.class);
+
+ private Boolean calledOnce = false;
+
+ public void run() {
+ log.info(getClass().getSimpleName() + " ran properly");
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ log.info(getClass().getSimpleName() + " init method called");
+
+ if (calledOnce)
+ throw new SlcException(getClass().getSimpleName()
+ + "init method called twice.");
+ else
+ calledOnce = true;
+ }
+}
--- /dev/null
+package org.argeo.slc.core.execution;
+
+import org.argeo.slc.core.test.SimpleTestResult;
+import org.argeo.slc.execution.ExecutionFlow;
+import org.argeo.slc.test.TestStatus;
+import org.springframework.context.ConfigurableApplicationContext;
+
+public class ParameterRefTest extends AbstractExecutionFlowTestCase {
+ public void test001() throws Exception {
+ ConfigurableApplicationContext applicationContext = createApplicationContext("parameterRef.xml");
+ ((ExecutionFlow) applicationContext.getBean("parameterRef.001")).run();
+
+ SimpleTestResult res = (SimpleTestResult) applicationContext
+ .getBean("parameterRef.testResult");
+ assertEquals(res.getParts().get(0).getStatus(), TestStatus.PASSED);
+ assertEquals(res.getParts().get(1).getStatus(), TestStatus.FAILED);
+
+ applicationContext.close();
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">\r
+\r
+ <import resource="imports.xml" />\r
+\r
+ <!-- DEFINITIONS -->\r
+ <bean id="parameterRef.spec" parent="slcTemplate.simpleSpec">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="exceptionIfInitCalledTwice">\r
+ <bean parent="specAttr.ref"\r
+ p:targetClass="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testData2">\r
+ <bean parent="specAttr.ref" p:targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ p:isParameter="true" p:isFrozen="true" />\r
+ </entry>\r
+ <entry key="testedComponentId">\r
+ <bean parent="specAttr.primitive" p:value="100" p:isParameter="true"\r
+ p:type="integer" />\r
+ </entry>\r
+ </map>\r
+ </property>\r
+ </bean>\r
+\r
+ <bean id="parameterRef.flowTemplate" parent="slcTemplate.simpleFlow"\r
+ abstract="true">\r
+ <constructor-arg ref="parameterRef.spec" />\r
+ <property name="executables">\r
+ <list>\r
+ <!-- Primitive -->\r
+ <bean parent="task.echo" scope="execution">\r
+ <property name="message" value="testedComponentId=@{testedComponentId}" />\r
+ </bean>\r
+\r
+ <!-- Exception if init called twice -->\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="exceptionIfInitCalledTwice" />\r
+ </bean>\r
+ <bean parent="parameterRef">\r
+ <property name="name" value="exceptionIfInitCalledTwice" />\r
+ </bean>\r
+\r
+ <!-- Basic tests -->\r
+ <bean parent="parameterRef.testRun">\r
+ <property name="testData">\r
+ <bean parent="parameterRef">\r
+ <constructor-arg value="testData1" />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+ <bean parent="parameterRef.testRun">\r
+ <property name="testData" ref="ref1" />\r
+ </bean>\r
+ </list>\r
+ </property>\r
+ </bean>\r
+\r
+ <!-- TEST CASES -->\r
+ <bean id="parameterRef.001" parent="parameterRef.flowTemplate">\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="exceptionIfInitCalledTwice">\r
+ <bean class="org.argeo.slc.core.execution.ExceptionIfInitCalledTwice" />\r
+ </entry>\r
+ <entry key="testData1">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="toto" />\r
+ <property name="reached" value="toto" />\r
+ </bean>\r
+ </entry>\r
+ <entry key="testData2">\r
+ <bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <property name="expected" value="tata" />\r
+ <property name="reached" value="toto" />\r
+ </bean>\r
+ </entry>\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+\r
+ <!-- UTILITIES -->\r
+\r
+ <bean id="ref1" parent="parameterRef">\r
+ <constructor-arg value="testData2" />\r
+ </bean>\r
+\r
+ <bean id="parameterRef.testResult" class="org.argeo.slc.core.test.SimpleTestResult" />\r
+\r
+ <bean id="parameterRef.testRun" class="org.argeo.slc.core.test.SimpleTestRun"\r
+ abstract="true">\r
+ <property name="testResult" ref="parameterRef.testResult" />\r
+ <property name="testDefinition">\r
+ <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+ </property>\r
+ </bean>\r
+\r
+</beans>
\ No newline at end of file