View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * Implements the external context for servlet request. JSF 1.2, 6.1.3
61   *
62   * @author Manfred Geiler (latest modification by $Author$)
63   * @author Anton Koinov
64   * @version $Revision$ $Date$
65   */
66  public final class ServletExternalContextImpl extends ServletExternalContextImplBase
67  {
68      //private static final Log log = LogFactory.getLog(ServletExternalContextImpl.class);
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); // initialize ServletExternalContextImplBase
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             // HACK: MultipartWrapper scrambles the servletPath for some reason in Tomcat 4.1.29 embedded in JBoss
114             // 3.2.3!?
115             // (this was reported by frederic.auge [frederic.auge@laposte.net])
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(); // releases fields on ServletExternalContextImplBase
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      * @since 2.0
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      * @since 2.0
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      * @since JSF 2.0
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     // FIXME: See with the EG if we can get the return value changed to Map<String, Cookie> as it
299     //        would be more elegant -= Simon Lessard =-
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         // return (_httpServletRequest).getPathInfo();
323         // HACK: see constructor
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         // If there is no dispatcher, send NOT_FOUND
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         // return (_httpServletRequest).getServletPath();
430         // HACK: see constructor
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      * @since 2.0
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      * @since 2.0
512      */
513     @Override
514     public void responseFlushBuffer() throws IOException
515     {
516         checkHttpServletResponse();
517         _httpServletResponse.flushBuffer();
518     }
519 
520     /**
521      * @since 2.0
522      */
523     @Override
524     public void responseReset()
525     {
526         checkHttpServletResponse();
527         _httpServletResponse.reset();
528     }
529 
530     /**
531      * @since 2.0
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      * @since JSF 1.2
557      * @param request
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      * @since JSF 1.2
576      * @param encoding
577      * @throws java.io.UnsupportedEncodingException
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      * @since JSF 1.2
589      */
590     @Override
591     public String getRequestCharacterEncoding()
592     {
593         return _servletRequest.getCharacterEncoding();
594     }
595 
596     /**
597      * @since JSF 1.2
598      */
599     @Override
600     public String getResponseCharacterEncoding()
601     {
602         return _servletResponse.getCharacterEncoding();
603     }
604 
605     /**
606      * @since JSF 1.2
607      * @param response
608      */
609     @Override
610     public void setResponse(final java.lang.Object response)
611     {
612         this._servletResponse = (ServletResponse) response;
613     }
614 
615     /**
616      * @since 2.0
617      */
618     @Override
619     public void setResponseBufferSize(int size)
620     {
621         checkHttpServletResponse();
622         _httpServletResponse.setBufferSize(size);
623     }
624 
625     /**
626      * @since JSF 1.2
627      * @param encoding
628      */
629     @Override
630     public void setResponseCharacterEncoding(final java.lang.String encoding)
631     {
632         this._servletResponse.setCharacterEncoding(encoding);
633     }
634 
635     /**
636      * @since 2.0
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         // If the response has not been committed yet.
649         if (!_servletResponse.isCommitted())
650         {
651             // Sets the content type of the response being sent to the client
652             _servletResponse.setContentType(contentType);
653         }
654         else
655         {
656             // I did not throw an exception just to be sure nothing breaks.
657             log.severe("Cannot set content type. Response already committed");
658         }
659     }
660 
661     /**
662      * @since 2.0
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      * @since JSF 2.0
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         //extract any URL fragment
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         //extract the current query string and add the params to the paramMap
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                     //shouldn't ever get here
810                     throw new UnsupportedOperationException("Encoding type=" + getResponseCharacterEncoding()
811                                                             + " not supported", e);
812                 }
813             }
814         }
815 
816         //add/update with new params on the paramMap
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         // start building the new URL
864         StringBuilder newUrl = new StringBuilder(baseUrl);
865 
866         //now add the updated param list onto the url
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                         //shouldn't ever get here
893                         throw new UnsupportedOperationException("Encoding type=" + getResponseCharacterEncoding()
894                                                                 + " not supported", e);
895                     }
896                 }
897             }
898         }
899 
900         //add the fragment back on (if any)
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      * @since 2.0
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                     //Fallback to servlet default flash
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         //return FlashImpl.getCurrentInstance(this);
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 }