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.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34 import java.util.stream.Stream;
35
36 import javax.faces.FacesException;
37 import javax.faces.FactoryFinder;
38 import javax.faces.application.Application;
39 import javax.faces.application.StateManager;
40 import javax.faces.application.ViewHandler;
41 import javax.faces.application.ViewVisitOption;
42 import javax.faces.component.UIViewParameter;
43 import javax.faces.component.UIViewRoot;
44 import javax.faces.context.ExternalContext;
45 import javax.faces.context.FacesContext;
46 import javax.faces.render.RenderKitFactory;
47 import javax.faces.render.ResponseStateManager;
48 import javax.faces.view.ViewDeclarationLanguage;
49 import javax.faces.view.ViewDeclarationLanguageFactory;
50 import javax.faces.view.ViewMetadata;
51 import javax.servlet.http.HttpServletResponse;
52
53 import org.apache.myfaces.application.viewstate.StateCacheUtils;
54 import org.apache.myfaces.shared.application.DefaultViewHandlerSupport;
55 import org.apache.myfaces.shared.application.InvalidViewIdException;
56 import org.apache.myfaces.shared.application.ViewHandlerSupport;
57 import org.apache.myfaces.view.facelets.StateWriter;
58
59
60
61
62
63
64 public class ViewHandlerImpl extends ViewHandler
65 {
66 private static final Logger log = Logger.getLogger(ViewHandlerImpl.class.getName());
67
68 public static final String FORM_STATE_MARKER = "<!--@@JSF_FORM_STATE_MARKER@@-->";
69 private ViewHandlerSupport _viewHandlerSupport;
70 private ViewDeclarationLanguageFactory _vdlFactory;
71
72 private Set<String> _protectedViewsSet;
73 private Set<String> _unmodifiableProtectedViewsSet;
74
75
76
77
78
79
80
81
82
83 public static ViewHandler getViewHandler(FacesContext facesContext)
84 {
85 return facesContext.getApplication().getViewHandler();
86 }
87
88 public ViewHandlerImpl()
89 {
90 _protectedViewsSet = Collections.newSetFromMap(new ConcurrentHashMap<String,Boolean>());
91 _unmodifiableProtectedViewsSet = Collections.unmodifiableSet(_protectedViewsSet);
92 _vdlFactory = (ViewDeclarationLanguageFactory)
93 FactoryFinder.getFactory(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY);
94 if (log.isLoggable(Level.FINEST))
95 {
96 log.finest("New ViewHandler instance created");
97 }
98 }
99
100 @Override
101 public String deriveViewId(FacesContext context, String input)
102 {
103 if(input != null)
104 {
105 try
106 {
107 return getViewHandlerSupport(context).calculateAndCheckViewId(context, input);
108 }
109 catch (InvalidViewIdException e)
110 {
111 sendSourceNotFound(context, e.getMessage());
112 }
113 }
114 return input;
115 }
116
117 @Override
118 public String deriveLogicalViewId(FacesContext context, String rawViewId)
119 {
120 if(rawViewId != null)
121 {
122 try
123 {
124 return getViewHandlerSupport(context).calculateViewId(context, rawViewId);
125 }
126 catch (InvalidViewIdException e)
127 {
128 sendSourceNotFound(context, e.getMessage());
129 }
130 }
131 return rawViewId;
132 }
133
134 @Override
135 public String getBookmarkableURL(FacesContext context, String viewId,
136 Map<String, List<String>> parameters, boolean includeViewParams)
137 {
138 Map<String, List<String>> viewParameters;
139 if (includeViewParams)
140 {
141 viewParameters = getViewParameterList(context, viewId, parameters);
142 }
143 else
144 {
145 viewParameters = parameters;
146 }
147
148
149
150 String actionEncodedViewId = getViewHandler(context).getActionURL(context, viewId);
151
152 ExternalContext externalContext = context.getExternalContext();
153 String bookmarkEncodedURL = externalContext.encodeBookmarkableURL(actionEncodedViewId, viewParameters);
154 return externalContext.encodeActionURL(bookmarkEncodedURL);
155 }
156
157 @Override
158 public String getRedirectURL(FacesContext context, String viewId,
159 Map<String, List<String>> parameters, boolean includeViewParams)
160 {
161 Map<String, List<String>> viewParameters;
162 if (includeViewParams)
163 {
164 viewParameters = getViewParameterList(context, viewId, parameters);
165 }
166 else
167 {
168 viewParameters = parameters;
169 }
170
171
172
173 String actionEncodedViewId = getViewHandler(context).getActionURL(context, viewId);
174
175 ExternalContext externalContext = context.getExternalContext();
176 String redirectEncodedURL = externalContext.encodeRedirectURL(actionEncodedViewId, viewParameters);
177 return externalContext.encodeActionURL(redirectEncodedURL);
178 }
179
180 @Override
181 public ViewDeclarationLanguage getViewDeclarationLanguage(
182 FacesContext context, String viewId)
183 {
184
185 return _vdlFactory.getViewDeclarationLanguage(viewId);
186 }
187
188 @Override
189 public void initView(FacesContext context) throws FacesException
190 {
191 if(context.getExternalContext().getRequestCharacterEncoding() == null)
192 {
193 super.initView(context);
194 }
195 }
196
197
198
199
200
201 @Override
202 public Locale calculateLocale(FacesContext facesContext)
203 {
204 Application application = facesContext.getApplication();
205 for (Iterator<Locale> requestLocales = facesContext.getExternalContext().getRequestLocales(); requestLocales
206 .hasNext();)
207 {
208 Locale requestLocale = requestLocales.next();
209 for (Iterator<Locale> supportedLocales = application.getSupportedLocales(); supportedLocales.hasNext();)
210 {
211 Locale supportedLocale = supportedLocales.next();
212
213
214 if (requestLocale.getLanguage().equals(supportedLocale.getLanguage())
215 && (supportedLocale.getCountry() == null || supportedLocale.getCountry().length() == 0))
216 {
217 return supportedLocale;
218 }
219 else if (supportedLocale.equals(requestLocale))
220 {
221 return supportedLocale;
222 }
223 }
224 }
225
226 Locale defaultLocale = application.getDefaultLocale();
227 return defaultLocale != null ? defaultLocale : Locale.getDefault();
228 }
229
230 @Override
231 public String calculateRenderKitId(FacesContext facesContext)
232 {
233 Object renderKitId = facesContext.getExternalContext().getRequestMap().get(
234 ResponseStateManager.RENDER_KIT_ID_PARAM);
235 if (renderKitId == null)
236 {
237 renderKitId = facesContext.getApplication().getDefaultRenderKitId();
238 }
239 if (renderKitId == null)
240 {
241 renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
242 }
243 return renderKitId.toString();
244 }
245
246 @Override
247 public UIViewRoot createView(FacesContext context, String viewId)
248 {
249 checkNull(context, "facesContext");
250 String calculatedViewId = getViewHandlerSupport(context).calculateViewId(context, viewId);
251
252
253
254
255
256
257 ViewDeclarationLanguage vdl = getViewDeclarationLanguage(context,calculatedViewId);
258 if (vdl == null)
259 {
260
261 sendSourceNotFound(context, viewId);
262 return null;
263 }
264 return vdl.createView(context,calculatedViewId);
265 }
266
267 @Override
268 public String getActionURL(FacesContext context, String viewId)
269 {
270 checkNull(context, "facesContext");
271 checkNull(viewId, "viewId");
272 return getViewHandlerSupport(context).calculateActionURL(context, viewId);
273 }
274
275 @Override
276 public String getResourceURL(FacesContext facesContext, String path)
277 {
278 checkNull(facesContext, "facesContext");
279 checkNull(path, "path");
280 if (path.length() > 0 && path.charAt(0) == '/')
281 {
282 String contextPath = facesContext.getExternalContext().getRequestContextPath();
283 if (contextPath == null)
284 {
285 return path;
286 }
287 else if (contextPath.length() == 1 && contextPath.charAt(0) == '/')
288 {
289
290
291 return path;
292 }
293 else
294 {
295 return contextPath + path;
296 }
297 }
298 return path;
299
300 }
301
302 @Override
303 public void renderView(FacesContext context, UIViewRoot viewToRender)
304 throws IOException, FacesException
305 {
306
307 checkNull(context, "context");
308 checkNull(viewToRender, "viewToRender");
309
310
311
312
313
314
315 getViewDeclarationLanguage(context,viewToRender.getViewId()).renderView(context, viewToRender);
316 }
317
318 @Override
319 public UIViewRoot restoreView(FacesContext context, String viewId)
320 {
321 checkNull(context, "context");
322
323 String calculatedViewId = getViewHandlerSupport(context).calculateViewId(context, viewId);
324
325
326
327
328
329
330 ViewDeclarationLanguage vdl = getViewDeclarationLanguage(context,calculatedViewId);
331 if (vdl == null)
332 {
333
334 sendSourceNotFound(context, viewId);
335 return null;
336
337 }
338 return vdl.restoreView(context, calculatedViewId);
339 }
340
341 @Override
342 public void writeState(FacesContext context) throws IOException
343 {
344 checkNull(context, "context");
345
346 if(context.getPartialViewContext().isAjaxRequest())
347 {
348 return;
349 }
350
351 ResponseStateManager responseStateManager = context.getRenderKit().getResponseStateManager();
352
353 setWritingState(context, responseStateManager);
354
355 StateManager stateManager = context.getApplication().getStateManager();
356
357
358
359
360
361
362
363
364 if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
365 {
366 if (StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
367 isWriteStateAfterRenderViewRequired(context))
368 {
369
370 context.getResponseWriter().write(FORM_STATE_MARKER);
371 }
372 else
373 {
374 stateManager.writeState(context, new Object[2]);
375 }
376 }
377 else
378 {
379
380 context.getResponseWriter().write(FORM_STATE_MARKER);
381 }
382 }
383
384 @Override
385 public void addProtectedView(String urlPattern)
386 {
387 _protectedViewsSet.add(urlPattern);
388 }
389
390 @Override
391 public boolean removeProtectedView(String urlPattern)
392 {
393 return _protectedViewsSet.remove(urlPattern);
394 }
395
396 @Override
397 public Set<String> getProtectedViewsUnmodifiable()
398 {
399 return _unmodifiableProtectedViewsSet;
400 }
401
402 private void setWritingState(FacesContext context, ResponseStateManager rsm)
403 {
404
405
406 StateWriter stateWriter = StateWriter.getCurrentInstance(context);
407 if (stateWriter != null)
408 {
409
410
411
412
413
414
415 if (StateCacheUtils.isMyFacesResponseStateManager(rsm))
416 {
417 if (StateCacheUtils.getMyFacesResponseStateManager(rsm).isWriteStateAfterRenderViewRequired(context))
418 {
419 stateWriter.writingState();
420 }
421 else
422 {
423 stateWriter.writingStateWithoutWrapper();
424 }
425 }
426 else
427 {
428 stateWriter.writingState();
429 }
430
431
432 }
433
434
435
436
437 }
438
439 private Map<String, List<String>> getViewParameterList(FacesContext context,
440 String viewId, Map<String, List<String>> parametersFromArg)
441 {
442 UIViewRoot viewRoot = context.getViewRoot();
443 String currentViewId = viewRoot.getViewId();
444 Collection<UIViewParameter> toViewParams = null;
445 Collection<UIViewParameter> currentViewParams = ViewMetadata.getViewParameters(viewRoot);
446
447 if (currentViewId.equals(viewId))
448 {
449 toViewParams = currentViewParams;
450 }
451 else
452 {
453 String calculatedViewId = getViewHandlerSupport(context).calculateViewId(context, viewId);
454
455
456
457
458 ViewDeclarationLanguage vdl = getViewDeclarationLanguage(context,calculatedViewId);
459 ViewMetadata viewMetadata = vdl.getViewMetadata(context, viewId);
460
461 if (viewMetadata != null)
462 {
463 UIViewRoot viewFromMetaData = viewMetadata.createMetadataView(context);
464 toViewParams = ViewMetadata.getViewParameters(viewFromMetaData);
465 }
466 }
467
468 if (toViewParams == null || toViewParams.isEmpty())
469 {
470 return parametersFromArg;
471 }
472
473
474
475
476
477
478
479 Map<String, List<String>> parameters = new HashMap<String, List<String>>();
480 parameters.putAll(parametersFromArg);
481
482 for (UIViewParameter viewParameter : toViewParams)
483 {
484 if (!parameters.containsKey(viewParameter.getName()))
485 {
486 String parameterValue = viewParameter.getStringValueFromModel(context);
487 if (parameterValue == null)
488 {
489 if(currentViewId.equals(viewId))
490 {
491 parameterValue = viewParameter.getStringValue(context);
492 }
493 else
494 {
495 if (viewParameter.getName() != null)
496 {
497 for (UIViewParameter curParam : currentViewParams)
498 {
499 if (viewParameter.getName().equals(curParam.getName()))
500 {
501 parameterValue = curParam.getStringValue(context);
502 break;
503 }
504 }
505 }
506 }
507 }
508
509 if (parameterValue != null)
510 {
511
512
513
514 List<String> parameterValueList = new ArrayList<String>(1);
515 parameterValueList.add(parameterValue);
516 parameters.put(viewParameter.getName(), parameterValueList);
517 }
518 }
519 }
520 return parameters;
521 }
522
523 private void checkNull(final Object o, final String param)
524 {
525 if (o == null)
526 {
527 throw new NullPointerException(param + " can not be null.");
528 }
529 }
530
531 private void sendSourceNotFound(FacesContext context, String message)
532 {
533 HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
534 try
535 {
536 context.responseComplete();
537 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
538 }
539 catch (IOException ioe)
540 {
541 throw new FacesException(ioe);
542 }
543 }
544
545 public void setViewHandlerSupport(ViewHandlerSupport viewHandlerSupport)
546 {
547 _viewHandlerSupport = viewHandlerSupport;
548 }
549
550 protected ViewHandlerSupport getViewHandlerSupport()
551 {
552 return getViewHandlerSupport(FacesContext.getCurrentInstance());
553 }
554
555 protected ViewHandlerSupport getViewHandlerSupport(FacesContext context)
556 {
557 if (_viewHandlerSupport == null)
558 {
559 _viewHandlerSupport = new DefaultViewHandlerSupport(context);
560 }
561 return _viewHandlerSupport;
562 }
563
564 @Override
565 public Stream<String> getViews(FacesContext facesContext, String path, int maxDepth, ViewVisitOption... options)
566 {
567 Stream concatenatedStream = null;
568 for (ViewDeclarationLanguage vdl : _vdlFactory.getAllViewDeclarationLanguages())
569 {
570 Stream stream = vdl.getViews(facesContext, path, maxDepth, options);
571 if (concatenatedStream == null)
572 {
573 concatenatedStream = stream;
574 }
575 else
576 {
577 concatenatedStream = Stream.concat(concatenatedStream, stream);
578 }
579 }
580 return concatenatedStream == null ? Stream.empty() : concatenatedStream;
581 }
582
583 @Override
584 public String getWebsocketURL(FacesContext context, String channelAndToken)
585 {
586 String url = context.getExternalContext().getRequestContextPath() +
587 "/javax.faces.push/"+channelAndToken;
588 return url;
589 }
590
591 }