GRAILS-1019: Allowing expressions to be used with the 'disabled' attribute for g...
[grails.git] / src / web / org / codehaus / groovy / grails / webflow / executor / GrailsFlowExecutor.java
blobabb34365d143dc4e9232562ff0f1d7a1faf29f46
1 /* Copyright 2006-2007 Graeme Rocher
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 package org.codehaus.groovy.grails.webflow.executor;
17 import org.springframework.webflow.executor.FlowExecutorImpl;
18 import org.springframework.webflow.executor.ResponseInstruction;
19 import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
20 import org.springframework.webflow.definition.FlowDefinition;
21 import org.springframework.webflow.execution.FlowExecutionFactory;
22 import org.springframework.webflow.execution.FlowExecution;
23 import org.springframework.webflow.execution.ViewSelection;
24 import org.springframework.webflow.execution.FlowExecutionContextHolder;
25 import org.springframework.webflow.execution.repository.FlowExecutionRepository;
26 import org.springframework.webflow.execution.repository.FlowExecutionKey;
27 import org.springframework.webflow.execution.repository.FlowExecutionLock;
28 import org.springframework.webflow.context.ExternalContext;
29 import org.springframework.webflow.context.ExternalContextHolder;
30 import org.springframework.webflow.core.FlowException;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
34 /**
35 * Class description here.
37 * @author Graeme Rocher
38 * @since 0.4
39 * <p/>
40 * Created: Jul 20, 2007
41 * Time: 5:46:45 PM
43 public class GrailsFlowExecutor extends FlowExecutorImpl {
45 private static final Log logger = LogFactory.getLog(FlowExecutorImpl.class);
46 /**
47 * Create a new flow executor.
49 * @param definitionLocator the locator for accessing flow definitions to
50 * execute
51 * @param executionFactory the factory for creating executions of flow
52 * definitions
53 * @param executionRepository the repository for persisting paused flow
54 * executions
56 public GrailsFlowExecutor(FlowDefinitionLocator definitionLocator, FlowExecutionFactory executionFactory, FlowExecutionRepository executionRepository) {
57 super(definitionLocator, executionFactory, executionRepository);
60 public ResponseInstruction launch(String flowDefinitionId, ExternalContext context) throws FlowException {
61 if (logger.isDebugEnabled()) {
62 logger.debug("Launching flow execution for flow definition '" + flowDefinitionId + "'");
64 // expose external context as a thread-bound service
65 ExternalContextHolder.setExternalContext(context);
66 try {
67 FlowDefinition flowDefinition = getDefinitionLocator().getFlowDefinition(flowDefinitionId);
68 FlowExecution flowExecution = getExecutionFactory().createFlowExecution(flowDefinition);
69 FlowExecutionContextHolder.setFlowExecutionContext(flowExecution);
70 ViewSelection selectedView = flowExecution.start(createInput(context), context);
71 if (flowExecution.isActive()) {
72 // execution still active => store it in the repository
73 final FlowExecutionRepository executionRepository = getExecutionRepository();
74 FlowExecutionKey key = executionRepository.generateKey(flowExecution);
75 FlowExecutionLock lock = executionRepository.getLock(key);
76 lock.lock();
77 try {
78 executionRepository.putFlowExecution(key, flowExecution);
80 finally {
81 lock.unlock();
83 return new ResponseInstruction(key.toString(), flowExecution, selectedView);
85 else {
86 // execution already ended => just render the selected view
87 return new ResponseInstruction(flowExecution, selectedView);
90 finally {
91 cleanUpAfterFlowExecution();
95 private void cleanUpAfterFlowExecution() {
96 FlowExecutionContextHolder.setFlowExecutionContext(null);
97 ExternalContextHolder.setExternalContext(null);
100 public ResponseInstruction resume(String flowExecutionKey, String eventId, ExternalContext context) throws FlowException {
101 if (logger.isDebugEnabled()) {
102 logger.debug("Resuming flow execution with key '" + flowExecutionKey +
103 "' on user event '" + eventId + "'");
105 // expose external context as a thread-bound service
106 ExternalContextHolder.setExternalContext(context);
107 try {
108 final FlowExecutionRepository executionRepository = getExecutionRepository();
109 FlowExecutionKey key = executionRepository.parseFlowExecutionKey(flowExecutionKey);
110 FlowExecutionLock lock = executionRepository.getLock(key);
111 // make sure we're the only one manipulating the flow execution
112 lock.lock();
113 try {
114 FlowExecution flowExecution = executionRepository.getFlowExecution(key);
115 FlowExecutionContextHolder.setFlowExecutionContext(flowExecution);
116 ViewSelection selectedView = flowExecution.signalEvent(eventId, context);
117 if (flowExecution.isActive()) {
118 // execution still active => store it in the repository
119 key = executionRepository.getNextKey(flowExecution, key);
120 executionRepository.putFlowExecution(key, flowExecution);
121 return new ResponseInstruction(key.toString(), flowExecution, selectedView);
123 else {
124 // execution ended => remove it from the repository
125 executionRepository.removeFlowExecution(key);
126 return new ResponseInstruction(flowExecution, selectedView);
129 finally {
130 lock.unlock();
133 finally {
134 cleanUpAfterFlowExecution();
139 public ResponseInstruction refresh(String flowExecutionKey, ExternalContext context) throws FlowException {
140 if (logger.isDebugEnabled()) {
141 logger.debug("Refreshing flow execution with key '" + flowExecutionKey + "'");
143 // expose external context as a thread-bound service
144 ExternalContextHolder.setExternalContext(context);
145 try {
146 final FlowExecutionRepository executionRepository = getExecutionRepository();
147 FlowExecutionKey key = executionRepository.parseFlowExecutionKey(flowExecutionKey);
148 FlowExecutionLock lock = executionRepository.getLock(key);
149 // make sure we're the only one manipulating the flow execution
150 lock.lock();
151 try {
152 FlowExecution flowExecution = executionRepository.getFlowExecution(key);
153 FlowExecutionContextHolder.setFlowExecutionContext(flowExecution);
154 ViewSelection selectedView = flowExecution.refresh(context);
155 // don't generate a new key for a refresh, just update
156 // the flow execution with it's existing key
157 executionRepository.putFlowExecution(key, flowExecution);
158 return new ResponseInstruction(key.toString(), flowExecution, selectedView);
160 finally {
161 lock.unlock();
164 finally {
165 cleanUpAfterFlowExecution();