KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > application > NavigationHandlerImpl


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.application;
17
18 import java.io.IOException JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Comparator JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27
28 import javax.faces.FacesException;
29 import javax.faces.application.NavigationHandler;
30 import javax.faces.application.ViewHandler;
31 import javax.faces.component.UIViewRoot;
32 import javax.faces.context.ExternalContext;
33 import javax.faces.context.FacesContext;
34 import javax.servlet.http.HttpServletRequest JavaDoc;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.myfaces.config.RuntimeConfig;
39 import org.apache.myfaces.config.element.NavigationCase;
40 import org.apache.myfaces.config.element.NavigationRule;
41 import org.apache.myfaces.portlet.PortletUtil;
42 import org.apache.myfaces.util.HashMapUtils;
43
44 /**
45  * @author Thomas Spiegl (latest modification by $Author: matzew $)
46  * @author Anton Koinov
47  * @version $Revision: 1.35 $ $Date: 2005/03/11 09:12:15 $
48  * $Log: NavigationHandlerImpl.java,v $
49  * Revision 1.35 2005/03/11 09:12:15 matzew
50  * Patch from Stan Silver that removes the portlet dependency (MYFACES-126)
51  *
52  * Revision 1.34 2005/01/26 17:03:09 matzew
53  * MYFACES-86. portlet support provided by Stan Silver (JBoss Group)
54  *
55  * Revision 1.33 2004/10/13 11:50:59 matze
56  * renamed packages to org.apache
57  *
58  * Revision 1.32 2004/08/26 08:03:29 manolito
59  * viewId for redirect might already contain a query string, so we must check for ? in url
60  *
61  * Revision 1.31 2004/08/26 08:00:58 manolito
62  * add current queryString to url on redirect
63  *
64  * Revision 1.30 2004/07/07 08:34:57 mwessendorf
65  * removed unused import-statements
66  *
67  * Revision 1.29 2004/07/07 00:25:04 o_rossmueller
68  * tidy up config/confignew package (moved confignew classes to package config)
69  *
70  * Revision 1.28 2004/07/01 22:05:14 mwessendorf
71  * ASF switch
72  *
73  * Revision 1.27 2004/06/16 23:02:21 o_rossmueller
74  * merged confignew_branch
75  *
76  * Revision 1.26.2.1 2004/06/16 02:07:22 o_rossmueller
77  * get navigation rules from RuntimeConfig
78  * refactored all remaining usages of MyFacesFactoryFinder to use RuntimeConfig
79  *
80  * Revision 1.26 2004/05/18 12:02:28 manolito
81  * getActionURL and getResourceURL must not call encodeActionURL or encodeResourceURL
82  *
83  * Revision 1.25 2004/05/10 04:49:26 dave0000
84  * small optimization improvements
85  *
86  * Revision 1.24 2004/04/26 11:28:16 manolito
87  * global navigation-rule with no from-view-id NPE bug
88  *
89  */

90 public class NavigationHandlerImpl
91     extends NavigationHandler
92 {
93     private static final Log log = LogFactory.getLog(NavigationHandlerImpl.class);
94
95     private static final String JavaDoc ASTERISK = "*";
96     
97     private Map JavaDoc _navigationCases = null;
98     private List JavaDoc _wildcardKeys = new ArrayList JavaDoc();
99
100     public NavigationHandlerImpl()
101     {
102         if (log.isTraceEnabled()) log.trace("New NavigationHandler instance created");
103     }
104
105     public void handleNavigation(FacesContext facesContext, String JavaDoc fromAction, String JavaDoc outcome)
106     {
107         if (outcome == null)
108         {
109             // stay on current ViewRoot
110
return;
111         }
112
113         String JavaDoc viewId = facesContext.getViewRoot().getViewId();
114         Map JavaDoc casesMap = getNavigationCases(facesContext);
115         NavigationCase navigationCase = null;
116
117         List JavaDoc casesList = (List JavaDoc)casesMap.get(viewId);
118         if (casesList != null)
119         {
120             // Exact match?
121
navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
122         }
123
124         if (navigationCase == null)
125         {
126             // Wildcard match?
127
List JavaDoc keys = getSortedWildcardKeys();
128             for (int i = 0, size = keys.size(); i < size; i++)
129             {
130                 String JavaDoc fromViewId = (String JavaDoc)keys.get(i);
131                 if (fromViewId.length() > 2)
132                 {
133                     String JavaDoc prefix = fromViewId.substring(0, fromViewId.length() - 2);
134                     if (viewId.startsWith(prefix))
135                     {
136                         casesList = (List JavaDoc)casesMap.get(fromViewId);
137                         if (casesList != null)
138                         {
139                             navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
140                             if (navigationCase != null) break;
141                         }
142                     }
143                 }
144                 else
145                 {
146                     casesList = (List JavaDoc)casesMap.get(fromViewId);
147                     if (casesList != null)
148                     {
149                         navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
150                         if (navigationCase != null) break;
151                     }
152                 }
153             }
154         }
155
156         if (navigationCase != null)
157         {
158             if (log.isTraceEnabled())
159             {
160                 log.trace("handleNavigation fromAction=" + fromAction + " outcome=" + outcome +
161                           " toViewId =" + navigationCase.getToViewId() +
162                           " redirect=" + navigationCase.isRedirect());
163             }
164             if (navigationCase.isRedirect() &&
165                (!PortletUtil.isPortletRequest(facesContext)))
166             { // Spec section 7.4.2 says "redirects not possible" in this case for portlets
167
ExternalContext externalContext = facesContext.getExternalContext();
168                 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
169                 String JavaDoc redirectPath = viewHandler.getActionURL(facesContext, navigationCase.getToViewId());
170                 Object JavaDoc req = externalContext.getRequest();
171                 if (req instanceof HttpServletRequest JavaDoc)
172                 {
173                     String JavaDoc queryString = ((HttpServletRequest JavaDoc)req).getQueryString();
174                     if (queryString != null)
175                     {
176                         if (redirectPath.indexOf('?') == -1)
177                         {
178                             redirectPath = redirectPath + '?' + queryString;
179                         }
180                         else
181                         {
182                             redirectPath = redirectPath + '&' + queryString;
183                         }
184                     }
185                 }
186                 
187                 try
188                 {
189                     externalContext.redirect(externalContext.encodeActionURL(redirectPath));
190                 }
191                 catch (IOException JavaDoc e)
192                 {
193                     throw new FacesException(e.getMessage(), e);
194                 }
195                 facesContext.responseComplete();
196             }
197             else
198             {
199                 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
200                 //create new view
201
UIViewRoot viewRoot = viewHandler.createView(facesContext, navigationCase.getToViewId());
202                 facesContext.setViewRoot(viewRoot);
203                 facesContext.renderResponse();
204             }
205         }
206         else
207         {
208             // no navigationcase found, stay on current ViewRoot
209
if (log.isTraceEnabled())
210             {
211                 log.trace("handleNavigation fromAction=" + fromAction + " outcome=" + outcome +
212                           " no matching navigation-case found, staying on current ViewRoot");
213             }
214         }
215     }
216
217     private NavigationCase calcMatchingNavigationCase(List JavaDoc casesList, String JavaDoc actionRef, String JavaDoc outcome)
218     {
219         for (int i = 0, size = casesList.size(); i < size; i++)
220         {
221             NavigationCase caze = (NavigationCase)casesList.get(i);
222             String JavaDoc cazeOutcome = caze.getFromOutcome();
223             String JavaDoc cazeActionRef = caze.getFromAction();
224             if ((cazeOutcome == null || cazeOutcome.equals(outcome)) &&
225                 (cazeActionRef == null || cazeActionRef.equals(actionRef)))
226             {
227                 return caze;
228             }
229         }
230         return null;
231     }
232
233     private List JavaDoc getSortedWildcardKeys()
234     {
235         return _wildcardKeys;
236     }
237
238     private Map JavaDoc getNavigationCases(FacesContext facesContext)
239     {
240         if (_navigationCases == null)
241         {
242             synchronized(this)
243             {
244                 if (_navigationCases == null)
245                 {
246                     ExternalContext externalContext = facesContext.getExternalContext();
247                     RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
248         
249                     Collection JavaDoc rules = runtimeConfig.getNavigationRules();
250                     int rulesSize = rules.size();
251                     Map JavaDoc cases = new HashMap JavaDoc(HashMapUtils.calcCapacity(rulesSize));
252                     List JavaDoc wildcardKeys = new ArrayList JavaDoc();
253
254                     for (Iterator JavaDoc iterator = rules.iterator(); iterator.hasNext();)
255                     {
256                         NavigationRule rule = (NavigationRule) iterator.next();
257                         String JavaDoc fromViewId = rule.getFromViewId();
258         
259                         //specification 7.4.2 footnote 4 - missing fromViewId is allowed:
260
if (fromViewId == null)
261                         {
262                             fromViewId = ASTERISK;
263                         }
264                         else
265                         {
266                             fromViewId = fromViewId.trim();
267                         }
268         
269                         List JavaDoc list = (List JavaDoc) cases.get(fromViewId);
270                         if (list == null)
271                         {
272                             list = new ArrayList JavaDoc(rule.getNavigationCases());
273                             cases.put(fromViewId, list);
274                             if (fromViewId.endsWith(ASTERISK))
275                             {
276                                 wildcardKeys.add(fromViewId);
277                             }
278                         } else {
279                             list.addAll(rule.getNavigationCases());
280                         }
281         
282                     }
283                     Collections.sort(wildcardKeys, new KeyComparator());
284                         
285                     synchronized (cases)
286                     {
287                         // We do not really need this sychronization at all, but this
288
// gives us the peace of mind that some good optimizing compiler
289
// will not rearrange the execution of the assignment to an
290
// earlier time, before all init code completes
291
_navigationCases = cases;
292                         _wildcardKeys = wildcardKeys;
293                     }
294                 }
295             }
296         }
297         return _navigationCases;
298     }
299
300     private static final class KeyComparator
301         implements Comparator JavaDoc
302     {
303         public int compare(Object JavaDoc o1, Object JavaDoc o2)
304         {
305             return -(((String JavaDoc)o1).compareTo((String JavaDoc)o2));
306         }
307     }
308 }
309
Popular Tags