View Javadoc
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.execution.ExecutionContext;
21  import org.argeo.slc.execution.ExecutionFlow;
22  import org.argeo.slc.execution.ExecutionStack;
23  import org.aspectj.lang.ProceedingJoinPoint;
24  import org.aspectj.lang.annotation.Around;
25  import org.aspectj.lang.annotation.Aspect;
26  import org.aspectj.lang.annotation.Pointcut;
27  
28  @Aspect
29  /** Aspect intercepting calls on execution flows and contexts. */
30  public class ExecutionAspect {
31  	private final static Log log = LogFactory.getLog(ExecutionAspect.class);
32  
33  	private ExecutionStack executionStack;
34  	private ExecutionContext executionContext;
35  
36  	@Around("flowExecution()")
37  	public void aroundFlow(ProceedingJoinPoint pjp) throws Throwable {
38  		// IMPORTANT: Make sure that the execution context is called before the
39  		// execution stack
40  		executionContext.getUuid();
41  
42  		ExecutionFlow executionFlow = (ExecutionFlow) pjp.getTarget();
43  		executionStack.enterFlow(executionFlow);
44  		executionContext.setVariable(ExecutionContext.VAR_FLOW_ID,
45  				executionStack.getCurrentStackLevelUuid());
46  		executionContext.setVariable(ExecutionContext.VAR_FLOW_NAME,
47  				executionFlow.getName());
48  
49  		logStackEvent("=> ", executionFlow);
50  		try {
51  			// Actually execute the flow
52  			pjp.proceed();
53  		} finally {
54  			logStackEvent("<= ", executionFlow);
55  			executionStack.leaveFlow(executionFlow);
56  		}
57  	}
58  
59  	@Around("getVariable()")
60  	public Object aroundGetVariable(ProceedingJoinPoint pjp) throws Throwable {
61  		Object obj = pjp.proceed();
62  		// if the variable was not found, look in the stack starting at the
63  		// upper flows
64  		if (obj == null) {
65  			String key = pjp.getArgs()[0].toString();
66  			obj = executionStack.findLocalVariable(key);
67  		}
68  		return obj;
69  	}
70  
71  	@Pointcut("execution(void org.argeo.slc.execution.ExecutionFlow.run())")
72  	public void flowExecution() {
73  	}
74  
75  	@Pointcut("execution(* org.argeo.slc.execution.ExecutionContext.getVariable(..))")
76  	public void getVariable() {
77  	}
78  
79  	public void setExecutionStack(ExecutionStack executionStack) {
80  		this.executionStack = executionStack;
81  	}
82  
83  	public void setExecutionContext(ExecutionContext executionContext) {
84  		this.executionContext = executionContext;
85  	}
86  
87  	protected void logStackEvent(String symbol, ExecutionFlow executionFlow) {
88  		Integer stackSize = executionStack.getStackSize();
89  		if (log.isTraceEnabled())
90  			log.debug(depthSpaces(stackSize) + symbol + executionFlow + " #"
91  					+ executionStack.getCurrentStackLevelUuid() + ", depth="
92  					+ stackSize);
93  		if (log.isDebugEnabled())
94  			log.debug(depthSpaces(stackSize) + symbol + executionFlow);
95  	}
96  
97  	protected void logRunnableExecution(ExecutionFlow executionFlow,
98  			Runnable runnable) {
99  		Integer stackSize = executionStack.getStackSize();
100 		if (log.isDebugEnabled())
101 			log.debug(depthSpaces(stackSize + 1)
102 					+ runnable.getClass().getSimpleName() + " in "
103 					+ executionFlow);
104 	}
105 
106 	private String depthSpaces(int depth) {
107 		StringBuffer buf = new StringBuffer(depth * 2);
108 		for (int i = 0; i < depth; i++)
109 			buf.append("  ");
110 		return buf.toString();
111 	}
112 
113 }