From: Mathieu Baudier Date: Wed, 18 Feb 2009 13:55:17 +0000 (+0000) Subject: Introduce aspects and execution parameters X-Git-Tag: argeo-slc-2.1.7~2145 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;ds=sidebyside;h=5ae68ecbb5176b7924d279cd8d96a0b650abcf2c;p=gpl%2Fargeo-slc.git Introduce aspects and execution parameters git-svn-id: https://svn.argeo.org/slc/trunk@2154 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/sandbox/argeo.slc.executionflow/pom.xml b/sandbox/argeo.slc.executionflow/pom.xml index 6a9248839..1025a48ce 100644 --- a/sandbox/argeo.slc.executionflow/pom.xml +++ b/sandbox/argeo.slc.executionflow/pom.xml @@ -27,6 +27,16 @@ org.argeo.slc.support.simple + + org.aspectj + com.springsource.org.aspectj.runtime + 1.6.2.RELEASE + + + org.aspectj + com.springsource.org.aspectj.weaver + 1.6.2.RELEASE + org.codehaus.groovy com.springsource.org.codehaus.groovy diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionAspect.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionAspect.java new file mode 100644 index 000000000..6d3257e83 --- /dev/null +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionAspect.java @@ -0,0 +1,48 @@ +package org.argeo.slc.executionflow; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; + +@Aspect +public class ExecutionAspect { + private static Log log = LogFactory.getLog(ExecutionAspect.class); + + // @Around("execution(void org.argeo.slc.executionflow.ExecutionFlow.execute()) && target(org.argeo.slc.executionflow.ExecutionFlow)") + public void registerFlow(ProceedingJoinPoint pjp) throws Throwable { + try { + log.debug("registerFlow " + pjp.getTarget().getClass()); + ExecutionContext.enterFlow((ExecutionFlow) pjp.getTarget()); + pjp.proceed(); + } finally { + ExecutionContext.leaveFlow((ExecutionFlow) pjp.getTarget()); + } + } + + @Before("flowExecution()") + public void beforeFlow(JoinPoint jp) throws Throwable { + //log.debug("this " + jp.getThis().getClass()); + //log.debug("target " + jp.getTarget().getClass()); + // Thread.dumpStack(); + ExecutionFlow executionFlow = (ExecutionFlow) jp.getTarget(); + ExecutionContext.enterFlow(executionFlow); + } + + @After("flowExecution()") + public void afterFlow(JoinPoint jp) throws Throwable { + //log.debug("this " + jp.getThis().getClass()); + //log.debug("target " + jp.getTarget().getClass()); + ExecutionFlow executionFlow = (ExecutionFlow) jp.getTarget(); + ExecutionContext.leaveFlow(executionFlow); + } + + @Pointcut("execution(void org.argeo.slc.executionflow.ExecutionFlow.execute())") + public void flowExecution() { + } +} diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionContext.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionContext.java new file mode 100644 index 000000000..ed411520c --- /dev/null +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionContext.java @@ -0,0 +1,44 @@ +package org.argeo.slc.executionflow; + +import java.util.Stack; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; + +public class ExecutionContext { + private final static Log log = LogFactory.getLog(ExecutionContext.class); + + private final static ThreadLocal executionContext = new ThreadLocal(); + + private final Stack stack = new Stack(); + + public static ExecutionFlow getCurrentFlow() { + if (executionContext.get() == null) + return null; + return executionContext.get().stack.peek(); + } + + public static void enterFlow(ExecutionFlow executionFlow) { + if (executionContext.get() == null) { + // TODO: deal with parallell flows + executionContext.set(new ExecutionContext()); + } + Stack stack = executionContext.get().stack; + stack.push(executionFlow); + if (log.isDebugEnabled()) + log.debug("Depth: " + stack.size() + ". Enter " + executionFlow); + } + + public static void leaveFlow(ExecutionFlow executionFlow) { + Stack stack = executionContext.get().stack; + if (log.isDebugEnabled()) + log.debug("Depth: " + stack.size() + ". Leave " + executionFlow); + ExecutionFlow leftEf = stack.pop(); + leftEf.getScopedObjects().clear(); + if (!leftEf.getUuid().equals(executionFlow.getUuid())) { + throw new SlcException("Asked to leave " + executionFlow + + " but last is " + leftEf); + } + } +} diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFlow.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFlow.java index 652218471..0d4ae934e 100644 --- a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFlow.java +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionFlow.java @@ -6,5 +6,7 @@ import org.argeo.slc.process.Executable; public interface ExecutionFlow extends Executable{ public Map getAttributes(); + public ExecutionSpec getExecutionSpec(); public String getUuid(); + public Map getScopedObjects(); } diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionParameterPostProcessor.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionParameterPostProcessor.java new file mode 100644 index 000000000..adeddaafb --- /dev/null +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionParameterPostProcessor.java @@ -0,0 +1,104 @@ +package org.argeo.slc.executionflow; + +import java.beans.PropertyDescriptor; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import org.springframework.beans.factory.config.TypedStringValue; + +public class ExecutionParameterPostProcessor extends + InstantiationAwareBeanPostProcessorAdapter { + private final static Log log = LogFactory + .getLog(ExecutionParameterPostProcessor.class); + + private String placeholderPrefix = "@{"; + private String placeholderSuffix = "}"; + private String nullValue; + + @Override + public PropertyValues postProcessPropertyValues(PropertyValues pvs, + PropertyDescriptor[] pds, Object bean, String beanName) + throws BeansException { + ExecutionFlow currentFlow = ExecutionContext.getCurrentFlow(); + if (currentFlow == null) + return pvs; + + Properties props = new Properties(); + Map attributes = currentFlow.getAttributes(); + Map specAttributes = currentFlow + .getExecutionSpec().getAttributes(); + + for (String key : specAttributes.keySet()) { + ExecutionSpecAttribute obj = specAttributes.get(key); + if (!(obj instanceof RefSpecAttribute)) { + if (!attributes.containsKey(key)) + throw new SlcException("Specified attribute " + key + + " is not set in " + currentFlow); + + props.setProperty(key, attributes.get(key).toString()); +// if (log.isTraceEnabled()) +// log.trace("Use attribute " + key); + } + } + CustomPpc ppc = new CustomPpc(props); + + for (PropertyValue pv : pvs.getPropertyValues()) { + if (pv.getValue() instanceof TypedStringValue) { + TypedStringValue tsv = (TypedStringValue) pv.getValue(); + String originalValue = tsv.getValue(); + String convertedValue = ppc.process(originalValue); + tsv.setValue(convertedValue); + if (log.isTraceEnabled()) { + if (!originalValue.equals(convertedValue)) + log.trace("Converted " + beanName + "[" + pv.getName() + + "]: " + originalValue + " to " + + convertedValue); + } + } else { +// if (log.isTraceEnabled()) +// log.trace(beanName + "[" + pv.getName() + "]: " +// + pv.getValue().getClass()); + } + } + + return pvs; + } + + public void setPlaceholderPrefix(String placeholderPrefix) { + this.placeholderPrefix = placeholderPrefix; + } + + public void setPlaceholderSuffix(String placeholderSuffix) { + this.placeholderSuffix = placeholderSuffix; + } + + public void setNullValue(String nullValue) { + this.nullValue = nullValue; + } + + private class CustomPpc extends PropertyPlaceholderConfigurer { + private final Properties props; + + public CustomPpc(Properties props) { + super(); + this.props = props; + setPlaceholderPrefix(placeholderPrefix); + setPlaceholderSuffix(placeholderSuffix); + setSystemPropertiesMode(SYSTEM_PROPERTIES_MODE_NEVER); + } + + public String process(String strVal) { + String value = parseStringValue(strVal, this.props, new HashSet()); + return (value.equals(nullValue) ? null : value); + } + } +} diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionScope.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionScope.java index 46d5d19f7..e60874435 100644 --- a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionScope.java +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionScope.java @@ -7,28 +7,46 @@ import org.springframework.beans.factory.config.Scope; public class ExecutionScope implements Scope { private final static Log log = LogFactory.getLog(ExecutionScope.class); - + public Object get(String name, ObjectFactory objectFactory) { - log.info("Getting bean "+name); - ExecutionFlow executionFlow = SimpleExecutionFlow.getCurrentExecutionFlow(); - Object obj = executionFlow.getAttributes().get(name); - log.info("Scoped object "+obj); + + if (log.isTraceEnabled()) + log.info("Getting scoped bean " + name); + ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow(); + // returns cached instance + if (executionFlow.getScopedObjects().containsKey(name)) { + Object obj = executionFlow.getScopedObjects().get(name); + if (log.isTraceEnabled()) + log.info("Return cached scoped object " + obj); + return obj; + } + // creates instance + Object obj = objectFactory.getObject(); + if (obj instanceof ExecutionFlow) { + // add to itself (it is not yet the current flow) + ((ExecutionFlow) obj).getScopedObjects().put(name, obj); + if (log.isTraceEnabled()) + log.info("Cached flow object " + obj + " in itself"); + } else { + executionFlow.getScopedObjects().put(name, obj); + if (log.isTraceEnabled()) + log.info("Created regular scoped object " + obj); + } return obj; } public String getConversationId() { - ExecutionFlow executionFlow = SimpleExecutionFlow.getCurrentExecutionFlow(); + ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow(); return executionFlow.getUuid(); } public void registerDestructionCallback(String name, Runnable callback) { - // TODO Auto-generated method stub - + throw new UnsupportedOperationException(); } public Object remove(String name) { - // TODO Auto-generated method stub - return null; + log.debug("Remove object " + name); + throw new UnsupportedOperationException(); } } diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionTargetSource.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionTargetSource.java index 51bdf250f..3b0153787 100644 --- a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionTargetSource.java +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/ExecutionTargetSource.java @@ -14,8 +14,7 @@ public class ExecutionTargetSource implements TargetSource { public Object getTarget() throws Exception { if (log.isTraceEnabled()) log.trace("Getting object " + name); - ExecutionFlow executionFlow = SimpleExecutionFlow - .getCurrentExecutionFlow(); + ExecutionFlow executionFlow = ExecutionContext.getCurrentFlow(); Object obj = executionFlow.getAttributes().get(name); if (log.isTraceEnabled()) log.trace("Target object " + obj); diff --git a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionFlow.java b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionFlow.java index 952bce0de..747fa1652 100644 --- a/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionFlow.java +++ b/sandbox/argeo.slc.executionflow/src/main/java/org/argeo/slc/executionflow/SimpleExecutionFlow.java @@ -10,26 +10,31 @@ import org.apache.commons.lang.math.RandomUtils; import org.argeo.slc.SlcException; import org.argeo.slc.process.Executable; import org.argeo.slc.test.ExecutableTestRun; +import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.validation.MapBindingResult; -public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean { - private static ThreadLocal executionFlow = new ThreadLocal(); +public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean, + BeanNameAware { + // private static ThreadLocal executionFlow = new + // ThreadLocal(); - private ExecutionSpec executionSpec; + private ExecutionSpec executionSpec = new SimpleExecutionSpec(); + private String name = null; private Map attributes = new HashMap(); + private Map scopedObjects = new HashMap(); private List executables = new ArrayList(); private final String uuid = UUID.randomUUID().toString(); public void execute() { try { - executionFlow.set(this); + // ExecutionContext.enterFlow(this); for (Executable executable : executables) { executable.execute(); } } finally { - executionFlow.set(null); + // ExecutionContext.leaveFlow(this); } } @@ -67,6 +72,10 @@ public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean { + errors.toString()); } + public void setBeanName(String name) { + this.name = name; + } + public void setExecutables(List executables) { this.executables = executables; } @@ -79,10 +88,6 @@ public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean { this.attributes = attributes; } - public static ExecutionFlow getCurrentExecutionFlow() { - return executionFlow.get(); - } - public Map getAttributes() { return attributes; } @@ -91,4 +96,16 @@ public class SimpleExecutionFlow implements ExecutionFlow, InitializingBean { return uuid; } + public Map getScopedObjects() { + return scopedObjects; + } + + public ExecutionSpec getExecutionSpec() { + return executionSpec; + } + + public String toString() { + return new StringBuffer("Flow ").append(name).append(" [#") + .append(uuid).append(']').toString(); + } } diff --git a/sandbox/argeo.slc.executionflow/src/slc/conf/basic.xml b/sandbox/argeo.slc.executionflow/src/slc/conf/basic.xml index 82e71d15a..19e9735af 100644 --- a/sandbox/argeo.slc.executionflow/src/slc/conf/basic.xml +++ b/sandbox/argeo.slc.executionflow/src/slc/conf/basic.xml @@ -1,9 +1,11 @@ + http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> @@ -54,9 +56,6 @@ - - --> - - - \ No newline at end of file diff --git a/sandbox/argeo.slc.executionflow/src/slc/conf/common.xml b/sandbox/argeo.slc.executionflow/src/slc/conf/common.xml index 80f54b562..44c84b5a1 100644 --- a/sandbox/argeo.slc.executionflow/src/slc/conf/common.xml +++ b/sandbox/argeo.slc.executionflow/src/slc/conf/common.xml @@ -1,9 +1,11 @@ + http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> diff --git a/sandbox/argeo.slc.executionflow/src/slc/conf/main.xml b/sandbox/argeo.slc.executionflow/src/slc/conf/main.xml index 4d43965c5..e2c8dbea0 100644 --- a/sandbox/argeo.slc.executionflow/src/slc/conf/main.xml +++ b/sandbox/argeo.slc.executionflow/src/slc/conf/main.xml @@ -1,11 +1,11 @@ + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> @@ -13,9 +13,28 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sandbox/argeo.slc.executionflow/src/slc/conf/slc.properties b/sandbox/argeo.slc.executionflow/src/slc/conf/slc.properties index 7cce428ea..23475a1cd 100644 --- a/sandbox/argeo.slc.executionflow/src/slc/conf/slc.properties +++ b/sandbox/argeo.slc.executionflow/src/slc/conf/slc.properties @@ -2,6 +2,7 @@ log4j.rootLogger=WARN, console ## Levels log4j.logger.org.argeo=DEBUG +log4j.logger.org.argeo.slc.executionflow.ExecutionParameterPostProcessor=TRACE ## Appenders # console is set to be a ConsoleAppender. diff --git a/sandbox/argeo.slc.executionflow/src/slc/conf/testCases/basic-001.xml b/sandbox/argeo.slc.executionflow/src/slc/conf/testCases/basic-001.xml index 494f9789d..c35361bdb 100644 --- a/sandbox/argeo.slc.executionflow/src/slc/conf/testCases/basic-001.xml +++ b/sandbox/argeo.slc.executionflow/src/slc/conf/testCases/basic-001.xml @@ -1,14 +1,19 @@ + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.5.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> - + + - + @@ -19,9 +24,11 @@ - - - + + + +