01: /*
02: * Copyright 2004-2007 the original author or authors.
03: *
04: * Licensed under the Apache License, Version 2.0 (the "License");
05: * you may not use this file except in compliance with the License.
06: * You may obtain a copy of the License at
07: *
08: * http://www.apache.org/licenses/LICENSE-2.0
09: *
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.springframework.webflow.executor.jsf;
17:
18: import javax.faces.context.FacesContext;
19: import javax.faces.el.EvaluationException;
20: import javax.faces.el.VariableResolver;
21:
22: import org.springframework.web.jsf.DelegatingVariableResolver;
23: import org.springframework.webflow.execution.FlowExecution;
24:
25: /**
26: * Custom variable resolver that searches the current flow execution for variables to resolve. The search algorithm
27: * looks in flash scope first, then flow scope, then conversation scope. If no variable is found this resolver delegates
28: * to the next resolver in the chain.
29: *
30: * Suitable for use along side other variable resolvers to support EL binding expressions like {#bean.property} where
31: * "bean" could be a property in any supported scope.
32: *
33: * Consider combining use of this class with a Spring {@link DelegatingVariableResolver} to also support
34: * lazy-initialized binding variables managed by a Spring application context using custom bean scopes. Also consider
35: * such a Spring-backed managed bean facility as the sole-provider for centralized JSF managed bean references.
36: *
37: * @author Keith Donald
38: */
39: public class DelegatingFlowVariableResolver extends VariableResolver {
40:
41: /**
42: * The standard variable resolver to delegate to if this one doesn't apply.
43: */
44: private VariableResolver resolverDelegate;
45:
46: /**
47: * Create a new FlowExecutionVariableResolver, using the given original VariableResolver.
48: * <p>
49: * A JSF implementation will automatically pass its original resolver into the constructor of a configured resolver,
50: * provided that there is a corresponding constructor argument.
51: *
52: * @param resolverDelegate the original VariableResolver
53: */
54: public DelegatingFlowVariableResolver(
55: VariableResolver resolverDelegate) {
56: this .resolverDelegate = resolverDelegate;
57: }
58:
59: /**
60: * Return the original VariableResolver that this resolver delegates to.
61: */
62: protected final VariableResolver getResolverDelegate() {
63: return resolverDelegate;
64: }
65:
66: public Object resolveVariable(FacesContext context, String name)
67: throws EvaluationException {
68: FlowExecution execution = FlowExecutionHolderUtils
69: .getCurrentFlowExecution(context);
70: if (execution != null) {
71: if (execution.isActive()) {
72: // flow execution is active: try flash/flow/conversation scope
73: if (execution.getActiveSession().getFlashMap()
74: .contains(name)) {
75: return execution.getActiveSession().getFlashMap()
76: .get(name);
77: } else if (execution.getActiveSession().getScope()
78: .contains(name)) {
79: return execution.getActiveSession().getScope().get(
80: name);
81: } else if (execution.getConversationScope().contains(
82: name)) {
83: return execution.getConversationScope().get(name);
84: }
85: } else {
86: // flow execution has ended: check for end-state attributes exposed in the request map
87: if (context.getExternalContext().getRequestMap()
88: .containsKey(name)) {
89: return context.getExternalContext().getRequestMap()
90: .get(name);
91: }
92: }
93: }
94: // no flow execution bound or flow execution attribute found with that name - delegate
95: return resolverDelegate.resolveVariable(context, name);
96: }
97: }
|