dev@javaserverfaces.java.net

[REVIEW] Call setCharacterEncoding() before calling ResponseStateMananger.isPostBack()

From: Ryan Lubke <Ryan.Lubke_at_Sun.COM>
Date: Thu, 18 Aug 2005 09:05:10 -0700

This changebundle corrects an issue with the RI running against the latest
version of glassfish.

Problem description: Systest failure due to the fact that
ResponseStateManager.isPostBack()
   (which interogates request parameters) is called before we make a
call to
   ServletRequest.setCharacterEncoding() in ViewHandler.restoreView().
   ServletRequest.setCharacterEncoding() must be called before any
request paramer
   is read or any call to getReader().



SECTION: Modified Files
----------------------------
M src/com/sun/faces/application/ViewHandlerImpl.java
M src/com/sun/faces/lifecycle/RestoreViewPhase.java
  - move the logic that would parse the content-type request header
    from ViewHandlerImpl.restoreView() to a private
    method in RestoreViewPhase. This private method is called
    before isPostBack().


SECTION: Diffs
----------------------------
Index: src/com/sun/faces/application/ViewHandlerImpl.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java,v
retrieving revision 1.56
diff -u -r1.56 ViewHandlerImpl.java
--- src/com/sun/faces/application/ViewHandlerImpl.java 10 Aug 2005
13:35:38 -0000 1.56
+++ src/com/sun/faces/application/ViewHandlerImpl.java 18 Aug 2005
16:04:39 -0000
@@ -284,59 +284,7 @@
             throw new NullPointerException(message);
         }
 
- ExternalContext extContext = context.getExternalContext();
-
- // set the request character encoding. NOTE! This MUST be done
- // before any request praameter is accessed.
-
- /*
- HttpServletRequest request =
- (HttpServletRequest) extContext.getRequest();
- */
- Map headerMap = extContext.getRequestHeaderMap();
- String
- contentType = null,
- charEnc = null;
-
- // look for a charset in the Content-Type header first.
- if (null != (contentType = (String)
headerMap.get("Content-Type"))) {
- // see if this header had a charset
- String charsetStr = "charset=";
- int
- len = charsetStr.length(),
- i = 0;
-
- // if we have a charset in this Content-Type header AND it
- // has a non-zero length.
- if (-1 != (i = contentType.indexOf(charsetStr)) &&
- (i + len < contentType.length())) {
- charEnc = contentType.substring(i + len);
- }
- }
- // failing that, look in the session for a previously saved one
- if (null == charEnc) {
- if (null != extContext.getSession(false)) {
- charEnc = (String) extContext.getSessionMap().get
- (CHARACTER_ENCODING_KEY);
- }
- }
- if (null != charEnc) {
- try {
- if (logger.isLoggable(Level.FINE)) {
- logger.fine("set character encoding on request to "
- + charEnc);
- }
- Object request = extContext.getRequest();
- if (request instanceof ServletRequest) {
- ((ServletRequest)
request).setCharacterEncoding(charEnc);
- }
- } catch (java.io.UnsupportedEncodingException uee) {
- if (logger.isLoggable(Level.SEVERE)) {
- logger.log(Level.SEVERE,uee.getMessage(), uee);
- }
- throw new FacesException(uee);
- }
- }
+ ExternalContext extContext = context.getExternalContext();
 
         String mapping = getFacesMapping(context);
         UIViewRoot viewRoot = null;
Index: src/com/sun/faces/lifecycle/RestoreViewPhase.java
===================================================================
RCS file:
/cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/lifecycle/RestoreViewPhase.java,v
retrieving revision 1.26
diff -u -r1.26 RestoreViewPhase.java
--- src/com/sun/faces/lifecycle/RestoreViewPhase.java 21 Jul 2005
13:46:30 -0000 1.26
+++ src/com/sun/faces/lifecycle/RestoreViewPhase.java 18 Aug 2005
16:04:39 -0000
@@ -18,12 +18,15 @@
 import javax.el.ValueExpression;
 import javax.faces.FacesException;
 import javax.faces.application.ViewExpiredException;
+import javax.faces.application.ViewHandler;
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewRoot;
 import javax.faces.context.FacesContext;
+import javax.faces.context.ExternalContext;
 import javax.faces.event.PhaseId;
 import javax.faces.render.ResponseStateManager;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.ServletRequest;
 
 import com.sun.faces.util.Util;
 
@@ -140,7 +143,9 @@
                 Util.NULL_REQUEST_VIEW_ERROR_MESSAGE_ID));
         }
 
- if (isPostback(facesContext)) {
+ setCharacterEncoding(facesContext.getExternalContext());
+
+ if (isPostback(facesContext)) {
         // try to restore the view
         if (null == (viewRoot = (Util.getViewHandler(facesContext)).
              restoreView(facesContext, viewId))) {
@@ -205,6 +210,56 @@
             doPerComponentActions(context, (UIComponent) kids.next());
         }
       
+ }
+
+
+ private static void setCharacterEncoding(ExternalContext extContext) {
+
+ // set the request character encoding. NOTE! This MUST be done
+ // before any request parameter is accessed
+
+ Map<String,String> headerMap = extContext.getRequestHeaderMap();
+ String contentType = headerMap.get("Content-Type");
+ String charEnc = null;
+
+ // look for a charset in the Content-Type header first.
+ if (null != contentType) {
+ // see if this header had a charset
+ String charsetStr = "charset=";
+ int len = charsetStr.length();
+ int idx = contentType.indexOf(charsetStr);
+
+ // if we have a charset in this Content-Type header AND it
+ // has a non-zero length.
+ if (idx != -1 && idx + len < contentType.length()) {
+ charEnc = contentType.substring(idx + len);
+ }
+ }
+
+ // failing that, look in the session for a previously saved one
+ if (null == charEnc) {
+ if (null != extContext.getSession(false)) {
+ charEnc = (String) extContext.getSessionMap().get
+ (ViewHandler.CHARACTER_ENCODING_KEY);
+ }
+ }
+ if (null != charEnc) {
+ try {
+ if (logger.isLoggable(Level.FINE)) {
+ logger.fine("set character encoding on request to "
+ + charEnc);
+ }
+ Object request = extContext.getRequest();
+ if (request instanceof ServletRequest) {
+ ((ServletRequest)
request).setCharacterEncoding(charEnc);
+ }
+ } catch (java.io.UnsupportedEncodingException uee) {
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, uee.getMessage(), uee);
+ }
+ throw new FacesException(uee);
+ }
+ }
     }
 
     // The testcase for this class is TestRestoreViewPhase.java