1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application.jsp;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.myfaces.application.DefaultViewHandlerSupport;
24 import org.apache.myfaces.application.InvalidViewIdException;
25 import org.apache.myfaces.application.ViewHandlerSupport;
26 import org.apache.myfaces.shared_impl.config.MyfacesConfig;
27 import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
28
29 import javax.faces.FacesException;
30 import javax.faces.FactoryFinder;
31 import javax.faces.application.Application;
32 import javax.faces.application.StateManager;
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 import javax.faces.context.ResponseWriter;
38 import javax.faces.render.RenderKit;
39 import javax.faces.render.RenderKitFactory;
40 import javax.faces.render.ResponseStateManager;
41 import javax.servlet.ServletRequest;
42 import javax.servlet.ServletResponse;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletResponse;
45 import javax.servlet.http.HttpSession;
46 import javax.servlet.jsp.jstl.core.Config;
47 import java.io.IOException;
48 import java.io.StringWriter;
49 import java.io.Writer;
50 import java.util.Iterator;
51 import java.util.Locale;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 public class JspViewHandlerImpl extends ViewHandler
112 {
113 private static final Log log = LogFactory.getLog(JspViewHandlerImpl.class);
114 public static final String FORM_STATE_MARKER = "<!--@@JSF_FORM_STATE_MARKER@@-->";
115 public static final int FORM_STATE_MARKER_LEN = FORM_STATE_MARKER.length();
116
117 private static final String AFTER_VIEW_TAG_CONTENT_PARAM = JspViewHandlerImpl.class + ".AFTER_VIEW_TAG_CONTENT";
118
119 private ViewHandlerSupport _viewHandlerSupport;
120
121 public JspViewHandlerImpl()
122 {
123 if (log.isTraceEnabled())
124 log.trace("New ViewHandler instance created");
125 }
126
127
128
129
130
131 public void setViewHandlerSupport(ViewHandlerSupport viewHandlerSupport)
132 {
133 _viewHandlerSupport = viewHandlerSupport;
134 }
135
136
137
138
139 protected ViewHandlerSupport getViewHandlerSupport()
140 {
141 if (_viewHandlerSupport == null)
142 {
143 _viewHandlerSupport = new DefaultViewHandlerSupport();
144 }
145 return _viewHandlerSupport;
146 }
147
148
149
150
151
152 public Locale calculateLocale(FacesContext facesContext)
153 {
154 Application application = facesContext.getApplication();
155 for (Iterator<Locale> requestLocales = facesContext.getExternalContext().getRequestLocales(); requestLocales
156 .hasNext();)
157 {
158 Locale requestLocale = requestLocales.next();
159 for (Iterator<Locale> supportedLocales = application.getSupportedLocales(); supportedLocales.hasNext();)
160 {
161 Locale supportedLocale = supportedLocales.next();
162
163
164 if (requestLocale.getLanguage().equals(supportedLocale.getLanguage())
165 && (supportedLocale.getCountry() == null || supportedLocale.getCountry().length() == 0))
166 {
167 return supportedLocale;
168 }
169 else if (supportedLocale.equals(requestLocale))
170 {
171 return supportedLocale;
172 }
173 }
174 }
175
176 Locale defaultLocale = application.getDefaultLocale();
177 return defaultLocale != null ? defaultLocale : Locale.getDefault();
178 }
179
180 public String calculateRenderKitId(FacesContext facesContext)
181 {
182 Object renderKitId = facesContext.getExternalContext().getRequestMap().get(
183 ResponseStateManager.RENDER_KIT_ID_PARAM);
184 if (renderKitId == null)
185 {
186 renderKitId = facesContext.getApplication().getDefaultRenderKitId();
187 }
188 if (renderKitId == null)
189 {
190 renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
191 }
192 return renderKitId.toString();
193 }
194
195
196
197
198
199
200
201
202 public UIViewRoot createView(FacesContext facesContext, String viewId)
203 {
204 String calculatedViewId = viewId;
205 try
206 {
207 calculatedViewId = getViewHandlerSupport().calculateViewId(facesContext, viewId);
208 }
209 catch (InvalidViewIdException e)
210 {
211 sendSourceNotFound(facesContext, e.getMessage());
212 }
213
214 Application application = facesContext.getApplication();
215 ViewHandler applicationViewHandler = application.getViewHandler();
216
217 Locale currentLocale = null;
218 String currentRenderKitId = null;
219 UIViewRoot uiViewRoot = facesContext.getViewRoot();
220 if (uiViewRoot != null)
221 {
222
223 currentLocale = uiViewRoot.getLocale();
224 currentRenderKitId = uiViewRoot.getRenderKitId();
225 }
226
227 uiViewRoot = (UIViewRoot) application.createComponent(UIViewRoot.COMPONENT_TYPE);
228
229 uiViewRoot.setViewId(calculatedViewId);
230
231 if (currentLocale != null)
232 {
233
234 uiViewRoot.setLocale(currentLocale);
235 }
236 else
237 {
238
239 uiViewRoot.setLocale(applicationViewHandler.calculateLocale(facesContext));
240 }
241
242 if (currentRenderKitId != null)
243 {
244
245 uiViewRoot.setRenderKitId(currentRenderKitId);
246 }
247 else
248 {
249
250 uiViewRoot.setRenderKitId(applicationViewHandler.calculateRenderKitId(facesContext));
251 }
252
253 if (log.isTraceEnabled())
254 log.trace("Created view " + viewId);
255 return uiViewRoot;
256 }
257
258 private void sendSourceNotFound(FacesContext context, String message)
259 {
260 HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
261 try
262 {
263 context.responseComplete();
264 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
265 }
266 catch (IOException ioe)
267 {
268 throw new FacesException(ioe);
269 }
270 }
271
272
273
274
275
276
277
278
279
280
281 public String getActionURL(FacesContext facesContext, String viewId)
282 {
283 return getViewHandlerSupport().calculateActionURL(facesContext, viewId);
284 }
285
286 public String getResourceURL(FacesContext facesContext, String path)
287 {
288 if (path.length() > 0 && path.charAt(0) == '/')
289 {
290 return facesContext.getExternalContext().getRequestContextPath() + path;
291 }
292
293 return path;
294
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public void renderView(FacesContext facesContext, UIViewRoot viewToRender) throws IOException, FacesException
308 {
309 if (viewToRender == null)
310 {
311 log.fatal("viewToRender must not be null");
312 throw new NullPointerException("viewToRender must not be null");
313 }
314
315
316 if (!viewToRender.isRendered())
317 {
318 if (log.isTraceEnabled())
319 log.trace("View is not rendered");
320 return;
321 }
322
323 ExternalContext externalContext = facesContext.getExternalContext();
324
325 String viewId = facesContext.getViewRoot().getViewId();
326
327 if (log.isTraceEnabled())
328 log.trace("Rendering JSP view: " + viewId);
329
330 ServletResponse response = (ServletResponse) externalContext.getResponse();
331 ServletRequest request = (ServletRequest) externalContext.getRequest();
332
333 Locale locale = viewToRender.getLocale();
334 response.setLocale(locale);
335 Config.set(request, Config.FMT_LOCALE, facesContext.getViewRoot().getLocale());
336
337 if(!buildView(response, externalContext, viewId)) {
338
339
340 return;
341 }
342
343
344 if (externalContext.getRequest() instanceof HttpServletRequest)
345 {
346 HttpServletRequest httpServletRequest = (HttpServletRequest) externalContext.getRequest();
347 HttpSession session = httpServletRequest.getSession(false);
348
349 if (session != null)
350 {
351 session.setAttribute(ViewHandler.CHARACTER_ENCODING_KEY, response.getCharacterEncoding());
352 }
353 }
354
355
356 RenderKitFactory renderFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
357 RenderKit renderKit = renderFactory.getRenderKit(facesContext, viewToRender.getRenderKitId());
358
359 ResponseWriter responseWriter = facesContext.getResponseWriter();
360 if (responseWriter == null)
361 {
362 responseWriter = renderKit.createResponseWriter(response.getWriter(), null,
363 ((HttpServletRequest) externalContext.getRequest()).getCharacterEncoding());
364 facesContext.setResponseWriter(responseWriter);
365 }
366
367 ResponseWriter oldResponseWriter = responseWriter;
368 StateMarkerAwareWriter stateAwareWriter = null;
369
370 StateManager stateManager = facesContext.getApplication().getStateManager();
371 if (stateManager.isSavingStateInClient(facesContext))
372 {
373 stateAwareWriter = new StateMarkerAwareWriter();
374
375
376
377
378 responseWriter = hookInStateAwareWriter(
379 oldResponseWriter, stateAwareWriter, renderKit, externalContext);
380 facesContext.setResponseWriter(responseWriter);
381 }
382
383 actuallyRenderView(facesContext, viewToRender);
384
385 facesContext.setResponseWriter(oldResponseWriter);
386
387
388
389
390 if (stateManager.isSavingStateInClient(facesContext))
391 {
392 stateAwareWriter.flushToWriter(response.getWriter());
393 }
394 else
395 {
396 stateManager.saveView(facesContext);
397 }
398
399
400
401 ViewResponseWrapper afterViewTagResponse = (ViewResponseWrapper) externalContext.getRequestMap().get(
402 AFTER_VIEW_TAG_CONTENT_PARAM);
403 externalContext.getRequestMap().remove(AFTER_VIEW_TAG_CONTENT_PARAM);
404
405 if (afterViewTagResponse != null)
406 {
407 afterViewTagResponse.flushToWriter(response.getWriter(),
408 facesContext.getExternalContext().getResponseCharacterEncoding());
409 }
410
411 response.flushBuffer();
412 }
413
414
415
416
417 private void actuallyRenderView(FacesContext facesContext,
418 UIViewRoot viewToRender) throws IOException {
419
420 ResponseWriter responseWriter = facesContext.getResponseWriter();
421
422
423
424 responseWriter.startDocument();
425
426
427 viewToRender.encodeAll(facesContext);
428
429
430 responseWriter.endDocument();
431
432 responseWriter.flush();
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 private ResponseWriter hookInStateAwareWriter(ResponseWriter oldResponseWriter, StateMarkerAwareWriter stateAwareWriter, RenderKit renderKit, ExternalContext externalContext) {
450 return oldResponseWriter.cloneWithWriter(stateAwareWriter);
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 }
467
468
469
470
471
472
473
474
475
476
477
478
479
480 private boolean buildView(ServletResponse response, ExternalContext externalContext, String viewId) throws IOException {
481 ViewResponseWrapper wrappedResponse = new ViewResponseWrapper((HttpServletResponse) response);
482
483 externalContext.setResponse(wrappedResponse);
484 try
485 {
486 externalContext.dispatch(viewId);
487 }
488 finally
489 {
490 externalContext.setResponse(response);
491 }
492
493 boolean errorResponse = wrappedResponse.getStatus() < 200 || wrappedResponse.getStatus() > 299;
494 if (errorResponse)
495 {
496 wrappedResponse.flushToWrappedResponse();
497 return false;
498 }
499
500
501 externalContext.getRequestMap().put(AFTER_VIEW_TAG_CONTENT_PARAM, wrappedResponse);
502
503 return true;
504 }
505
506
507
508
509 public UIViewRoot restoreView(FacesContext facesContext, String viewId)
510 {
511 Application application = facesContext.getApplication();
512 ViewHandler applicationViewHandler = application.getViewHandler();
513 String renderKitId = applicationViewHandler.calculateRenderKitId(facesContext);
514 String calculatedViewId = getViewHandlerSupport().calculateViewId(facesContext, viewId);
515 UIViewRoot viewRoot = application.getStateManager().restoreView(facesContext, calculatedViewId, renderKitId);
516 return viewRoot;
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543 public void writeState(FacesContext facesContext) throws IOException
544 {
545 StateManager stateManager = facesContext.getApplication().getStateManager();
546 if (stateManager.isSavingStateInClient(facesContext))
547 {
548
549 ExternalContext extContext = facesContext.getExternalContext();
550 if (!(JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript())) {
551 facesContext.getResponseWriter().write(FORM_STATE_MARKER);
552 }
553 }
554 else
555 {
556 stateManager.writeState(facesContext, new Object[2]);
557 }
558 }
559
560
561
562
563 private static class StateMarkerAwareWriter extends Writer
564 {
565 private StringBuilder buf;
566
567 public StateMarkerAwareWriter()
568 {
569 this.buf = new StringBuilder();
570 }
571
572 @Override
573 public void close() throws IOException
574 {
575 }
576
577 @Override
578 public void flush() throws IOException
579 {
580 }
581
582 @Override
583 public void write(char[] cbuf, int off, int len) throws IOException
584 {
585 if ((off < 0) || (off > cbuf.length) || (len < 0) ||
586 ((off + len) > cbuf.length) || ((off + len) < 0)) {
587 throw new IndexOutOfBoundsException();
588 } else if (len == 0) {
589 return;
590 }
591 buf.append(cbuf, off, len);
592 }
593
594 public StringBuilder getStringBuilder()
595 {
596 return buf;
597 }
598
599 public void flushToWriter(Writer writer) throws IOException
600 {
601 FacesContext facesContext = FacesContext.getCurrentInstance();
602 StateManager stateManager = facesContext.getApplication().getStateManager();
603
604 StringWriter stateWriter = new StringWriter();
605 ResponseWriter realWriter = facesContext.getResponseWriter();
606 facesContext.setResponseWriter(realWriter.cloneWithWriter(stateWriter));
607
608 Object serializedView = stateManager.saveView(facesContext);
609
610 stateManager.writeState(facesContext, serializedView);
611 facesContext.setResponseWriter(realWriter);
612
613 StringBuilder contentBuffer = getStringBuilder();
614 String state = stateWriter.getBuffer().toString();
615
616 ExternalContext extContext = facesContext.getExternalContext();
617 if (JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript()) {
618
619 write(contentBuffer, 0, contentBuffer.length(), writer);
620 writer.write(state);
621 } else {
622
623 int lastFormMarkerPos = 0;
624 int formMarkerPos = 0;
625
626 while ((formMarkerPos = contentBuffer.indexOf(FORM_STATE_MARKER, formMarkerPos)) > -1)
627 {
628
629 write(contentBuffer, lastFormMarkerPos, formMarkerPos, writer);
630
631 writer.write(state);
632 formMarkerPos += FORM_STATE_MARKER_LEN;
633 lastFormMarkerPos = formMarkerPos;
634 }
635
636 if (lastFormMarkerPos < contentBuffer.length()) {
637 write(contentBuffer, lastFormMarkerPos, contentBuffer.length(), writer);
638 }
639 }
640
641 }
642
643
644
645
646
647
648
649
650
651
652
653 private void write(StringBuilder contentBuffer, int beginIndex, int endIndex, Writer writer) throws IOException {
654 int index = beginIndex;
655 int bufferSize = 2048;
656 char[] bufToWrite = new char[bufferSize];
657
658 while (index < endIndex)
659 {
660 int maxSize = Math.min(bufferSize, endIndex - index);
661
662 contentBuffer.getChars(index, index + maxSize, bufToWrite, 0);
663 writer.write(bufToWrite, 0, maxSize);
664
665 index += bufferSize;
666 }
667 }
668 }
669 }