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 java.util.Collection;
020: import java.util.Iterator;
021:
022: import javax.faces.context.FacesContext;
023: import javax.faces.event.PhaseEvent;
024: import javax.faces.event.PhaseId;
025: import javax.faces.event.PhaseListener;
026:
027: import org.springframework.beans.factory.BeanFactoryUtils;
028: import org.springframework.beans.factory.ListableBeanFactory;
029: import org.springframework.web.context.WebApplicationContext;
030:
031: /**
032: * JSF PhaseListener implementation that delegates to one or more Spring-managed
033: * PhaseListener beans coming from the Spring root WebApplicationContext.
034: *
035: * <p>Configure this listener multicaster in your <code>faces-config.xml</code> file
036: * as follows:
037: *
038: * <pre>
039: * <application>
040: * ...
041: * <phase-listener>
042: * org.springframework.web.jsf.DelegatingPhaseListenerMulticaster
043: * </phase-listener>
044: * ...
045: * </application></pre>
046: *
047: * The multicaster will delegate all <code>beforePhase</code> and <code>afterPhase</code>
048: * events to all target PhaseListener beans. By default, those will simply be obtained
049: * by type: All beans in the Spring root WebApplicationContext that implement the
050: * PhaseListener interface will be fetched and invoked.
051: *
052: * <p>Note this multicaster's <code>getPhaseId()</code> method will always return
053: * <code>ANY_PHASE</code>. The phase id exposed by the target listener beans
054: * will be ignored; all events will be propagated to all listeners.
055: *
056: * <p>This multicaster may be subclassed to change the strategy used to obtain
057: * the listener beans, or to change the strategy used to access the ApplicationContext
058: * (normally obtained via {@link FacesContextUtils#getWebApplicationContext(FacesContext)}).
059: *
060: * @author Juergen Hoeller
061: * @author Colin Sampaleanu
062: * @since 1.2.7
063: */
064: public class DelegatingPhaseListenerMulticaster implements
065: PhaseListener {
066:
067: public PhaseId getPhaseId() {
068: return PhaseId.ANY_PHASE;
069: }
070:
071: public void beforePhase(PhaseEvent event) {
072: Collection listeners = getDelegates(event.getFacesContext());
073: Iterator it = listeners.iterator();
074: while (it.hasNext()) {
075: PhaseListener listener = (PhaseListener) it.next();
076: listener.beforePhase(event);
077: }
078: }
079:
080: public void afterPhase(PhaseEvent event) {
081: Collection listeners = getDelegates(event.getFacesContext());
082: Iterator it = listeners.iterator();
083: while (it.hasNext()) {
084: PhaseListener listener = (PhaseListener) it.next();
085: listener.afterPhase(event);
086: }
087: }
088:
089: /**
090: * Obtain the delegate PhaseListener beans from the Spring root
091: * WebApplicationContext.
092: * @param facesContext the current JSF context
093: * @return a Collection of PhaseListener objects
094: * @see #getBeanFactory
095: * @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(Class)
096: */
097: protected Collection getDelegates(FacesContext facesContext) {
098: ListableBeanFactory bf = getBeanFactory(facesContext);
099: return BeanFactoryUtils.beansOfTypeIncludingAncestors(bf,
100: PhaseListener.class, true, false).values();
101: }
102:
103: /**
104: * Retrieve the Spring BeanFactory to delegate bean name resolution to.
105: * <p>Default implementation delegates to <code>getWebApplicationContext</code>.
106: * Can be overridden to provide an arbitrary ListableBeanFactory reference to
107: * resolve against; usually, this will be a full Spring ApplicationContext.
108: * @param facesContext the current JSF context
109: * @return the Spring ListableBeanFactory (never <code>null</code>)
110: * @see #getWebApplicationContext
111: */
112: protected ListableBeanFactory getBeanFactory(
113: FacesContext facesContext) {
114: return getWebApplicationContext(facesContext);
115: }
116:
117: /**
118: * Retrieve the web application context to delegate bean name resolution to.
119: * <p>Default implementation delegates to FacesContextUtils.
120: * @param facesContext the current JSF context
121: * @return the Spring web application context (never <code>null</code>)
122: * @see FacesContextUtils#getRequiredWebApplicationContext
123: */
124: protected WebApplicationContext getWebApplicationContext(
125: FacesContext facesContext) {
126: return FacesContextUtils
127: .getRequiredWebApplicationContext(facesContext);
128: }
129:
130: }
|