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: /**
023: * Base class for JSF NavigationHandler implementations that want
024: * to be capable of decorating an original NavigationHandler.
025: *
026: * <p>Supports the standard JSF style of decoration (through a constructor argument)
027: * as well as an overloaded <code>handleNavigation</code> method with explicit
028: * NavigationHandler argument (passing in the original NavigationHandler). Subclasses
029: * are forced to implement this overloaded <code>handleNavigation</code> method.
030: * Standard JSF invocations will automatically delegate to the overloaded method,
031: * with the constructor-injected NavigationHandler as argument.
032: *
033: * @author Juergen Hoeller
034: * @since 1.2.7
035: * @see DelegatingNavigationHandlerProxy
036: */
037: public abstract class DecoratingNavigationHandler extends
038: NavigationHandler {
039:
040: private NavigationHandler decoratedNavigationHandler;
041:
042: /**
043: * Create a DecoratingNavigationHandler without fixed original NavigationHandler.
044: */
045: protected DecoratingNavigationHandler() {
046: }
047:
048: /**
049: * Create a DecoratingNavigationHandler with fixed original NavigationHandler.
050: * @param originalNavigationHandler the original NavigationHandler to decorate
051: */
052: protected DecoratingNavigationHandler(
053: NavigationHandler originalNavigationHandler) {
054: this .decoratedNavigationHandler = originalNavigationHandler;
055: }
056:
057: /**
058: * Return the fixed original NavigationHandler decorated by this handler, if any
059: * (that is, if passed in through the constructor).
060: */
061: public final NavigationHandler getDecoratedNavigationHandler() {
062: return decoratedNavigationHandler;
063: }
064:
065: /**
066: * This implementation of the standard JSF <code>handleNavigation</code> method
067: * delegates to the overloaded variant, passing in constructor-injected
068: * NavigationHandler as argument.
069: * @see #handleNavigation(javax.faces.context.FacesContext, String, String, javax.faces.application.NavigationHandler)
070: */
071: public final void handleNavigation(FacesContext facesContext,
072: String fromAction, String outcome) {
073: handleNavigation(facesContext, fromAction, outcome,
074: this .decoratedNavigationHandler);
075: }
076:
077: /**
078: * Special <code>handleNavigation</code> variant with explicit NavigationHandler
079: * argument. Either called directly, by code with an explicit original handler,
080: * or called from the standard <code>handleNavigation</code> method, as
081: * plain JSF-defined NavigationHandler.
082: * <p>Implementations should invoke <code>callNextHandlerInChain</code> to
083: * delegate to the next handler in the chain. This will always call the most
084: * appropriate next handler (see <code>callNextHandlerInChain</code> javadoc).
085: * Alternatively, the decorated NavigationHandler or the passed-in original
086: * NavigationHandler can also be called directly; however, this is not as
087: * flexible in terms of reacting to potential positions in the chain.
088: * @param facesContext the current JSF context
089: * @param fromAction the action binding expression that was evaluated to retrieve the
090: * specified outcome, or <code>null</code> if the outcome was acquired by some other means
091: * @param outcome the logical outcome returned by a previous invoked application action
092: * (which may be <code>null</code>)
093: * @param originalNavigationHandler the original NavigationHandler,
094: * or <code>null</code> if none
095: * @see #callNextHandlerInChain
096: */
097: public abstract void handleNavigation(FacesContext facesContext,
098: String fromAction, String outcome,
099: NavigationHandler originalNavigationHandler);
100:
101: /**
102: * Method to be called by subclasses when intending to delegate to the next
103: * handler in the NavigationHandler chain. Will always call the most
104: * appropriate next handler, either the decorated NavigationHandler passed
105: * in as constructor argument or the original NavigationHandler as passed
106: * into this method - according to the position of this instance in the chain.
107: * <p>Will call the decorated NavigationHandler specified as constructor
108: * argument, if any. In case of a DecoratingNavigationHandler as target, the
109: * original NavigationHandler as passed into this method will be passed on to
110: * the next element in the chain: This ensures propagation of the original
111: * handler that the last element in the handler chain might delegate back to.
112: * In case of a standard NavigationHandler as target, the original handler
113: * will simply not get passed on; no delegating back to the original is
114: * possible further down the chain in that scenario.
115: * <p>If no decorated NavigationHandler specified as constructor argument,
116: * this instance is the last element in the chain. Hence, this method will
117: * call the original NavigationHandler as passed into this method. If no
118: * original NavigantionHandler has been passed in (for example if this
119: * instance is the last element in a chain with standard NavigationHandlers
120: * as earlier elements), this method corresponds to a no-op.
121: * @param facesContext the current JSF context
122: * @param fromAction the action binding expression that was evaluated to retrieve the
123: * specified outcome, or <code>null</code> if the outcome was acquired by some other means
124: * @param outcome the logical outcome returned by a previous invoked application action
125: * (which may be <code>null</code>)
126: * @param originalNavigationHandler the original NavigationHandler,
127: * or <code>null</code> if none
128: */
129: protected final void callNextHandlerInChain(
130: FacesContext facesContext, String fromAction,
131: String outcome, NavigationHandler originalNavigationHandler) {
132:
133: NavigationHandler decoratedNavigationHandler = getDecoratedNavigationHandler();
134:
135: if (decoratedNavigationHandler instanceof DecoratingNavigationHandler) {
136: // DecoratingNavigationHandler specified through constructor argument:
137: // Call it with original NavigationHandler passed in.
138: DecoratingNavigationHandler decHandler = (DecoratingNavigationHandler) decoratedNavigationHandler;
139: decHandler.handleNavigation(facesContext, fromAction,
140: outcome, originalNavigationHandler);
141: } else if (decoratedNavigationHandler != null) {
142: // Standard NavigationHandler specified through constructor argument:
143: // Call it through standard API, without original NavigationHandler passed in.
144: // The called handler will not be able to redirect to the original handler.
145: decoratedNavigationHandler.handleNavigation(facesContext,
146: fromAction, outcome);
147: } else if (originalNavigationHandler != null) {
148: // No NavigationHandler specified through constructor argument:
149: // Call original handler, marking the end of this chain.
150: originalNavigationHandler.handleNavigation(facesContext,
151: fromAction, outcome);
152: }
153: }
154:
155: }
|