001: /*
002: * Copyright 2002-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:
017: package org.springframework.web.jsf;
018:
019: import javax.faces.context.FacesContext;
020: import javax.faces.el.EvaluationException;
021: import javax.faces.el.VariableResolver;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: import org.springframework.beans.factory.BeanFactory;
027: import org.springframework.util.Assert;
028: import org.springframework.web.context.WebApplicationContext;
029:
030: /**
031: * JSF 1.1 <code>VariableResolver</code> that first delegates to the Spring
032: * root <code>WebApplicationContext</code>, then to the original resolver
033: * of the underlying JSF implementation.
034: *
035: * <p>Configure this resolver in your <code>faces-config.xml</code> file as follows:
036: *
037: * <pre>
038: * <application>
039: * ...
040: * <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
041: * </application></pre>
042: *
043: * All your JSF expressions can then implicitly refer to the names of
044: * Spring-managed service layer beans, for example in property values of
045: * JSF-managed beans:
046: *
047: * <pre>
048: * <managed-bean>
049: * <managed-bean-name>myJsfManagedBean</managed-bean-name>
050: * <managed-bean-class>example.MyJsfManagedBean</managed-bean-class>
051: * <managed-bean-scope>session</managed-bean-scope>
052: * <managed-property>
053: * <property-name>mySpringManagedBusinessObject</property-name>
054: * <value>#{mySpringManagedBusinessObject}</value>
055: * </managed-property>
056: * </managed-bean></pre>
057: *
058: * with "mySpringManagedBusinessObject" defined as Spring bean in
059: * applicationContext.xml:
060: *
061: * <pre>
062: * <bean id="mySpringManagedBusinessObject" class="example.MySpringManagedBusinessObject">
063: * ...
064: * </bean></pre>
065: *
066: * @author Juergen Hoeller
067: * @since 1.1
068: * @see WebApplicationContextVariableResolver
069: * @see FacesContextUtils#getRequiredWebApplicationContext
070: */
071: public class DelegatingVariableResolver extends VariableResolver {
072:
073: /** Logger available to subclasses */
074: protected final Log logger = LogFactory.getLog(getClass());
075:
076: protected final VariableResolver originalVariableResolver;
077:
078: /**
079: * Create a new DelegatingVariableResolver, using the given original VariableResolver.
080: * <p>A JSF implementation will automatically pass its original resolver into the
081: * constructor of a configured resolver, provided that there is a corresponding
082: * constructor argument.
083: * @param originalVariableResolver the original VariableResolver
084: */
085: public DelegatingVariableResolver(
086: VariableResolver originalVariableResolver) {
087: Assert.notNull(originalVariableResolver,
088: "Original JSF VariableResolver must not be null");
089: this .originalVariableResolver = originalVariableResolver;
090: }
091:
092: /**
093: * Return the original JSF VariableResolver that this resolver delegates to.
094: * Used to resolve standard JSF-managed beans.
095: */
096: protected final VariableResolver getOriginalVariableResolver() {
097: return this .originalVariableResolver;
098: }
099:
100: /**
101: * Delegate to the original VariableResolver first, then try to
102: * resolve the variable as Spring bean in the root WebApplicationContext.
103: */
104: public Object resolveVariable(FacesContext facesContext, String name)
105: throws EvaluationException {
106: Object value = resolveOriginal(facesContext, name);
107: if (value != null) {
108: return value;
109: }
110: Object bean = resolveSpringBean(facesContext, name);
111: if (bean != null) {
112: return bean;
113: }
114: return null;
115: }
116:
117: /**
118: * Resolve the attribute via the original JSF VariableResolver.
119: */
120: protected Object resolveOriginal(FacesContext facesContext,
121: String name) {
122: if (logger.isTraceEnabled()) {
123: logger.trace("Attempting to resolve variable '" + name
124: + "' via original VariableResolver");
125: }
126: Object value = getOriginalVariableResolver().resolveVariable(
127: facesContext, name);
128: if (value != null && logger.isDebugEnabled()) {
129: logger.debug("Successfully resolved variable '" + name
130: + "' via original VariableResolver");
131: }
132: return value;
133: }
134:
135: /**
136: * Resolve the attribute as a Spring bean in the ApplicationContext.
137: */
138: protected Object resolveSpringBean(FacesContext facesContext,
139: String name) {
140: if (logger.isTraceEnabled()) {
141: logger.trace("Attempting to resolve variable '" + name
142: + "' in Spring ApplicationContext");
143: }
144: BeanFactory bf = getBeanFactory(facesContext);
145: if (bf.containsBean(name)) {
146: if (logger.isDebugEnabled()) {
147: logger.debug("Successfully resolved variable '" + name
148: + "' in Spring ApplicationContext");
149: }
150: return bf.getBean(name);
151: } else {
152: return null;
153: }
154: }
155:
156: /**
157: * Retrieve the Spring BeanFactory to delegate bean name resolution to.
158: * <p>The default implementation delegates to <code>getWebApplicationContext</code>.
159: * Can be overridden to provide an arbitrary BeanFactory reference to resolve
160: * against; usually, this will be a full Spring ApplicationContext.
161: * @param facesContext the current JSF context
162: * @return the Spring BeanFactory (never <code>null</code>)
163: * @see #getWebApplicationContext
164: */
165: protected BeanFactory getBeanFactory(FacesContext facesContext) {
166: return getWebApplicationContext(facesContext);
167: }
168:
169: /**
170: * Retrieve the web application context to delegate bean name resolution to.
171: * <p>The default implementation delegates to FacesContextUtils.
172: * @param facesContext the current JSF context
173: * @return the Spring web application context (never <code>null</code>)
174: * @see FacesContextUtils#getRequiredWebApplicationContext
175: */
176: protected WebApplicationContext getWebApplicationContext(
177: FacesContext facesContext) {
178: return FacesContextUtils
179: .getRequiredWebApplicationContext(facesContext);
180: }
181:
182: }
|