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 org.apache.myfaces.util.EnumerationIterator;
22  
23  import javax.faces.FacesException;
24  import javax.faces.application.ViewHandler;
25  import javax.faces.context.ExternalContext;
26  import javax.faces.context.FacesContext;
27  import javax.servlet.*;
28  import javax.servlet.http.HttpServletRequest;
29  import javax.servlet.http.HttpServletResponse;
30  import javax.servlet.http.HttpSession;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.net.MalformedURLException;
34  import java.net.URL;
35  import java.security.Principal;
36  import java.util.*;
37  import java.lang.reflect.Method;
38  
39  import org.apache.commons.logging.LogFactory;
40  import org.apache.commons.logging.Log;
41  import org.apache.myfaces.context.ReleaseableExternalContext;
42  
43  /**
44   * JSF 1.0 PRD2, 6.1.1
45   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
46   * @author Anton Koinov
47   * @version $Revision: 775389 $ $Date: 2009-05-15 18:23:28 -0500 (Fri, 15 May 2009) $
48   *
49   * Revision 1.11 Sylvain Vieujot
50   * Forward the message when an exception is thrown in dispatch
51   */
52  public class ServletExternalContextImpl
53      extends ExternalContext implements ReleaseableExternalContext
54  {
55  
56      private static final Log log = LogFactory.getLog(ServletExternalContextImpl.class);
57  
58      private static final String INIT_PARAMETER_MAP_ATTRIBUTE = InitParameterMap.class.getName();
59  
60      private ServletContext _servletContext;
61      private ServletRequest _servletRequest;
62      private ServletResponse _servletResponse;
63      private Map _applicationMap;
64      private Map _sessionMap;
65      private Map _requestMap;
66      private Map _requestParameterMap;
67      private Map _requestParameterValuesMap;
68      private Map _requestHeaderMap;
69      private Map _requestHeaderValuesMap;
70      private Map _requestCookieMap;
71      private Map _initParameterMap;
72      private boolean _isHttpServletRequest;
73      private String _requestServletPath;
74      private String _requestPathInfo;
75      private static Method setCharacterEncodingMethod = null;
76      
77      static {
78          try {
79              setCharacterEncodingMethod = ServletRequest.class.getMethod("setCharacterEncoding", new Class[]{String.class});
80          } catch (Exception e) {
81                      log.warn("Detecting request character encoding is disable.");
82                      log.warn("Failed to obtain ServletRequest#setCharacterEncoding() method: " + e);
83          }
84      } 
85  
86      public ServletExternalContextImpl(ServletContext servletContext,
87                                        ServletRequest servletRequest,
88                                        ServletResponse servletResponse)
89      {
90          _servletContext = servletContext;
91          _servletRequest = servletRequest;
92          _servletResponse = servletResponse;
93          _applicationMap = null;
94          _sessionMap = null;
95          _requestMap = null;
96          _requestParameterMap = null;
97          _requestParameterValuesMap = null;
98          _requestHeaderMap = null;
99          _requestHeaderValuesMap = null;
100         _requestCookieMap = null;
101         _initParameterMap = null;
102         _isHttpServletRequest = (servletRequest != null &&
103                                  servletRequest instanceof HttpServletRequest);
104         if (_isHttpServletRequest)
105         {
106             //HACK: MultipartWrapper scrambles the servletPath for some reason in Tomcat 4.1.29 embedded in JBoss 3.2.3!?
107             // (this was reported by frederic.auge [frederic.auge@laposte.net])
108             HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
109 
110             _requestServletPath = httpServletRequest.getServletPath();
111             _requestPathInfo = httpServletRequest.getPathInfo();
112 
113             // try to set character encoding as described in section 2.5.2.2 of JSF 1.1 spec
114             // we have to use reflection as method setCharacterEncoding is not supported Servlet API <= 2.3
115             try
116             {
117                 if (setCharacterEncodingMethod != null) {
118                     String contentType = httpServletRequest.getHeader("Content-Type");
119 
120                     String characterEncoding = lookupCharacterEncoding(contentType);
121 
122                     if (characterEncoding == null) {
123                         HttpSession session = httpServletRequest.getSession(false);
124 
125                         if (session != null) {
126                             characterEncoding = (String) session.getAttribute(ViewHandler.CHARACTER_ENCODING_KEY);
127                         }
128                     }
129 
130                     if (characterEncoding != null)
131                     {
132                         setCharacterEncodingMethod.invoke(servletRequest, new Object[]{characterEncoding});
133                     }
134                 }
135             } catch (Exception e)
136             {
137                 if (log.isWarnEnabled())
138                     log.warn("Failed to set character encoding " + e);
139             }
140         }
141     }
142 
143 
144     private String lookupCharacterEncoding(String contentType)
145     {
146         String characterEncoding = null;
147 
148         if (contentType != null)
149         {
150             int charsetFind = contentType.indexOf("charset=");
151             if (charsetFind != -1)
152             {
153                 if (charsetFind == 0)
154                 {
155                     //charset at beginning of Content-Type, curious
156                     characterEncoding = contentType.substring(8);
157                 }
158                 else
159                 {
160                     char charBefore = contentType.charAt(charsetFind - 1);
161                     if (charBefore == ';' || Character.isWhitespace(charBefore))
162                     {
163                         //Correct charset after mime type
164                         characterEncoding = contentType.substring(charsetFind + 8);
165                     }
166                 }
167                 if (log.isDebugEnabled()) log.debug("Incoming request has Content-Type header with character encoding " + characterEncoding);
168             }
169             else
170             {
171                 if (log.isDebugEnabled()) log.debug("Incoming request has Content-Type header without character encoding: " + contentType);
172             }
173         }
174         return characterEncoding;
175     }
176 
177 
178     public void release()
179     {
180         _servletContext = null;
181         _servletRequest = null;
182         _servletResponse = null;
183         _applicationMap = null;
184         _sessionMap = null;
185         _requestMap = null;
186         _requestParameterMap = null;
187         _requestParameterValuesMap = null;
188         _requestHeaderMap = null;
189         _requestHeaderValuesMap = null;
190         _requestCookieMap = null;
191         _initParameterMap = null;
192     }
193 
194 
195     public Object getSession(boolean create)
196     {
197         if (!_isHttpServletRequest)
198         {
199             throw new IllegalArgumentException("Only HttpServletRequest supported");
200         }
201         return ((HttpServletRequest)_servletRequest).getSession(create);
202     }
203 
204     public Object getContext()
205     {
206         return _servletContext;
207     }
208 
209     public Object getRequest()
210     {
211         return _servletRequest;
212     }
213 
214     public Object getResponse()
215     {
216         return _servletResponse;
217     }
218 
219     public void setResponse(Object response) {
220         if (response instanceof ServletResponse) {
221             this._servletResponse = (ServletResponse) response;
222         }
223     }
224 
225     public Map getApplicationMap()
226     {
227         if (_applicationMap == null)
228         {
229             _applicationMap = new ApplicationMap(_servletContext);
230         }
231         return _applicationMap;
232     }
233 
234     public Map getSessionMap()
235     {
236         if (_sessionMap == null)
237         {
238             if (!_isHttpServletRequest)
239             {
240                 throw new IllegalArgumentException("Only HttpServletRequest supported");
241             }
242             _sessionMap = new SessionMap((HttpServletRequest) _servletRequest);
243         }
244         return _sessionMap;
245     }
246 
247     public Map getRequestMap()
248     {
249         if (_requestMap == null)
250         {
251             _requestMap = new RequestMap(_servletRequest);
252         }
253         return _requestMap;
254     }
255 
256     public Map getRequestParameterMap()
257     {
258         if (_requestParameterMap == null)
259         {
260             _requestParameterMap = new RequestParameterMap(_servletRequest);
261         }
262         return _requestParameterMap;
263     }
264 
265     public Map getRequestParameterValuesMap()
266     {
267         if (_requestParameterValuesMap == null)
268         {
269             _requestParameterValuesMap = new RequestParameterValuesMap(_servletRequest);
270         }
271         return _requestParameterValuesMap;
272     }
273 
274     public Iterator getRequestParameterNames()
275     {
276         final Enumeration enumer = _servletRequest.getParameterNames();
277         Iterator it = new Iterator()
278         {
279             public boolean hasNext() {
280                 return enumer.hasMoreElements();
281             }
282 
283             public Object next() {
284                 return enumer.nextElement();
285             }
286 
287             public void remove() {
288                 throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
289             }
290         };
291         return it;
292     }
293 
294     public Map getRequestHeaderMap()
295     {
296         if (_requestHeaderMap == null)
297         {
298             if (!_isHttpServletRequest)
299             {
300                 throw new IllegalArgumentException("Only HttpServletRequest supported");
301             }
302             _requestHeaderMap = new RequestHeaderMap((HttpServletRequest)_servletRequest);
303         }
304         return _requestHeaderMap;
305     }
306 
307     public Map getRequestHeaderValuesMap()
308     {
309         if (_requestHeaderValuesMap == null)
310         {
311             if (!_isHttpServletRequest)
312             {
313                 throw new IllegalArgumentException("Only HttpServletRequest supported");
314             }
315             _requestHeaderValuesMap = new RequestHeaderValuesMap((HttpServletRequest)_servletRequest);
316         }
317         return _requestHeaderValuesMap;
318     }
319 
320     public Map getRequestCookieMap()
321     {
322         if (_requestCookieMap == null)
323         {
324             if (!_isHttpServletRequest)
325             {
326                 throw new IllegalArgumentException("Only HttpServletRequest supported");
327             }
328             _requestCookieMap = new CookieMap((HttpServletRequest)_servletRequest);
329         }
330         return _requestCookieMap;
331     }
332 
333     public Locale getRequestLocale()
334     {
335         return _servletRequest.getLocale();
336     }
337 
338     public String getRequestPathInfo()
339     {
340         if (!_isHttpServletRequest)
341         {
342             throw new IllegalArgumentException("Only HttpServletRequest supported");
343         }
344         //return ((HttpServletRequest)_servletRequest).getPathInfo();
345         //HACK: see constructor
346         return _requestPathInfo;
347     }
348 
349     public String getRequestContextPath()
350     {
351         if (!_isHttpServletRequest)
352         {
353             throw new IllegalArgumentException("Only HttpServletRequest supported");
354         }
355         return ((HttpServletRequest)_servletRequest).getContextPath();
356     }
357 
358     public String getInitParameter(String s)
359     {
360         return _servletContext.getInitParameter(s);
361     }
362 
363     public Map getInitParameterMap()
364     {
365         if (_initParameterMap == null)
366         {
367             // We cache it as an attribute in ServletContext itself (is this circular reference a problem?)
368             if ((_initParameterMap = (Map) _servletContext.getAttribute(INIT_PARAMETER_MAP_ATTRIBUTE)) == null)
369             {
370                 _initParameterMap = new InitParameterMap(_servletContext);
371                 _servletContext.setAttribute(INIT_PARAMETER_MAP_ATTRIBUTE, _initParameterMap);
372             }
373         }
374         return _initParameterMap;
375     }
376 
377     public Set getResourcePaths(String s)
378     {
379         return _servletContext.getResourcePaths(s);
380     }
381 
382     public InputStream getResourceAsStream(String s)
383     {
384         return _servletContext.getResourceAsStream(s);
385     }
386 
387     public String encodeActionURL(String s)
388     {
389         if (!_isHttpServletRequest)
390         {
391             throw new IllegalArgumentException("Only HttpServletRequest supported");
392         }
393         return ((HttpServletResponse)_servletResponse).encodeURL(s);
394     }
395 
396     public String encodeResourceURL(String s)
397     {
398         if (!_isHttpServletRequest)
399         {
400             throw new IllegalArgumentException("Only HttpServletRequest supported");
401         }
402         return ((HttpServletResponse)_servletResponse).encodeURL(s);
403     }
404 
405     public String encodeNamespace(String s)
406     {
407         return s;
408     }
409 
410     public void dispatch(String requestURI) throws IOException, FacesException
411     {
412         RequestDispatcher requestDispatcher
413             = _servletRequest.getRequestDispatcher(requestURI);
414         
415         // If there is no dispatcher, send NOT_FOUND
416         if (requestDispatcher == null)
417         {
418            ((HttpServletResponse)_servletResponse).sendError(
419                   HttpServletResponse.SC_NOT_FOUND);
420 
421            return;
422        } 
423         
424         try
425         {
426             requestDispatcher.forward(_servletRequest, _servletResponse);
427         }
428         catch (ServletException e)
429         {
430             if (e.getMessage() != null)
431             {
432                 throw new FacesException(e.getMessage(), e);
433             }
434             else
435             {
436                 throw new FacesException(e);
437             }
438         }
439     }
440 
441     public String getRequestServletPath()
442     {
443         if (!_isHttpServletRequest)
444         {
445             throw new IllegalArgumentException("Only HttpServletRequest supported");
446         }
447         //return ((HttpServletRequest)_servletRequest).getServletPath();
448         //HACK: see constructor
449         return _requestServletPath;
450     }
451 
452     public String getAuthType()
453     {
454         if (!_isHttpServletRequest)
455         {
456             throw new IllegalArgumentException("Only HttpServletRequest supported");
457         }
458         return ((HttpServletRequest)_servletRequest).getAuthType();
459     }
460 
461     public String getRemoteUser()
462     {
463         if (!_isHttpServletRequest)
464         {
465             throw new IllegalArgumentException("Only HttpServletRequest supported");
466         }
467         return ((HttpServletRequest)_servletRequest).getRemoteUser();
468     }
469 
470     public boolean isUserInRole(String role)
471     {
472         if (!_isHttpServletRequest)
473         {
474             throw new IllegalArgumentException("Only HttpServletRequest supported");
475         }
476         return ((HttpServletRequest)_servletRequest).isUserInRole(role);
477     }
478 
479     public Principal getUserPrincipal()
480     {
481         if (!_isHttpServletRequest)
482         {
483             throw new IllegalArgumentException("Only HttpServletRequest supported");
484         }
485         return ((HttpServletRequest)_servletRequest).getUserPrincipal();
486     }
487 
488     public void log(String message) {
489         _servletContext.log(message);
490     }
491 
492     public void log(String message, Throwable t) {
493         _servletContext.log(message, t);
494     }
495 
496     public void redirect(String url) throws IOException
497     {
498         if (_servletResponse instanceof HttpServletResponse)
499         {
500             ((HttpServletResponse)_servletResponse).sendRedirect(url);
501             FacesContext.getCurrentInstance().responseComplete();            
502         }
503         else
504         {
505             throw new IllegalArgumentException("Only HttpServletResponse supported");
506         }
507     }
508 
509     public Iterator getRequestLocales()
510     {
511         if (!_isHttpServletRequest)
512         {
513             throw new IllegalArgumentException("Only HttpServletRequest supported");
514         }
515         return new EnumerationIterator(((HttpServletRequest)_servletRequest).getLocales());
516     }
517 
518     public URL getResource(String s) throws MalformedURLException
519     {
520         return _servletContext.getResource(s);
521     }
522 }