001: /*
002: * Copyright 2004-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.springframework.webflow.executor.jsf;
017:
018: import javax.faces.context.FacesContext;
019: import javax.faces.el.PropertyResolver;
020:
021: import org.springframework.beans.factory.BeanFactory;
022: import org.springframework.util.Assert;
023: import org.springframework.web.context.WebApplicationContext;
024: import org.springframework.web.jsf.DelegatingVariableResolver;
025: import org.springframework.web.jsf.FacesContextUtils;
026: import org.springframework.webflow.execution.FlowExecution;
027:
028: /**
029: * Custom property resolver that resolves flow session scope attributes of the current flow execution. This resolver
030: * will also create and set the attribute value to a bean from the root Spring Web Application Context if the value does
031: * not already exist, allowing for lazy-initialized binding variables.
032: *
033: * Designed mainly to be used with the {@link FlowVariableResolver}. This is the original property resolver implemented
034: * with Spring Web Flow 1.0. In general, prefer {@link DelegatingFlowVariableResolver} or
035: * {@link FlowExecutionVariableResolver} over use of this class. Also, consider use of the
036: * {@link DelegatingVariableResolver} as an alternative to accessing lazy-initialized binding variables managed by a
037: * Spring application context that uses custom bean scopes.
038: *
039: * @author Colin Sampaleanu
040: * @author Keith Donald
041: */
042: public class FlowPropertyResolver extends
043: AbstractFlowExecutionPropertyResolver {
044:
045: /**
046: * Creates a new flow execution property resolver that resolves flow scope attributes.
047: * @param resolverDelegate the resolver to delegate to when the property is not a flow execution attribute
048: */
049: public FlowPropertyResolver(PropertyResolver resolverDelegate) {
050: super (resolverDelegate);
051: }
052:
053: protected Class doGetAttributeType(FlowExecution execution,
054: String attributeName) {
055: // we want to access flow scope of the active session (conversation)
056: Object value = execution.getActiveSession().getScope().get(
057: attributeName);
058: // note that MyFaces returns Object.class for a null value here, but
059: // as I read the JSF spec, null should be returned when the object
060: // type can not be determined this certainly seems to be the case
061: // for a map value which doesn' even exist
062: return (value == null) ? null : value.getClass();
063: }
064:
065: protected Object doGetAttribute(FlowExecution execution,
066: String attributeName) {
067: Object value = execution.getActiveSession().getScope().get(
068: attributeName);
069: if (value == null) {
070: FacesContext facesContext = FacesContext
071: .getCurrentInstance();
072: Assert
073: .notNull(facesContext,
074: "The current FacesContext must be present during property resolution stage");
075: BeanFactory beanFactory = getWebApplicationContext(facesContext);
076: if (beanFactory.containsBean(attributeName)) {
077: // note: this resolver doesn't care, but this should be
078: // a stateless bean with singleton scope or a stateful bean with prototype scope
079: value = beanFactory.getBean(attributeName);
080: execution.getActiveSession().getScope().put(
081: attributeName, value);
082: }
083: }
084: return value;
085: }
086:
087: protected void doSetAttribute(FlowExecution execution,
088: String attributeName, Object attributeValue) {
089: execution.getActiveSession().getScope().put(attributeName,
090: attributeValue);
091: }
092:
093: /**
094: * Retrieve the web application context to delegate bean name resolution to. Default implementation delegates to
095: * FacesContextUtils.
096: * @param facesContext the current JSF context
097: * @return the Spring web application context (never <code>null</code>)
098: * @see FacesContextUtils#getRequiredWebApplicationContext
099: */
100: protected WebApplicationContext getWebApplicationContext(
101: FacesContext facesContext) {
102: return FacesContextUtils
103: .getRequiredWebApplicationContext(facesContext);
104: }
105: }
|