001: /*
002: * Copyright 2002-2006 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.application.NavigationHandler;
020: import javax.faces.context.FacesContext;
021:
022: import org.springframework.beans.factory.BeanFactory;
023: import org.springframework.web.context.WebApplicationContext;
024:
025: /**
026: * JSF NavigationHandler implementation that delegates to a NavigationHandler
027: * bean obtained from the Spring root WebApplicationContext.
028: *
029: * <p>Configure this handler proxy in your <code>faces-config.xml</code> file
030: * as follows:
031: *
032: * <pre>
033: * <application>
034: * ...
035: * <navigation-handler>
036: * org.springframework.web.jsf.DelegatingNavigationHandlerProxy
037: * </navigation-handler>
038: * ...
039: * </application></pre>
040: *
041: * By default, the Spring ApplicationContext will be searched for the NavigationHandler
042: * under the bean name "jsfNavigationHandler". In the simplest case, this is a plain
043: * Spring bean definition like the following. However, all of Spring's bean configuration
044: * power can be applied to such a bean, in particular all flavors of dependency injection.
045: *
046: * <pre>
047: * <bean name="jsfNavigationHandler" class="mypackage.MyNavigationHandler">
048: * <property name="myProperty" ref="myOtherBean"/>
049: * </bean></pre>
050: *
051: * The target NavigationHandler bean will typically extend the standard JSF
052: * NavigationHandler class. However, note that decorating the original
053: * NavigationHandler (the JSF provider's default handler) is <i>not</i> supported
054: * in such a scenario, since we can't inject the original handler in standard
055: * JSF style (that is, as constructor argument).
056: *
057: * <p>For <b>decorating the original NavigationHandler</b>, make sure that your
058: * target bean extends Spring's <b>DecoratingNavigationHandler</b> class. This
059: * allows to pass in the original handler as method argument, which this proxy
060: * automatically detects. Note that a DecoratingNavigationHandler subclass
061: * will still work as standard JSF NavigationHandler as well!
062: *
063: * <p>This proxy may be subclassed to change the bean name used to search for the
064: * navigation handler, change the strategy used to obtain the target handler,
065: * or change the strategy used to access the ApplicationContext (normally obtained
066: * via {@link FacesContextUtils#getWebApplicationContext(FacesContext)}).
067: *
068: * @author Juergen Hoeller
069: * @author Colin Sampaleanu
070: * @since 1.2.7
071: * @see DecoratingNavigationHandler
072: */
073: public class DelegatingNavigationHandlerProxy extends NavigationHandler {
074:
075: /**
076: * Default name of the target bean in the Spring application context:
077: * "jsfNavigationHandler"
078: */
079: public final static String DEFAULT_TARGET_BEAN_NAME = "jsfNavigationHandler";
080:
081: private NavigationHandler originalNavigationHandler;
082:
083: /**
084: * Create a new DelegatingNavigationHandlerProxy.
085: */
086: public DelegatingNavigationHandlerProxy() {
087: }
088:
089: /**
090: * Create a new DelegatingNavigationHandlerProxy.
091: * @param originalNavigationHandler the original NavigationHandler
092: */
093: public DelegatingNavigationHandlerProxy(
094: NavigationHandler originalNavigationHandler) {
095: this .originalNavigationHandler = originalNavigationHandler;
096: }
097:
098: /**
099: * Handle the navigation request implied by the specified parameters,
100: * through delegating to the target bean in the Spring application context.
101: * <p>The target bean needs to extend the JSF NavigationHandler class.
102: * If it extends Spring's DecoratingNavigationHandler, the overloaded
103: * <code>handleNavigation</code> method with the original NavigationHandler
104: * as argument will be used. Else, the standard <code>handleNavigation</code>
105: * method will be called.
106: */
107: public void handleNavigation(FacesContext facesContext,
108: String fromAction, String outcome) {
109: NavigationHandler handler = getDelegate(facesContext);
110: if (handler instanceof DecoratingNavigationHandler) {
111: ((DecoratingNavigationHandler) handler).handleNavigation(
112: facesContext, fromAction, outcome,
113: this .originalNavigationHandler);
114: } else {
115: handler.handleNavigation(facesContext, fromAction, outcome);
116: }
117: }
118:
119: /**
120: * Return the target NavigationHandler to delegate to.
121: * <p>By default, a bean with the name "jsfNavigationHandler" is obtained
122: * from the Spring root WebApplicationContext, for every invocation.
123: * @param facesContext the current JSF context
124: * @return the target NavigationHandler to delegate to
125: * @see #getTargetBeanName
126: * @see #getBeanFactory
127: */
128: protected NavigationHandler getDelegate(FacesContext facesContext) {
129: String targetBeanName = getTargetBeanName(facesContext);
130: return (NavigationHandler) getBeanFactory(facesContext)
131: .getBean(targetBeanName, NavigationHandler.class);
132: }
133:
134: /**
135: * Return the name of the target NavigationHandler bean in the BeanFactory.
136: * Default is "jsfNavigationHandler".
137: * @param facesContext the current JSF context
138: * @return the name of the target bean
139: */
140: protected String getTargetBeanName(FacesContext facesContext) {
141: return DEFAULT_TARGET_BEAN_NAME;
142: }
143:
144: /**
145: * Retrieve the Spring BeanFactory to delegate bean name resolution to.
146: * <p>Default implementation delegates to <code>getWebApplicationContext</code>.
147: * Can be overridden to provide an arbitrary BeanFactory reference to resolve
148: * against; usually, this will be a full Spring ApplicationContext.
149: * @param facesContext the current JSF context
150: * @return the Spring BeanFactory (never <code>null</code>)
151: * @see #getWebApplicationContext
152: */
153: protected BeanFactory getBeanFactory(FacesContext facesContext) {
154: return getWebApplicationContext(facesContext);
155: }
156:
157: /**
158: * Retrieve the web application context to delegate bean name resolution to.
159: * <p>Default implementation delegates to FacesContextUtils.
160: * @param facesContext the current JSF context
161: * @return the Spring web application context (never <code>null</code>)
162: * @see FacesContextUtils#getRequiredWebApplicationContext
163: */
164: protected WebApplicationContext getWebApplicationContext(
165: FacesContext facesContext) {
166: return FacesContextUtils
167: .getRequiredWebApplicationContext(facesContext);
168: }
169:
170: }
|