1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30
31 import javax.faces.FacesException;
32 import javax.faces.application.NavigationHandler;
33 import javax.faces.application.ViewHandler;
34 import javax.faces.component.UIViewRoot;
35 import javax.faces.context.ExternalContext;
36 import javax.faces.context.FacesContext;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.myfaces.config.RuntimeConfig;
41 import org.apache.myfaces.config.element.NavigationCase;
42 import org.apache.myfaces.config.element.NavigationRule;
43 import org.apache.myfaces.portlet.PortletUtil;
44 import org.apache.myfaces.shared_impl.util.HashMapUtils;
45
46
47
48
49
50
51 public class NavigationHandlerImpl
52 extends NavigationHandler
53 {
54 private static final Log log = LogFactory.getLog(NavigationHandlerImpl.class);
55
56 private static final String ASTERISK = "*";
57
58 private Map<String, List> _navigationCases = null;
59 private List<String> _wildcardKeys = new ArrayList<String>();
60
61 public NavigationHandlerImpl()
62 {
63 if (log.isTraceEnabled()) log.trace("New NavigationHandler instance created");
64 }
65
66 public void handleNavigation(FacesContext facesContext, String fromAction, String outcome)
67 {
68 if (outcome == null)
69 {
70
71 return;
72 }
73
74 NavigationCase navigationCase = getNavigationCase(facesContext, fromAction, outcome);
75
76 if (navigationCase != null)
77 {
78 if (log.isTraceEnabled())
79 {
80 log.trace("handleNavigation fromAction=" + fromAction + " outcome=" + outcome +
81 " toViewId =" + navigationCase.getToViewId() +
82 " redirect=" + navigationCase.isRedirect());
83 }
84 if (navigationCase.isRedirect() &&
85 (!PortletUtil.isPortletRequest(facesContext)))
86 {
87 ExternalContext externalContext = facesContext.getExternalContext();
88 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
89 String redirectPath = viewHandler.getActionURL(facesContext, navigationCase.getToViewId());
90
91 try
92 {
93 externalContext.redirect(externalContext.encodeActionURL(redirectPath));
94 }
95 catch (IOException e)
96 {
97 throw new FacesException(e.getMessage(), e);
98 }
99 }
100 else
101 {
102 ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
103
104 String newViewId = navigationCase.getToViewId();
105 UIViewRoot viewRoot = viewHandler.createView(facesContext, newViewId);
106 facesContext.setViewRoot(viewRoot);
107 facesContext.renderResponse();
108 }
109 }
110 else
111 {
112
113 if (log.isTraceEnabled())
114 {
115 log.trace("handleNavigation fromAction=" + fromAction + " outcome=" + outcome +
116 " no matching navigation-case found, staying on current ViewRoot");
117 }
118 }
119 }
120
121
122
123
124
125 public NavigationCase getNavigationCase(FacesContext facesContext, String fromAction, String outcome)
126 {
127 String viewId = facesContext.getViewRoot().getViewId();
128 Map<String, List> casesMap = getNavigationCases(facesContext);
129 NavigationCase navigationCase = null;
130
131 List casesList = casesMap.get(viewId);
132 if (casesList != null)
133 {
134
135 navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
136 }
137
138 if (navigationCase == null)
139 {
140
141 List<String> keys = getSortedWildcardKeys();
142 for (int i = 0, size = keys.size(); i < size; i++)
143 {
144 String fromViewId = keys.get(i);
145 if (fromViewId.length() > 2)
146 {
147 String prefix = fromViewId.substring(0, fromViewId.length() - 1);
148 if (viewId != null && viewId.startsWith(prefix))
149 {
150 casesList = casesMap.get(fromViewId);
151 if (casesList != null)
152 {
153 navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
154 if (navigationCase != null) break;
155 }
156 }
157 }
158 else
159 {
160 casesList = casesMap.get(fromViewId);
161 if (casesList != null)
162 {
163 navigationCase = calcMatchingNavigationCase(casesList, fromAction, outcome);
164 if (navigationCase != null) break;
165 }
166 }
167 }
168 }
169 return navigationCase;
170 }
171
172
173
174
175 public String getViewId(FacesContext context, String fromAction, String outcome)
176 {
177 return this.getNavigationCase(context, fromAction, outcome).getToViewId();
178 }
179
180
181
182
183
184
185
186
187 public String beforeNavigation(String viewId)
188 {
189 return null;
190 }
191
192 private NavigationCase calcMatchingNavigationCase(List casesList, String actionRef, String outcome)
193 {
194 for (int i = 0, size = casesList.size(); i < size; i++)
195 {
196 NavigationCase caze = (NavigationCase)casesList.get(i);
197 String cazeOutcome = caze.getFromOutcome();
198 String cazeActionRef = caze.getFromAction();
199 if ((cazeOutcome == null || cazeOutcome.equals(outcome)) &&
200 (cazeActionRef == null || cazeActionRef.equals(actionRef)))
201 {
202 return caze;
203 }
204 }
205 return null;
206 }
207
208 private List<String> getSortedWildcardKeys()
209 {
210 return _wildcardKeys;
211 }
212
213 private Map<String, List> getNavigationCases(FacesContext facesContext)
214 {
215 ExternalContext externalContext = facesContext.getExternalContext();
216 RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
217
218 if (_navigationCases == null || runtimeConfig.isNavigationRulesChanged())
219 {
220 synchronized(this)
221 {
222 if (_navigationCases == null || runtimeConfig.isNavigationRulesChanged())
223 {
224 Collection rules = runtimeConfig.getNavigationRules();
225 int rulesSize = rules.size();
226 Map<String, List> cases = new HashMap<String, List>(HashMapUtils.calcCapacity(rulesSize));
227 List<String> wildcardKeys = new ArrayList<String>();
228
229 for (Iterator iterator = rules.iterator(); iterator.hasNext();)
230 {
231 NavigationRule rule = (NavigationRule) iterator.next();
232 String fromViewId = rule.getFromViewId();
233
234
235 if (fromViewId == null)
236 {
237 fromViewId = ASTERISK;
238 }
239 else
240 {
241 fromViewId = fromViewId.trim();
242 }
243
244 List list = cases.get(fromViewId);
245 if (list == null)
246 {
247 list = new ArrayList(rule.getNavigationCases());
248 cases.put(fromViewId, list);
249 if (fromViewId.endsWith(ASTERISK))
250 {
251 wildcardKeys.add(fromViewId);
252 }
253 } else {
254 list.addAll(rule.getNavigationCases());
255 }
256
257 }
258 Collections.sort(wildcardKeys, new KeyComparator());
259
260 synchronized (cases)
261 {
262
263
264
265
266 _navigationCases = cases;
267 _wildcardKeys = wildcardKeys;
268
269 runtimeConfig.setNavigationRulesChanged(false);
270 }
271 }
272 }
273 }
274 return _navigationCases;
275 }
276
277 private static final class KeyComparator
278 implements Comparator
279 {
280 public int compare(Object o1, Object o2)
281 {
282 return -(((String)o1).compareTo((String)o2));
283 }
284 }
285 }