You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mm...@apache.org on 2007/10/26 13:39:20 UTC

svn commit: r588608 - in /myfaces: core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/ core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/ shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/c...

Author: mmarinschek
Date: Fri Oct 26 04:39:18 2007
New Revision: 588608

URL: http://svn.apache.org/viewvc?rev=588608&view=rev
Log:
https://issues.apache.org/jira/browse/MYFACES-1742 (MYFACES-1742): Improved view-state handling in View-Handler. Thanks to Michael Kurz.

Modified:
    myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/JspViewHandlerImpl.java
    myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormRenderer.java
    myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlResponseStateManager.java
    myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
    myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java

Modified: myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/JspViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/JspViewHandlerImpl.java?rev=588608&r1=588607&r2=588608&view=diff
==============================================================================
--- myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/JspViewHandlerImpl.java (original)
+++ myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/application/jsp/JspViewHandlerImpl.java Fri Oct 26 04:39:18 2007
@@ -20,6 +20,8 @@
 import org.apache.myfaces.application.DefaultViewHandlerSupport;
 import org.apache.myfaces.application.InvalidViewIdException;
 import org.apache.myfaces.application.ViewHandlerSupport;
+import org.apache.myfaces.shared_impl.config.MyfacesConfig;
+import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
 
 import javax.faces.FacesException;
 import javax.faces.FactoryFinder;
@@ -414,17 +416,51 @@
      */
     public void writeState(FacesContext facesContext) throws IOException
     {
-        facesContext.getResponseWriter().write(FORM_STATE_MARKER);
+        // Only write state marker if javascript view state is disabled
+    	ExternalContext extContext = facesContext.getExternalContext();
+        if (!(JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript())) {
+        	facesContext.getResponseWriter().write(FORM_STATE_MARKER);
+        }
     }
 
     /**
      * Writes the response and replaces the state marker tags with the state information for the current context
      */
-    private static class StateMarkerAwareWriter extends StringWriter
+    private static class StateMarkerAwareWriter extends Writer
     {
-        public StateMarkerAwareWriter()
-        {
-        }
+		private StringBuilder buf;
+
+		public StateMarkerAwareWriter()
+		{
+			this.buf = new StringBuilder();
+		}
+
+		@Override
+		public void close() throws IOException
+		{
+		}
+
+		@Override
+		public void flush() throws IOException
+		{
+		}
+
+		@Override
+		public void write(char[] cbuf, int off, int len) throws IOException
+		{
+			if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+					((off + len) > cbuf.length) || ((off + len) < 0)) {
+				throw new IndexOutOfBoundsException();
+			} else if (len == 0) {
+				return;
+			}
+			buf.append(cbuf, off, len);
+		}
+
+		public StringBuilder getStringBuilder()
+		{
+			return buf;
+		}
 
         public void flushToWriter(Writer writer) throws IOException
         {
@@ -440,32 +476,60 @@
             stateManager.writeState(facesContext, serializedView);
             facesContext.setResponseWriter(realWriter);
 
-            StringBuffer contentBuffer = getBuffer();
-            StringBuffer state = stateWriter.getBuffer();
+            StringBuilder contentBuffer = getStringBuilder();
+            String state = stateWriter.getBuffer().toString();
 
-            int form_marker;
-            while ((form_marker = contentBuffer.indexOf(JspViewHandlerImpl.FORM_STATE_MARKER)) > -1 )
-            {
-                //FORM_STATE_MARKER found, replace it
-                contentBuffer.replace(form_marker, form_marker + FORM_STATE_MARKER_LEN, state.toString());
+            ExternalContext extContext = facesContext.getExternalContext();
+            if (JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript()) {
+            	// If javascript viewstate is enabled no state markers were written
+            	write(contentBuffer, 0, contentBuffer.length(), writer);
+            	writer.write(state);
+            } else {
+            	// If javascript viewstate is disabled state markers must be replaced
+            	int lastFormMarkerPos = 0;
+            	int formMarkerPos = 0;
+            	// Find all state markers and write out actual state instead
+            	while ((formMarkerPos = contentBuffer.indexOf(FORM_STATE_MARKER, formMarkerPos)) > -1)
+            	{
+            		// Write content before state marker
+            		write(contentBuffer, lastFormMarkerPos, formMarkerPos, writer);
+            		// Write state and move position in buffer after marker
+            		writer.write(state);
+            		formMarkerPos += FORM_STATE_MARKER_LEN;
+            		lastFormMarkerPos = formMarkerPos;
+            	}
+                // Write content after last state marker
+                if (lastFormMarkerPos < contentBuffer.length()) {
+                	write(contentBuffer, lastFormMarkerPos, contentBuffer.length(), writer);
+                }
             }
+            
+        }
 
-            int bufferLength = contentBuffer.length();
-            int index = 0;
-            int bufferSize = 512;
+        /**
+         * Writes the content of the specified StringBuffer from index 
+         * <code>beginIndex</code> to index <code>endIndex - 1</code>.
+         * 
+         * @param contentBuffer  the <code>StringBuffer</code> to copy content from
+         * @param begin  the beginning index, inclusive.
+         * @param end  the ending index, exclusive
+         * @param writer  the <code>Writer</code> to write to
+         * @throws IOException  if an error occurs writing to specified <code>Writer</code>
+         */
+        private void write(StringBuilder contentBuffer, int beginIndex, int endIndex, Writer writer) throws IOException {
+            int index = beginIndex;
+            int bufferSize = 2048;
+            char[] bufToWrite = new char[bufferSize];
 
-            while (index < bufferLength)
+            while (index < endIndex)
             {
-                int maxSize = Math.min(bufferSize, bufferLength - index);
-                char[] bufToWrite = new char[maxSize];
+                int maxSize = Math.min(bufferSize, endIndex - index);
 
                 contentBuffer.getChars(index, index + maxSize, bufToWrite, 0);
-                writer.write(bufToWrite);
+                writer.write(bufToWrite, 0, maxSize);
 
                 index += bufferSize;
             }
-
         }
     }
-
 }

Modified: myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormRenderer.java?rev=588608&r1=588607&r2=588608&view=diff
==============================================================================
--- myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormRenderer.java (original)
+++ myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlFormRenderer.java Fri Oct 26 04:39:18 2007
@@ -15,7 +15,17 @@
  */
 package org.apache.myfaces.renderkit.html;
 
+import java.io.IOException;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.shared_impl.config.MyfacesConfig;
+import org.apache.myfaces.shared_impl.renderkit.html.HTML;
 import org.apache.myfaces.shared_impl.renderkit.html.HtmlFormRendererBase;
+import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
 
 
 /**
@@ -28,5 +38,23 @@
         extends HtmlFormRendererBase
 {
     //private static final Log log = LogFactory.getLog(HtmlFormRenderer.class);
-
+	
+	@Override
+	protected void afterFormElementsEnd(FacesContext facesContext,
+			UIComponent component) throws IOException {
+		super.afterFormElementsEnd(facesContext, component);
+		
+        ResponseWriter writer = facesContext.getResponseWriter();
+        ExternalContext extContext = facesContext.getExternalContext();
+        
+        // If javascript viewstate is enabled write empty hidden input in forms 
+        if (JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript()) {
+            writer.startElement(HTML.INPUT_ELEM, null);
+            writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
+            writer.writeAttribute(HTML.NAME_ATTR, HtmlResponseStateManager.VIEW_STATE_PARAM, null);
+            writer.writeAttribute(HTML.ID_ATTR, HtmlResponseStateManager.VIEW_STATE_PARAM, null);
+            writer.writeAttribute(HTML.VALUE_ATTR, "", null);
+            writer.endElement(HTML.INPUT_ELEM);
+        }
+	}
 }

Modified: myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlResponseStateManager.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlResponseStateManager.java?rev=588608&r1=588607&r2=588608&view=diff
==============================================================================
--- myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlResponseStateManager.java (original)
+++ myfaces/core/branches/1_2_1/impl/src/main/java/org/apache/myfaces/renderkit/html/HtmlResponseStateManager.java Fri Oct 26 04:39:18 2007
@@ -18,10 +18,14 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
+import org.apache.myfaces.shared_impl.config.MyfacesConfig;
 import org.apache.myfaces.shared_impl.renderkit.html.HTML;
+import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils;
 import org.apache.myfaces.shared_impl.util.StateUtils;
 
 import javax.faces.application.StateManager;
+import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.context.ResponseWriter;
 import javax.faces.render.RenderKitFactory;
@@ -95,13 +99,21 @@
                                        ResponseWriter responseWriter,
                                        Object savedState) throws IOException
     {
-        responseWriter.startElement(HTML.INPUT_ELEM, null);
-        responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
-        responseWriter.writeAttribute(HTML.NAME_ATTR, STANDARD_STATE_SAVING_PARAM, null);
-        responseWriter.writeAttribute(HTML.ID_ATTR, STANDARD_STATE_SAVING_PARAM, null);
-        responseWriter.writeAttribute(HTML.VALUE_ATTR, StateUtils.construct(savedState,
-                facesContext.getExternalContext()), null);
-        responseWriter.endElement(HTML.INPUT_ELEM);
+    	String serializedState = StateUtils.construct(savedState,
+                facesContext.getExternalContext());
+        ExternalContext extContext = facesContext.getExternalContext();
+        // Write Javascript viewstate if enabled and if javascript is allowed,
+        // otherwise write hidden input
+        if (JavascriptUtils.isJavascriptAllowed(extContext) && MyfacesConfig.getCurrentInstance(extContext).isViewStateJavascript()) {
+        	HtmlRendererUtils.renderViewStateJavascript(facesContext, STANDARD_STATE_SAVING_PARAM, serializedState);
+        } else {
+        	responseWriter.startElement(HTML.INPUT_ELEM, null);
+        	responseWriter.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
+        	responseWriter.writeAttribute(HTML.NAME_ATTR, STANDARD_STATE_SAVING_PARAM, null);
+        	responseWriter.writeAttribute(HTML.ID_ATTR, STANDARD_STATE_SAVING_PARAM, null);
+        	responseWriter.writeAttribute(HTML.VALUE_ATTR, serializedState, null);
+        	responseWriter.endElement(HTML.INPUT_ELEM);
+        }
     }
 
     private void writeRenderKitIdField(FacesContext facesContext,

Modified: myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java?rev=588608&r1=588607&r2=588608&view=diff
==============================================================================
--- myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java (original)
+++ myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java Fri Oct 26 04:39:18 2007
@@ -74,6 +74,8 @@
     public static final String INIT_PARAM_CONFIG_REFRESH_PERIOD = "org.apache.myfaces.CONFIG_REFRESH_PERIOD";
     public static final long INIT_PARAM_CONFIG_REFRESH_PERIOD_DEFAULT = 2;
 
+    private static final String  INIT_PARAM_VIEWSTATE_JAVASCRIPT = "org.apache.myfaces.VIEWSTATE_JAVASCRIPT";
+    private static final boolean INIT_PARAM_VIEWSTATE_JAVASCRIPT_DEFAULT = false;
 
     private boolean _prettyHtml;
     private boolean _detectJavascript;
@@ -84,6 +86,7 @@
     private boolean _checkExtensionsFilter;
     private boolean _readonlyAsDisabledForSelect;
     private long _configRefreshPeriod;
+    private boolean _viewStateJavascript;
 
 
     private static final boolean TOMAHAWK_AVAILABLE;
@@ -166,6 +169,9 @@
         myfacesConfig.setConfigRefreshPeriod(getLongInitParameter(extCtx, INIT_PARAM_CONFIG_REFRESH_PERIOD,
                 INIT_PARAM_CONFIG_REFRESH_PERIOD_DEFAULT));
 
+        myfacesConfig.setViewStateJavascript(getBooleanInitParameter(extCtx, INIT_PARAM_VIEWSTATE_JAVASCRIPT,
+                INIT_PARAM_VIEWSTATE_JAVASCRIPT_DEFAULT));
+
 
         if (TOMAHAWK_AVAILABLE)
         {
@@ -394,5 +400,18 @@
 	public void setCheckExtensionsFilter(boolean extensionsFilter)
 	{
 		_checkExtensionsFilter = extensionsFilter;
+	}
+
+    /**
+     * 
+     */
+	public boolean isViewStateJavascript()
+	{
+		return _viewStateJavascript;
+	}
+
+	private void setViewStateJavascript(boolean viewStateJavascript)
+	{
+		_viewStateJavascript = viewStateJavascript;
 	}
 }

Modified: myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java?rev=588608&r1=588607&r2=588608&view=diff
==============================================================================
--- myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java (original)
+++ myfaces/shared/branches/3_0_1/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlRendererUtils.java Fri Oct 26 04:39:18 2007
@@ -1601,6 +1601,35 @@
         return (String)component.getAttributes().get(JSFAttr.STYLE_LOCATION);
     }
 
+    public static void renderViewStateJavascript(FacesContext facesContext, String hiddenId, String serializedState) throws IOException {
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.startElement(HTML.SCRIPT_ELEM, null);
+        writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
+
+        final ExternalContext externalContext = facesContext.getExternalContext();
+		final MyfacesConfig currentInstance = MyfacesConfig.getCurrentInstance(externalContext);
+
+        ScriptContext context = new ScriptContext(currentInstance.isPrettyHtml());
+        context.prettyLine();
+        context.increaseIndent();
+
+		context.append("function setViewState() {\n");
+		context.append("\tvar state = '");
+		context.append(serializedState);
+		context.append("';\n");
+		context.append("\tfor (var i = 0; i < document.forms.length; i++) {\n");
+		context.append("\t\tdocument.forms[i]['" + hiddenId + "'].value = state;\n");
+		context.append("\t}\n");
+		context.append("}\n");
+		context.append("setViewState();\n");
+
+		context.decreaseIndent();
+		
+        writer.writeText(context.toString(), null);
+
+        writer.endElement(HTML.SCRIPT_ELEM);
+    }
     /**
      * The ScriptContext offers methods and fields
      * to help with rendering out a script and keeping a