View Javadoc

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