1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.context.servlet;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.UnsupportedEncodingException;
24 import java.io.Writer;
25 import java.net.URLDecoder;
26 import java.net.URLEncoder;
27 import java.security.Principal;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35 import java.util.logging.Logger;
36
37 import javax.faces.FacesException;
38 import javax.faces.FactoryFinder;
39 import javax.faces.context.FacesContext;
40 import javax.faces.context.Flash;
41 import javax.faces.context.FlashFactory;
42 import javax.faces.context.PartialResponseWriter;
43 import javax.faces.context.PartialViewContext;
44 import javax.faces.lifecycle.ClientWindow;
45 import javax.faces.render.ResponseStateManager;
46 import javax.servlet.RequestDispatcher;
47 import javax.servlet.ServletContext;
48 import javax.servlet.ServletException;
49 import javax.servlet.ServletRequest;
50 import javax.servlet.ServletResponse;
51 import javax.servlet.http.Cookie;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.servlet.http.HttpServletResponse;
54 import javax.servlet.http.HttpSession;
55
56 import org.apache.myfaces.shared.context.flash.FlashImpl;
57 import org.apache.myfaces.util.EnumerationIterator;
58
59
60
61
62
63
64
65
66 public final class ServletExternalContextImpl extends ServletExternalContextImplBase
67 {
68
69 private static final Logger log = Logger.getLogger(ServletExternalContextImpl.class.getName());
70
71 private static final String URL_PARAM_SEPERATOR="&";
72 private static final char URL_QUERY_SEPERATOR='?';
73 private static final char URL_FRAGMENT_SEPERATOR='#';
74 private static final String URL_NAME_VALUE_PAIR_SEPERATOR="=";
75
76 private ServletRequest _servletRequest;
77 private ServletResponse _servletResponse;
78 private Map<String, Object> _sessionMap;
79 private Map<String, Object> _requestMap;
80 private Map<String, String> _requestParameterMap;
81 private Map<String, String[]> _requestParameterValuesMap;
82 private Map<String, String> _requestHeaderMap;
83 private Map<String, String[]> _requestHeaderValuesMap;
84 private Map<String, Object> _requestCookieMap;
85 private HttpServletRequest _httpServletRequest;
86 private HttpServletResponse _httpServletResponse;
87 private String _requestServletPath;
88 private String _requestPathInfo;
89 private FlashFactory _flashFactory;
90 private Flash _flash;
91 private FacesContext _currentFacesContext;
92
93 public ServletExternalContextImpl(final ServletContext servletContext,
94 final ServletRequest servletRequest,
95 final ServletResponse servletResponse)
96 {
97 super(servletContext);
98
99 _servletRequest = servletRequest;
100 _servletResponse = servletResponse;
101 _sessionMap = null;
102 _requestMap = null;
103 _requestParameterMap = null;
104 _requestParameterValuesMap = null;
105 _requestHeaderMap = null;
106 _requestHeaderValuesMap = null;
107 _requestCookieMap = null;
108 _httpServletRequest = isHttpServletRequest(servletRequest) ? (HttpServletRequest) servletRequest : null;
109 _httpServletResponse = isHttpServletResponse(servletResponse) ? (HttpServletResponse) servletResponse : null;
110
111 if (_httpServletRequest != null)
112 {
113
114
115
116 _requestServletPath = _httpServletRequest.getServletPath();
117 _requestPathInfo = _httpServletRequest.getPathInfo();
118 }
119 }
120
121 public ServletExternalContextImpl(final ServletContext servletContext,
122 final ServletRequest servletRequest,
123 final ServletResponse servletResponse,
124 final FlashFactory flashFactory)
125 {
126 this(servletContext, servletRequest, servletResponse);
127 _flashFactory = flashFactory;
128 }
129
130 public void release()
131 {
132 super.release();
133
134 _currentFacesContext = null;
135 _servletRequest = null;
136 _servletResponse = null;
137 _sessionMap = null;
138 _requestMap = null;
139 _requestParameterMap = null;
140 _requestParameterValuesMap = null;
141 _requestHeaderMap = null;
142 _requestHeaderValuesMap = null;
143 _requestCookieMap = null;
144 _httpServletRequest = null;
145 _httpServletResponse = null;
146 }
147
148 @Override
149 public Object getSession(boolean create)
150 {
151 checkHttpServletRequest();
152 return ((HttpServletRequest) _servletRequest).getSession(create);
153 }
154
155 @Override
156 public String getSessionId(boolean create)
157 {
158 checkHttpServletRequest();
159 HttpSession session = ((HttpServletRequest) _servletRequest).getSession(create);
160 if (session != null)
161 {
162 return session.getId();
163 }
164 else
165 {
166 return "";
167 }
168 }
169
170
171 @Override
172 public Object getRequest()
173 {
174 return _servletRequest;
175 }
176
177
178
179
180 @Override
181 public int getRequestContentLength()
182 {
183 return _servletRequest.getContentLength();
184 }
185
186 @Override
187 public Object getResponse()
188 {
189 return _servletResponse;
190 }
191
192
193
194
195 @Override
196 public int getResponseBufferSize()
197 {
198 return _servletResponse.getBufferSize();
199 }
200
201 @Override
202 public String getResponseContentType()
203 {
204 return _servletResponse.getContentType();
205 }
206
207 @Override
208 public OutputStream getResponseOutputStream() throws IOException
209 {
210 return _servletResponse.getOutputStream();
211 }
212
213
214
215
216 @Override
217 public Writer getResponseOutputWriter() throws IOException
218 {
219 return _servletResponse.getWriter();
220 }
221
222 @Override
223 public Map<String, Object> getSessionMap()
224 {
225 if (_sessionMap == null)
226 {
227 checkHttpServletRequest();
228 _sessionMap = new SessionMap(_httpServletRequest);
229 }
230 return _sessionMap;
231 }
232
233 @Override
234 public Map<String, Object> getRequestMap()
235 {
236 if (_requestMap == null)
237 {
238 _requestMap = new RequestMap(_servletRequest);
239 }
240 return _requestMap;
241 }
242
243 @Override
244 public Map<String, String> getRequestParameterMap()
245 {
246 if (_requestParameterMap == null)
247 {
248 _requestParameterMap = new RequestParameterMap(_servletRequest);
249 }
250 return _requestParameterMap;
251 }
252
253 @Override
254 public Map<String, String[]> getRequestParameterValuesMap()
255 {
256 if (_requestParameterValuesMap == null)
257 {
258 _requestParameterValuesMap = new RequestParameterValuesMap(_servletRequest);
259 }
260 return _requestParameterValuesMap;
261 }
262
263 @Override
264 public int getRequestServerPort()
265 {
266 return _servletRequest.getServerPort();
267 }
268
269 @Override
270 @SuppressWarnings("unchecked")
271 public Iterator<String> getRequestParameterNames()
272 {
273 return new EnumerationIterator(_servletRequest.getParameterNames());
274 }
275
276 @Override
277 public Map<String, String> getRequestHeaderMap()
278 {
279 if (_requestHeaderMap == null)
280 {
281 checkHttpServletRequest();
282 _requestHeaderMap = new RequestHeaderMap(_httpServletRequest);
283 }
284 return _requestHeaderMap;
285 }
286
287 @Override
288 public Map<String, String[]> getRequestHeaderValuesMap()
289 {
290 if (_requestHeaderValuesMap == null)
291 {
292 checkHttpServletRequest();
293 _requestHeaderValuesMap = new RequestHeaderValuesMap(_httpServletRequest);
294 }
295 return _requestHeaderValuesMap;
296 }
297
298
299
300 @Override
301 public Map<String, Object> getRequestCookieMap()
302 {
303 if (_requestCookieMap == null)
304 {
305 checkHttpServletRequest();
306 _requestCookieMap = new CookieMap(_httpServletRequest);
307 }
308
309 return _requestCookieMap;
310 }
311
312 @Override
313 public Locale getRequestLocale()
314 {
315 return _servletRequest.getLocale();
316 }
317
318 @Override
319 public String getRequestPathInfo()
320 {
321 checkHttpServletRequest();
322
323
324 return _requestPathInfo;
325 }
326
327 @Override
328 public String getRequestContentType()
329 {
330 return _servletRequest.getContentType();
331 }
332
333 @Override
334 public String getRequestContextPath()
335 {
336 checkHttpServletRequest();
337 return _httpServletRequest.getContextPath();
338 }
339
340 @Override
341 public String getRequestScheme()
342 {
343 return _servletRequest.getScheme();
344 }
345
346 @Override
347 public String encodeActionURL(final String url)
348 {
349 checkNull(url, "url");
350 checkHttpServletRequest();
351 String encodedUrl = ((HttpServletResponse) _servletResponse).encodeURL(url);
352 encodedUrl = encodeURL(encodedUrl, null);
353 return encodedUrl;
354 }
355
356 @Override
357 public String encodeBookmarkableURL(String baseUrl, Map<String,List<String>> parameters)
358 {
359 return encodeURL(baseUrl, parameters);
360 }
361
362 @Override
363 public String encodeResourceURL(final String url)
364 {
365 checkNull(url, "url");
366 checkHttpServletRequest();
367 return ((HttpServletResponse) _servletResponse).encodeURL(url);
368 }
369
370 @Override
371 public String encodeNamespace(final String s)
372 {
373 return s;
374 }
375
376 @Override
377 public String encodePartialActionURL(String url)
378 {
379 checkNull(url, "url");
380 checkHttpServletRequest();
381 return encodeURL(((HttpServletResponse) _servletResponse).encodeURL(url), null);
382 }
383
384 @Override
385 public String encodeRedirectURL(String baseUrl, Map<String,List<String>> parameters)
386 {
387 return _httpServletResponse.encodeRedirectURL(encodeURL(baseUrl, parameters));
388 }
389
390 @Override
391 public void dispatch(final String requestURI) throws IOException, FacesException
392 {
393 RequestDispatcher requestDispatcher = _servletRequest.getRequestDispatcher(requestURI);
394
395
396 if (requestDispatcher == null)
397 {
398 ((HttpServletResponse) _servletResponse).sendError(HttpServletResponse.SC_NOT_FOUND);
399
400 return;
401 }
402
403 try
404 {
405 requestDispatcher.forward(_servletRequest, _servletResponse);
406 }
407 catch (ServletException e)
408 {
409 if (e.getMessage() != null)
410 {
411 throw new FacesException(e.getMessage(), e);
412 }
413
414 throw new FacesException(e);
415
416 }
417 }
418
419 @Override
420 public String getRequestServerName()
421 {
422 return _servletRequest.getServerName();
423 }
424
425 @Override
426 public String getRequestServletPath()
427 {
428 checkHttpServletRequest();
429
430
431 return _requestServletPath;
432 }
433
434 @Override
435 public String getAuthType()
436 {
437 checkHttpServletRequest();
438 return _httpServletRequest.getAuthType();
439 }
440
441 @Override
442 public String getRemoteUser()
443 {
444 checkHttpServletRequest();
445 return _httpServletRequest.getRemoteUser();
446 }
447
448 @Override
449 public boolean isUserInRole(final String role)
450 {
451 checkNull(role, "role");
452 checkHttpServletRequest();
453 return _httpServletRequest.isUserInRole(role);
454 }
455
456 @Override
457 public Principal getUserPrincipal()
458 {
459 checkHttpServletRequest();
460 return _httpServletRequest.getUserPrincipal();
461 }
462
463 @Override
464 public void invalidateSession()
465 {
466 HttpSession session = (HttpSession) getSession(false);
467
468 if (session != null)
469 {
470 session.invalidate();
471 }
472 }
473
474
475
476
477 @Override
478 public boolean isResponseCommitted()
479 {
480 return _httpServletResponse.isCommitted();
481 }
482
483 @Override
484 public void redirect(final String url) throws IOException
485 {
486 FacesContext facesContext = getCurrentFacesContext();
487 PartialViewContext partialViewContext = facesContext.getPartialViewContext();
488 if (partialViewContext.isPartialRequest())
489 {
490 PartialResponseWriter writer = partialViewContext.getPartialResponseWriter();
491 this.setResponseContentType("text/xml");
492 this.setResponseCharacterEncoding("UTF-8");
493 this.addResponseHeader("Cache-control", "no-cache");
494 writer.startDocument();
495 writer.redirect(url);
496 writer.endDocument();
497 facesContext.responseComplete();
498 }
499 else if (_servletResponse instanceof HttpServletResponse)
500 {
501 ((HttpServletResponse) _servletResponse).sendRedirect(url);
502 facesContext.responseComplete();
503 }
504 else
505 {
506 throw new IllegalArgumentException("Only HttpServletResponse supported");
507 }
508 }
509
510
511
512
513 @Override
514 public void responseFlushBuffer() throws IOException
515 {
516 checkHttpServletResponse();
517 _httpServletResponse.flushBuffer();
518 }
519
520
521
522
523 @Override
524 public void responseReset()
525 {
526 checkHttpServletResponse();
527 _httpServletResponse.reset();
528 }
529
530
531
532
533 @Override
534 public void responseSendError(int statusCode, String message) throws IOException
535 {
536 checkHttpServletResponse();
537 if (message == null)
538 {
539 _httpServletResponse.sendError(statusCode);
540 }
541 else
542 {
543 _httpServletResponse.sendError(statusCode, message);
544 }
545 }
546
547 @Override
548 @SuppressWarnings("unchecked")
549 public Iterator<Locale> getRequestLocales()
550 {
551 checkHttpServletRequest();
552 return new EnumerationIterator(_httpServletRequest.getLocales());
553 }
554
555
556
557
558
559 @Override
560 public void setRequest(final java.lang.Object request)
561 {
562 this._servletRequest = (ServletRequest) request;
563 this._httpServletRequest = isHttpServletRequest(_servletRequest) ? (HttpServletRequest) _servletRequest : null;
564 this._httpServletRequest = isHttpServletRequest(_servletRequest) ? (HttpServletRequest) _servletRequest : null;
565 this._requestHeaderMap = null;
566 this._requestHeaderValuesMap = null;
567 this._requestMap = null;
568 this._requestParameterMap = null;
569 this._requestParameterValuesMap = null;
570 this._requestCookieMap = null;
571 this._sessionMap = null;
572 }
573
574
575
576
577
578
579 @Override
580 public void setRequestCharacterEncoding(final java.lang.String encoding) throws java.io.UnsupportedEncodingException
581 {
582
583 this._servletRequest.setCharacterEncoding(encoding);
584
585 }
586
587
588
589
590 @Override
591 public String getRequestCharacterEncoding()
592 {
593 return _servletRequest.getCharacterEncoding();
594 }
595
596
597
598
599 @Override
600 public String getResponseCharacterEncoding()
601 {
602 return _servletResponse.getCharacterEncoding();
603 }
604
605
606
607
608
609 @Override
610 public void setResponse(final java.lang.Object response)
611 {
612 this._servletResponse = (ServletResponse) response;
613 }
614
615
616
617
618 @Override
619 public void setResponseBufferSize(int size)
620 {
621 checkHttpServletResponse();
622 _httpServletResponse.setBufferSize(size);
623 }
624
625
626
627
628
629 @Override
630 public void setResponseCharacterEncoding(final java.lang.String encoding)
631 {
632 this._servletResponse.setCharacterEncoding(encoding);
633 }
634
635
636
637
638 @Override
639 public void setResponseContentLength(int length)
640 {
641 checkHttpServletResponse();
642 _httpServletResponse.setContentLength(length);
643 }
644
645 @Override
646 public void setResponseContentType(String contentType)
647 {
648
649 if (!_servletResponse.isCommitted())
650 {
651
652 _servletResponse.setContentType(contentType);
653 }
654 else
655 {
656
657 log.severe("Cannot set content type. Response already committed");
658 }
659 }
660
661
662
663
664 @Override
665 public void setResponseHeader(String name, String value)
666 {
667 checkHttpServletResponse();
668 _httpServletResponse.setHeader(name, value);
669 }
670
671 @Override
672 public void setResponseStatus(int statusCode)
673 {
674 checkHttpServletResponse();
675 _httpServletResponse.setStatus(statusCode);
676 }
677
678 private void checkHttpServletRequest()
679 {
680 if (_httpServletRequest == null)
681 {
682 throw new UnsupportedOperationException("Only HttpServletRequest supported");
683 }
684 }
685
686 private boolean isHttpServletRequest(final ServletRequest servletRequest)
687 {
688 return servletRequest instanceof HttpServletRequest;
689 }
690
691 private void checkHttpServletResponse()
692 {
693 if (_httpServletRequest == null)
694 {
695 throw new UnsupportedOperationException("Only HttpServletResponse supported");
696 }
697 }
698 private boolean isHttpServletResponse(final ServletResponse servletResponse)
699 {
700 return servletResponse instanceof HttpServletResponse;
701 }
702
703
704
705
706 @Override
707 public void addResponseCookie(final String name,
708 final String value, final Map<String, Object> properties)
709 {
710 checkHttpServletResponse();
711 Cookie cookie = new Cookie(name, value);
712 if (properties != null)
713 {
714 for (Map.Entry<String, Object> entry : properties.entrySet())
715 {
716 String propertyKey = entry.getKey();
717 Object propertyValue = entry.getValue();
718 if ("comment".equals(propertyKey))
719 {
720 cookie.setComment((String) propertyValue);
721 continue;
722 }
723 else if ("domain".equals(propertyKey))
724 {
725 cookie.setDomain((String)propertyValue);
726 continue;
727 }
728 else if ("maxAge".equals(propertyKey))
729 {
730 cookie.setMaxAge((Integer) propertyValue);
731 continue;
732 }
733 else if ("secure".equals(propertyKey))
734 {
735 cookie.setSecure((Boolean) propertyValue);
736 continue;
737 }
738 else if ("path".equals(propertyKey))
739 {
740 cookie.setPath((String) propertyValue);
741 continue;
742 }
743 else if ("httpOnly".equals(propertyKey))
744 {
745 cookie.setHttpOnly((Boolean) propertyValue);
746 continue;
747 }
748 throw new IllegalArgumentException("Unused key when creating Cookie");
749 }
750 }
751 _httpServletResponse.addCookie(cookie);
752 }
753
754 @Override
755 public void addResponseHeader(String name, String value)
756 {
757 _httpServletResponse.addHeader(name, value);
758 }
759
760 private String encodeURL(String baseUrl, Map<String, List<String>> parameters)
761 {
762 checkNull(baseUrl, "url");
763 checkHttpServletRequest();
764
765 String fragment = null;
766 String queryString = null;
767 Map<String, List<String>> paramMap = null;
768
769
770 int index = baseUrl.indexOf(URL_FRAGMENT_SEPERATOR);
771 if (index != -1)
772 {
773 fragment = baseUrl.substring(index+1);
774 baseUrl = baseUrl.substring(0,index);
775 }
776
777
778 index = baseUrl.indexOf(URL_QUERY_SEPERATOR);
779 if (index != -1)
780 {
781 queryString = baseUrl.substring(index + 1);
782 baseUrl = baseUrl.substring(0, index);
783 String[] nameValuePairs = queryString.split(URL_PARAM_SEPERATOR);
784 for (int i = 0; i < nameValuePairs.length; i++)
785 {
786 String[] currentPair = nameValuePairs[i].split(URL_NAME_VALUE_PAIR_SEPERATOR);
787 String currentName = currentPair[0];
788
789 if (paramMap == null)
790 {
791 paramMap = new HashMap<String, List<String>>();
792 }
793
794 List<String> values = paramMap.get(currentName);
795 if (values == null)
796 {
797 values = new ArrayList<String>(1);
798 paramMap.put(currentName, values);
799 }
800
801 try
802 {
803 values.add(currentPair.length > 1
804 ? URLDecoder.decode(currentPair[1], getResponseCharacterEncoding())
805 : "");
806 }
807 catch (UnsupportedEncodingException e)
808 {
809
810 throw new UnsupportedOperationException("Encoding type=" + getResponseCharacterEncoding()
811 + " not supported", e);
812 }
813 }
814 }
815
816
817 if (parameters != null && parameters.size() > 0)
818 {
819 for (Map.Entry<String, List<String>> pair : parameters.entrySet())
820 {
821 if (pair.getKey() != null && pair.getKey().trim().length() != 0)
822 {
823 if (paramMap == null)
824 {
825 paramMap = new HashMap<String, List<String>>();
826 }
827 paramMap.put(pair.getKey(), pair.getValue());
828 }
829 }
830 }
831
832 FacesContext facesContext = getCurrentFacesContext();
833 ClientWindow window = facesContext.getExternalContext().getClientWindow();
834 if (window != null && window.isClientWindowRenderModeEnabled(facesContext))
835 {
836 if (paramMap == null)
837 {
838 paramMap = new HashMap<String, List<String>>();
839 }
840
841 if (!paramMap.containsKey(ResponseStateManager.CLIENT_WINDOW_URL_PARAM))
842 {
843 paramMap.put(ResponseStateManager.CLIENT_WINDOW_URL_PARAM, Arrays.asList(window.getId()));
844 }
845
846 Map<String, String> additionalQueryURLParameters = window.getQueryURLParameters(facesContext);
847 if (additionalQueryURLParameters != null)
848 {
849 for (Map.Entry<String , String> entry : additionalQueryURLParameters.entrySet())
850 {
851 paramMap.put(entry.getKey(), Arrays.asList(entry.getValue()));
852 }
853 }
854 }
855
856 boolean hasParams = paramMap != null && paramMap.size()>0;
857
858 if (!hasParams && fragment == null)
859 {
860 return baseUrl;
861 }
862
863
864 StringBuilder newUrl = new StringBuilder(baseUrl);
865
866
867 if (hasParams)
868 {
869 boolean isFirstPair = true;
870 for (Map.Entry<String, List<String>> pair : paramMap.entrySet())
871 {
872 for (String value : pair.getValue())
873 {
874 if (!isFirstPair)
875 {
876 newUrl.append(URL_PARAM_SEPERATOR);
877 }
878 else
879 {
880 newUrl.append(URL_QUERY_SEPERATOR);
881 isFirstPair = false;
882 }
883
884 newUrl.append(pair.getKey());
885 newUrl.append(URL_NAME_VALUE_PAIR_SEPERATOR);
886 try
887 {
888 newUrl.append(URLEncoder.encode(value,getResponseCharacterEncoding()));
889 }
890 catch (UnsupportedEncodingException e)
891 {
892
893 throw new UnsupportedOperationException("Encoding type=" + getResponseCharacterEncoding()
894 + " not supported", e);
895 }
896 }
897 }
898 }
899
900
901 if (fragment != null)
902 {
903 newUrl.append(URL_FRAGMENT_SEPERATOR);
904 newUrl.append(fragment);
905 }
906
907 return newUrl.toString();
908 }
909
910
911
912
913 public Flash getFlash()
914 {
915 if (_flash == null)
916 {
917 if (_flashFactory == null)
918 {
919 _flashFactory = (FlashFactory) FactoryFinder.getFactory(
920 FactoryFinder.FLASH_FACTORY);
921 if (_flashFactory == null)
922 {
923
924 _flash = FlashImpl.getCurrentInstance(this);
925 }
926 else
927 {
928 _flash = _flashFactory.getFlash(true);
929 }
930 }
931 else
932 {
933 _flash = _flashFactory.getFlash(true);
934 }
935 }
936 return _flash;
937
938 }
939
940 @Override
941 public boolean isSecure()
942 {
943 return _servletRequest.isSecure();
944 }
945
946 @Override
947 public int getSessionMaxInactiveInterval()
948 {
949 HttpSession session = _httpServletRequest.getSession();
950 return session.getMaxInactiveInterval();
951 }
952
953 @Override
954 public void setSessionMaxInactiveInterval(int interval)
955 {
956 HttpSession session = _httpServletRequest.getSession();
957 session.setMaxInactiveInterval(interval);
958 }
959
960 protected FacesContext getCurrentFacesContext()
961 {
962 if (_currentFacesContext == null)
963 {
964 _currentFacesContext = FacesContext.getCurrentInstance();
965 }
966 return _currentFacesContext;
967 }
968 }