You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/05/11 03:28:53 UTC

svn commit: r1101720 [1/2] - in /myfaces/core/trunk: ./ impl/src/main/java/org/apache/myfaces/application/ impl/src/main/java/org/apache/myfaces/application/jsp/ impl/src/main/java/org/apache/myfaces/view/facelets/ impl/src/test/java/org/apache/myfaces...

Author: lu4242
Date: Wed May 11 01:28:53 2011
New Revision: 1101720

URL: http://svn.apache.org/viewvc?rev=1101720&view=rev
Log:
MYFACES-3134 Move all code related to state caching into one place

Added:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCacheImpl.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/StateManagerImplTest.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletMultipleRequestsTestCase.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsClientSideTest.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsTest.java
    myfaces/core/trunk/impl/src/test/resources/org/apache/myfaces/view/facelets/simpleTree.xhtml
Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/jsp/JspStateManagerImpl.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementHelper.java
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategyTest.java
    myfaces/core/trunk/pom.xml

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCache.java Wed May 11 01:28:53 2011
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.application;
+
+import javax.faces.context.FacesContext;
+
+/**
+ *  
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public abstract class StateCache
+{
+
+    /**
+     * Put the state on the cache, to can be restored later.
+     * 
+     * @param facesContext
+     * @param serializedView
+     */
+    public abstract void saveSerializedView(FacesContext facesContext, Object serializedView);
+    
+    /**
+     * 
+     * @param facesContext
+     * @param viewId The viewId of the view to be restored
+     * @param viewState A token usually retrieved from a call to ResponseStateManager.getState that will be
+     *                  used to identify or restore the state.
+     * @return
+     */
+    public abstract Object restoreSerializedView(FacesContext facesContext, String viewId, Object viewState);
+
+    /**
+     * 
+     * @param facesContext
+     * @param state The state that will be used to derive the token returned.
+     * @return A token (usually encoded on javax.faces.ViewState input hidden field) that will be passed to 
+     *         ResponseStateManager.writeState or ResponseStateManager.getViewState to be 
+     *         output to the client.
+     */
+    public abstract Object encodeSerializedState(FacesContext facesContext, Object serializedView);
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCacheImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCacheImpl.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCacheImpl.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateCacheImpl.java Wed May 11 01:28:53 2011
@@ -0,0 +1,687 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.application;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+import org.apache.commons.collections.map.AbstractReferenceMap;
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
+import org.apache.myfaces.shared_impl.util.MyFacesObjectInputStream;
+
+public class StateCacheImpl extends StateCache
+{
+
+    private static final Logger log = Logger.getLogger(StateCacheImpl.class.getName());
+    
+    private static final String SERIALIZED_VIEW_SESSION_ATTR= 
+        StateCacheImpl.class.getName() + ".SERIALIZED_VIEW";
+    
+    private static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR = 
+        StateCacheImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW";
+
+    /**
+     * Only applicable if state saving method is "server" (= default).
+     * Defines the amount (default = 20) of the latest views are stored in session.
+     */
+    @JSFWebConfigParam(defaultValue="20",since="1.1")
+    private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
+
+    /**
+     * Default value for <code>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</code> context parameter.
+     */
+    private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 20;
+
+    /**
+     * Only applicable if state saving method is "server" (= default).
+     * If <code>true</code> (default) the state will be serialized to a byte stream before it is written to the session.
+     * If <code>false</code> the state will not be serialized to a byte stream.
+     */
+    @JSFWebConfigParam(defaultValue="true",since="1.1")
+    private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
+
+    /**
+     * Only applicable if state saving method is "server" (= default) and if <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> is <code>true</code> (= default).
+     * If <code>true</code> (default) the serialized state will be compressed before it is written to the session.
+     * If <code>false</code> the state will not be compressed.
+     */
+    @JSFWebConfigParam(defaultValue="true",since="1.1")
+    private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
+
+    /**
+     * Default value for <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
+     */
+    private static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
+
+    /**
+     * Default value for <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
+     */
+    private static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = true;
+
+    /**
+     * Define the way of handle old view references(views removed from session), making possible to
+     * store it in a cache, so the state manager first try to get the view from the session. If is it
+     * not found and soft or weak ReferenceMap is used, it try to get from it.
+     * <p>
+     * Only applicable if state saving method is "server" (= default).
+     * </p>
+     * <p>
+     * The gc is responsible for remove the views, according to the rules used for soft, weak or phantom
+     * references. If a key in soft and weak mode is garbage collected, its values are purged.
+     * </p>
+     * <p>
+     * By default no cache is used, so views removed from session became phantom references.
+     * </p>
+     * <ul> 
+     * <li> off, no: default, no cache is used</li> 
+     * <li> hard-soft: use an ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT)</li>
+     * <li> soft: use an ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true) </li>
+     * <li> soft-weak: use an ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true) </li>
+     * <li> weak: use an ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true) </li>
+     * </ul>
+     * 
+     */
+    @JSFWebConfigParam(defaultValue="off", expectedValues="off, no, hard-soft, soft, soft-weak, weak", since="1.2.5")
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
+    
+    /**
+     * This option uses an hard-soft ReferenceMap, but it could cause a 
+     * memory leak, because the keys are not removed by any method
+     * (MYFACES-1660). So use with caution.
+     */
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT = "hard-soft";
+    
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT = "soft";
+    
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK = "soft-weak";
+    
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK = "weak";
+    
+    private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF = "off";
+
+    private static final int UNCOMPRESSED_FLAG = 0;
+    private static final int COMPRESSED_FLAG = 1;
+
+    private static final int JSF_SEQUENCE_INDEX = 0;
+
+    //------------------------------------- METHODS COPIED FROM JspStateManagerImpl--------------------------------
+
+    protected Integer getServerStateId(Object[] state)
+    {
+      if (state != null)
+      {
+          Object serverStateId = state[JSF_SEQUENCE_INDEX];
+          if (serverStateId != null)
+          {
+              return Integer.valueOf((String) serverStateId, Character.MAX_RADIX);
+          }
+      }
+      return null;
+    }
+
+    protected void saveSerializedViewInServletSession(FacesContext context,
+                                                      Object serializedView)
+    {
+        Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
+        SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
+                .get(SERIALIZED_VIEW_SESSION_ATTR);
+        if (viewCollection == null)
+        {
+            viewCollection = new SerializedViewCollection();
+            sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
+        }
+        viewCollection.add(context, serializeView(context, serializedView));
+        // replace the value to notify the container about the change
+        sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
+    }
+
+    protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Integer sequence)
+    {
+        ExternalContext externalContext = context.getExternalContext();
+        Map<String, Object> requestMap = externalContext.getRequestMap();
+        Object serializedView = null;
+        if (requestMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
+        {
+            serializedView = requestMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
+        }
+        else
+        {
+            SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
+                    .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
+            if (viewCollection != null)
+            {
+                /*
+                String sequenceStr = externalContext.getRequestParameterMap().get(
+                       RendererUtils.SEQUENCE_PARAM);
+                Integer sequence = null;
+                if (sequenceStr == null)
+                {
+                    // use latest sequence
+                    Map map = externalContext.getSessionMap();
+                    sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
+                }
+                else
+                {
+                    sequence = new Integer(sequenceStr);
+                }
+                */
+                if (sequence != null)
+                {
+                    Object state = viewCollection.get(sequence, viewId);
+                    if (state != null)
+                    {
+                        serializedView = deserializeView(state);
+                    }
+                }
+            }
+            requestMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
+            nextViewSequence(context);
+        }
+        return serializedView;
+    }
+
+    protected int getNextViewSequence(FacesContext context)
+    {
+        ExternalContext externalContext = context.getExternalContext();
+
+        if (!externalContext.getRequestMap().containsKey(RendererUtils.SEQUENCE_PARAM))
+        {
+            nextViewSequence(context);
+        }
+
+        Integer sequence = (Integer) externalContext.getRequestMap().get(RendererUtils.SEQUENCE_PARAM);
+        return sequence.intValue();
+    }
+
+    protected void nextViewSequence(FacesContext facescontext)
+    {
+        ExternalContext externalContext = facescontext.getExternalContext();
+        Object sessionObj = externalContext.getSession(true);
+        synchronized(sessionObj) // synchronized to increase sequence if multiple requests
+                                 // are handled at the same time for the session
+        {
+            Map<String, Object> map = externalContext.getSessionMap();
+            Integer sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
+            if(sequence == null || sequence.intValue() == Integer.MAX_VALUE)
+            {
+                sequence = Integer.valueOf(1);
+            }
+            else
+            {
+                sequence = Integer.valueOf(sequence.intValue() + 1);
+            }
+            map.put(RendererUtils.SEQUENCE_PARAM, sequence);
+            externalContext.getRequestMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
+        }
+    }
+
+    protected Object serializeView(FacesContext context, Object serializedView)
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering serializeView");
+
+        if(isSerializeStateInSession(context))
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize state in session");
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+            try
+            {
+                OutputStream os = baos;
+                if(isCompressStateInSession(context))
+                {
+                    if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize compressed");
+
+                    os.write(COMPRESSED_FLAG);
+                    os = new GZIPOutputStream(os, 1024);
+                }
+                else
+                {
+                    if (log.isLoggable(Level.FINEST)) log.finest("Processing serializeView - serialize uncompressed");
+
+                    os.write(UNCOMPRESSED_FLAG);
+                }
+
+                Object[] stateArray = (Object[]) serializedView;
+
+                ObjectOutputStream out = new ObjectOutputStream(os);
+                out.writeObject(stateArray[0]);
+                out.writeObject(stateArray[1]);
+                out.close();
+                baos.close();
+
+                if (log.isLoggable(Level.FINEST)) log.finest("Exiting serializeView - serialized. Bytes : "+baos.size());
+                return baos.toByteArray();
+            }
+            catch (IOException e)
+            {
+                log.log(Level.SEVERE, "Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
+                return null;
+            }
+        }
+
+
+        if (log.isLoggable(Level.FINEST))
+            log.finest("Exiting serializeView - do not serialize state in session.");
+
+        return serializedView;
+
+    }
+
+    /**
+     * Reads the value of the <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
+     * @see SERIALIZE_STATE_IN_SESSION_PARAM
+     * @param context <code>FacesContext</code> for the request we are processing.
+     * @return boolean true, if the server state should be serialized in the session
+     */
+    protected boolean isSerializeStateInSession(FacesContext context)
+    {
+        String value = context.getExternalContext().getInitParameter(
+                SERIALIZE_STATE_IN_SESSION_PARAM);
+        boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
+        if (value != null)
+        {
+           serialize = Boolean.valueOf(value);
+        }
+        return serialize;
+    }
+
+    /**
+     * Reads the value of the <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
+     * @see COMPRESS_SERVER_STATE_PARAM
+     * @param context <code>FacesContext</code> for the request we are processing.
+     * @return boolean true, if the server state steam should be compressed
+     */
+    protected boolean isCompressStateInSession(FacesContext context)
+    {
+        String value = context.getExternalContext().getInitParameter(
+                COMPRESS_SERVER_STATE_PARAM);
+        boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
+        if (value != null)
+        {
+           compress = Boolean.valueOf(value);
+        }
+        return compress;
+    }
+
+    protected Object deserializeView(Object state)
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering deserializeView");
+
+        if(state instanceof byte[])
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing deserializeView - deserializing serialized state. Bytes : "+((byte[]) state).length);
+
+            try
+            {
+                ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
+                InputStream is = bais;
+                if(is.read() == COMPRESSED_FLAG)
+                {
+                    is = new GZIPInputStream(is);
+                }
+                ObjectInputStream ois = null;
+                try
+                {
+                    final ObjectInputStream in = new MyFacesObjectInputStream(is);
+                    ois = in;
+                    Object object = null;
+                    if (System.getSecurityManager() != null) 
+                    {
+                        object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object []>() 
+                        {
+                            public Object[] run() throws PrivilegedActionException, IOException, ClassNotFoundException
+                            {
+                                return new Object[] {in.readObject(), in.readObject()};                                    
+                            }
+                        });
+                    }
+                    else
+                    {
+                        object = new Object[] {in.readObject(), in.readObject()};
+                    }
+                    return object;
+                }
+                finally
+                {
+                    if (ois != null)
+                    {
+                        ois.close();
+                        ois = null;
+                    }
+                }
+            }
+            catch (PrivilegedActionException e) 
+            {
+                log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
+                return null;
+            }
+            catch (IOException e)
+            {
+                log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
+                return null;
+            }
+            catch (ClassNotFoundException e)
+            {
+                log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
+                return null;
+            }
+        }
+        else if (state instanceof Object[])
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Exiting deserializeView - state not serialized.");
+
+            return state;
+        }
+        else if(state == null)
+        {
+            log.severe("Exiting deserializeView - this method should not be called with a null-state.");
+            return null;
+        }
+        else
+        {
+            log.severe("Exiting deserializeView - this method should not be called with a state of type : "+state.getClass());
+            return null;
+        }
+    }
+
+    protected static class SerializedViewCollection implements Serializable
+    {
+        private static final long serialVersionUID = -3734849062185115847L;
+
+        private final List<Object> _keys = new ArrayList<Object>(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
+        private final Map<Object, Object> _serializedViews = new HashMap<Object, Object>();
+
+        // old views will be hold as soft references which will be removed by
+        // the garbage collector if free memory is low
+        private transient Map<Object, Object> _oldSerializedViews = null;
+
+        public synchronized void add(FacesContext context, Object state)
+        {
+            Object key = new SerializedViewKey(context);
+            _serializedViews.put(key, state);
+
+            while (_keys.remove(key));
+            _keys.add(key);
+
+            int views = getNumberOfViewsInSession(context);
+            while (_keys.size() > views)
+            {
+                key = _keys.remove(0);
+                Object oldView = _serializedViews.remove(key);
+                if (oldView != null && 
+                    !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context))) 
+                {
+                    getOldSerializedViewsMap().put(key, oldView);
+                }
+            }
+        }
+
+        /**
+         * Reads the amount (default = 20) of views to be stored in session.
+         * @see NUMBER_OF_VIEWS_IN_SESSION_PARAM
+         * @param context FacesContext for the current request, we are processing
+         * @return Number vf views stored in the session
+         */
+        protected int getNumberOfViewsInSession(FacesContext context)
+        {
+            String value = context.getExternalContext().getInitParameter(
+                    NUMBER_OF_VIEWS_IN_SESSION_PARAM);
+            int views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
+            if (value != null)
+            {
+                try
+                {
+                    views = Integer.parseInt(value);
+                    if (views <= 0)
+                    {
+                        log.severe("Configured value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
+                                  + " is not valid, must be an value > 0, using default value ("
+                                  + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
+                        views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
+                    }
+                }
+                catch (Throwable e)
+                {
+                    log.log(Level.SEVERE, "Error determining the value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
+                              + ", expected an integer value > 0, using default value ("
+                              + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
+                }
+            }
+            return views;
+        }
+
+        /**
+         * @return old serialized views map
+         */
+        @SuppressWarnings("unchecked")
+        protected Map<Object, Object> getOldSerializedViewsMap()
+        {
+            FacesContext context = FacesContext.getCurrentInstance();
+            if (_oldSerializedViews == null && context != null)
+            {
+                String cacheMode = getCacheOldViewsInSessionMode(context); 
+                if (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
+                {
+                    _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
+                }
+                else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
+                {
+                    _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
+                }
+                else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
+                {
+                    _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
+                }
+                else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
+                {
+                    _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
+                }
+            }
+            
+            return _oldSerializedViews;
+        }
+        
+        /**
+         * Reads the value of the <code>org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE</code> context parameter.
+         * 
+         * @since 1.2.5
+         * @param context
+         * @return constant indicating caching mode
+         * @see CACHE_OLD_VIEWS_IN_SESSION_MODE
+         */
+        protected String getCacheOldViewsInSessionMode(FacesContext context)
+        {
+            String value = context.getExternalContext().getInitParameter(
+                    CACHE_OLD_VIEWS_IN_SESSION_MODE);
+            if (value == null)
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
+            }
+            else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
+            }
+            else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
+            }            
+            else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
+            }
+            else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
+            }
+            else
+            {
+                return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
+            }
+        }
+        
+        public Object get(Integer sequence, String viewId)
+        {
+            Object key = new SerializedViewKey(viewId, sequence);
+            Object value = _serializedViews.get(key);
+            if (value == null)
+            {
+                Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
+                if (oldSerializedViewMap != null)
+                {
+                    value = oldSerializedViewMap.get(key);
+                }
+            }
+            return value;
+        }
+    }
+
+    protected static class SerializedViewKey implements Serializable
+    {
+        private static final long serialVersionUID = -1170697124386063642L;
+
+        private final String _viewId;
+        private final Integer _sequenceId;
+
+        public SerializedViewKey(String viewId, Integer sequence)
+        {
+            _sequenceId = sequence;
+            _viewId = viewId;
+        }
+
+        public SerializedViewKey(FacesContext context)
+        {
+            _sequenceId = RendererUtils.getViewSequence(context);
+            _viewId = context.getViewRoot().getViewId();
+        }
+
+        @Override
+        public int hashCode()
+        {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + ((_sequenceId == null) ? 0 : _sequenceId.hashCode());
+            result = PRIME * result + ((_viewId == null) ? 0 : _viewId.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            final SerializedViewKey other = (SerializedViewKey) obj;
+            if (_sequenceId == null)
+            {
+                if (other._sequenceId != null)
+                    return false;
+            }
+            else if (!_sequenceId.equals(other._sequenceId))
+                return false;
+            if (_viewId == null)
+            {
+                if (other._viewId != null)
+                    return false;
+            }
+            else if (!_viewId.equals(other._viewId))
+                return false;
+            return true;
+        }
+
+    }
+    
+    //------------------------------------- METHOD FROM StateCache ------------------------------------------------
+
+    @Override
+    public void saveSerializedView(FacesContext facesContext, Object serializedView)
+    {
+        if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
+        {
+            //On client side the state is written completely on the page.
+        }
+        else
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - server-side state saving - save state");
+            //save state in server session
+            saveSerializedViewInServletSession(facesContext, serializedView);
+            
+            if (log.isLoggable(Level.FINEST)) log.finest("Exiting saveSerializedView - server-side state saving - saved state");
+        }
+    }
+
+    @Override
+    public Object restoreSerializedView(FacesContext facesContext, String viewId, Object viewState)
+    {
+        if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
+        {
+            //On client side the state was already restored by ResponseStateManager
+            return viewState;
+        }
+        else
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Restoring view from session");
+
+            Integer serverStateId = getServerStateId((Object[]) viewState);
+
+            return (serverStateId == null) ? null : getSerializedViewFromServletSession(facesContext, viewId, serverStateId);
+        }
+    }
+
+    @Override
+    public Object encodeSerializedState(FacesContext facesContext, Object serializedView)
+    {
+        if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
+        {
+            return serializedView;
+        }
+        else
+        {
+            Object[] identifier = new Object[2];
+            identifier[JSF_SEQUENCE_INDEX] = Integer.toString(getNextViewSequence(facesContext), Character.MAX_RADIX);
+            return identifier;
+        }
+    }
+    
+    
+}

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java Wed May 11 01:28:53 2011
@@ -0,0 +1,342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.application;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FactoryFinder;
+import javax.faces.application.StateManager;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.ResponseStateManager;
+import javax.faces.view.StateManagementStrategy;
+import javax.faces.view.ViewDeclarationLanguage;
+
+import org.apache.myfaces.application.jsp.JspStateManagerImpl;
+
+public class StateManagerImpl extends StateManager
+{
+    private static final Logger log = Logger.getLogger(StateManagerImpl.class.getName());
+    
+    private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
+        StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
+    
+    private RenderKitFactory _renderKitFactory = null;
+    
+    private StateCache _stateCache;
+    
+    public StateManagerImpl()
+    {
+        _stateCache = new StateCacheImpl();
+    }
+
+    @Override
+    protected Object getComponentStateToSave(FacesContext facesContext)
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering getComponentStateToSave");
+
+        UIViewRoot viewRoot = facesContext.getViewRoot();
+        if (viewRoot.isTransient())
+        {
+            return null;
+        }
+
+        Object serializedComponentStates = viewRoot.processSaveState(facesContext);
+        //Locale is a state attribute of UIViewRoot and need not be saved explicitly
+        if (log.isLoggable(Level.FINEST)) log.finest("Exiting getComponentStateToSave");
+        return serializedComponentStates;
+    }
+
+    /**
+     * Return an object which contains info about the UIComponent type
+     * of each node in the view tree. This allows an identical UIComponent
+     * tree to be recreated later, though all the components will have
+     * just default values for their members.
+     */
+    @Override
+    protected Object getTreeStructureToSave(FacesContext facesContext)
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering getTreeStructureToSave");
+        UIViewRoot viewRoot = facesContext.getViewRoot();
+        if (viewRoot.isTransient())
+        {
+            return null;
+        }
+        TreeStructureManager tsm = new TreeStructureManager();
+        Object retVal = tsm.buildTreeStructureToSave(viewRoot);
+        if (log.isLoggable(Level.FINEST)) log.finest("Exiting getTreeStructureToSave");
+        return retVal;
+    }
+
+    @Override
+    public UIViewRoot restoreView(FacesContext facesContext, String viewId, String renderKitId)
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering restoreView - viewId: "+viewId+" ; renderKitId: "+renderKitId);
+
+        UIViewRoot uiViewRoot = null;
+        
+        ViewDeclarationLanguage vdl = facesContext.getApplication().
+            getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
+        StateManagementStrategy sms = null; 
+        if (vdl != null)
+        {
+            sms = vdl.getStateManagementStrategy(facesContext, viewId);
+        }
+        
+        if (sms != null)
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Redirect to StateManagementStrategy: "+sms.getClass().getName());
+            
+            uiViewRoot = sms.restoreView(facesContext, viewId, renderKitId);
+        }
+        else
+        {
+            RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
+            ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
+
+            Object state = getStateCache().restoreSerializedView(facesContext, viewId, responseStateManager.getState(facesContext, viewId));
+
+            if (state != null) {
+                Object[] stateArray = (Object[])state;
+                TreeStructureManager tsm = new TreeStructureManager();
+                uiViewRoot = tsm.restoreTreeStructure(stateArray[0]);
+
+                if (uiViewRoot != null) {
+                    facesContext.setViewRoot (uiViewRoot);
+                    uiViewRoot.processRestoreState(facesContext, stateArray[1]);
+                }
+            }            
+        }
+        if (log.isLoggable(Level.FINEST)) log.finest("Exiting restoreView - "+viewId);
+
+        return uiViewRoot;
+    }
+
+    /**
+     * Wrap the original method and redirect to VDL StateManagementStrategy when
+     * necessary
+     */
+    @Override
+    public Object saveView(FacesContext facesContext)
+    {
+        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+        
+        String viewId = uiViewRoot.getViewId();
+        ViewDeclarationLanguage vdl = facesContext.getApplication().
+            getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
+        if (vdl != null)
+        {
+            StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
+            
+            if (sms != null)
+            {
+                if (log.isLoggable(Level.FINEST)) log.finest("Calling saveView of StateManagementStrategy: "+sms.getClass().getName());
+                
+                return sms.saveView(facesContext);
+            }
+        }
+
+        // In StateManagementStrategy.saveView there is a check for transient at
+        // start, but the same applies for VDL without StateManagementStrategy,
+        // so this should be checked before call parent (note that parent method
+        // does not do this check).
+        if (uiViewRoot.isTransient())
+        {
+            return null;
+        }
+
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering saveSerializedView");
+
+        checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
+
+        if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - Checked for duplicate Ids");
+
+        ExternalContext externalContext = facesContext.getExternalContext();
+
+        // SerializedView already created before within this request?
+        Object serializedView = externalContext.getRequestMap()
+                                                            .get(SERIALIZED_VIEW_REQUEST_ATTR);
+        if (serializedView == null)
+        {
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - create new serialized view");
+
+            // first call to saveSerializedView --> create SerializedView
+            Object treeStruct = getTreeStructureToSave(facesContext);
+            Object compStates = getComponentStateToSave(facesContext);
+            serializedView = new Object[] {treeStruct, compStates};
+            externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
+                                                serializedView);
+
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - new serialized view created");
+        }
+
+        
+        getStateCache().saveSerializedView(facesContext, serializedView);
+        
+        if (log.isLoggable(Level.FINEST)) log.finest("Exiting saveView");
+
+        return serializedView;
+    }
+
+    private static void checkForDuplicateIds(FacesContext context,
+                                             UIComponent component,
+                                             Set<String> ids)
+    {
+        String id = component.getId();
+        if (id != null && !ids.add(id))
+        {
+            throw new IllegalStateException("Client-id : " + id +
+                                            " is duplicated in the faces tree. Component : " + 
+                                            component.getClientId(context)+", path: " +
+                                            getPathToComponent(component));
+        }
+        
+        if (component instanceof NamingContainer)
+        {
+            ids = new HashSet<String>();
+        }
+        
+        Iterator<UIComponent> it = component.getFacetsAndChildren();
+        while (it.hasNext())
+        {
+            UIComponent kid = it.next();
+            checkForDuplicateIds(context, kid, ids);
+        }
+    }
+
+    private static String getPathToComponent(UIComponent component)
+    {
+        StringBuffer buf = new StringBuffer();
+
+        if(component == null)
+        {
+            buf.append("{Component-Path : ");
+            buf.append("[null]}");
+            return buf.toString();
+        }
+
+        getPathToComponent(component,buf);
+
+        buf.insert(0,"{Component-Path : ");
+        buf.append("}");
+
+        return buf.toString();
+    }
+
+    private static void getPathToComponent(UIComponent component, StringBuffer buf)
+    {
+        if(component == null)
+            return;
+
+        StringBuffer intBuf = new StringBuffer();
+
+        intBuf.append("[Class: ");
+        intBuf.append(component.getClass().getName());
+        if(component instanceof UIViewRoot)
+        {
+            intBuf.append(",ViewId: ");
+            intBuf.append(((UIViewRoot) component).getViewId());
+        }
+        else
+        {
+            intBuf.append(",Id: ");
+            intBuf.append(component.getId());
+        }
+        intBuf.append("]");
+
+        buf.insert(0,intBuf.toString());
+
+        getPathToComponent(component.getParent(),buf);
+    }
+
+    @Override
+    public void writeState(FacesContext facesContext,
+                           Object state) throws IOException
+    {
+        if (log.isLoggable(Level.FINEST)) log.finest("Entering writeState");
+
+        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+        //save state in response (client)
+        RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, uiViewRoot.getRenderKitId());
+        ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
+
+        responseStateManager.writeState(facesContext, 
+                getStateCache().encodeSerializedState(facesContext, state));
+
+        if (log.isLoggable(Level.FINEST)) log.finest("Exiting writeState");
+
+    }
+
+    @Override
+    public String getViewState(FacesContext facesContext)
+    {
+        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+        String viewId = uiViewRoot.getViewId();
+        ViewDeclarationLanguage vdl = facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
+        if (vdl != null)
+        {
+            StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
+            
+            if (sms != null)
+            {
+                if (log.isLoggable(Level.FINEST)) log.finest("Calling saveView of StateManagementStrategy from getViewState: "+sms.getClass().getName());
+                
+                return facesContext.getRenderKit().getResponseStateManager().getViewState(facesContext, saveView(facesContext));
+            }
+        }
+        Object[] savedState = (Object[]) saveView(facesContext);
+        
+        return facesContext.getRenderKit().getResponseStateManager().getViewState(facesContext,
+                getStateCache().encodeSerializedState(facesContext, savedState));
+    }
+
+    //helpers
+
+    protected RenderKitFactory getRenderKitFactory()
+    {
+        if (_renderKitFactory == null)
+        {
+            _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+        }
+        return _renderKitFactory;
+    }
+
+
+    
+    protected StateCache getStateCache()
+    {
+        return _stateCache;
+    }
+
+    protected void setStateCache(StateCache stateCache)
+    {
+        this._stateCache = stateCache;
+    }
+
+}

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/jsp/JspStateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/jsp/JspStateManagerImpl.java?rev=1101720&r1=1101719&r2=1101720&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/jsp/JspStateManagerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/jsp/JspStateManagerImpl.java Wed May 11 01:28:53 2011
@@ -42,16 +42,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
-import org.apache.commons.collections.map.AbstractReferenceMap;
-import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.myfaces.application.MyfacesStateManager;
-import org.apache.myfaces.application.TreeStructureManager;
-import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
-import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
-import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
-import org.apache.myfaces.shared_impl.util.MyFacesObjectInputStream;
 
 import javax.faces.FactoryFinder;
 import javax.faces.application.StateManager;
@@ -100,7 +90,6 @@ public class JspStateManagerImpl extends
      * Only applicable if state saving method is "server" (= default).
      * Defines the amount (default = 20) of the latest views are stored in session.
      */
-    @JSFWebConfigParam(defaultValue="20",since="1.1")
     private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
 
     /**
@@ -113,7 +102,6 @@ public class JspStateManagerImpl extends
      * If <code>true</code> (default) the state will be serialized to a byte stream before it is written to the session.
      * If <code>false</code> the state will not be serialized to a byte stream.
      */
-    @JSFWebConfigParam(defaultValue="true",since="1.1")
     private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
 
     /**
@@ -121,7 +109,6 @@ public class JspStateManagerImpl extends
      * If <code>true</code> (default) the serialized state will be compressed before it is written to the session.
      * If <code>false</code> the state will not be compressed.
      */
-    @JSFWebConfigParam(defaultValue="true",since="1.1")
     private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
 
     /**
@@ -157,7 +144,6 @@ public class JspStateManagerImpl extends
      * </ul>
      * 
      */
-    @JSFWebConfigParam(defaultValue="off", expectedValues="off, no, hard-soft, soft, soft-weak, weak", since="1.2.5")
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
     
     /**

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementHelper.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementHelper.java?rev=1101720&r1=1101719&r2=1101720&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementHelper.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementHelper.java Wed May 11 01:28:53 2011
@@ -50,13 +50,13 @@ import org.apache.myfaces.shared_impl.ut
  * This helper class contains methods used by DefaultFaceletsStateManagementStrategy that comes
  * from JspStateManagerImpl, but are used by our default StateManagementStrategy
  *  
- * TODO: Move all state saving methods commons to JspStateManagerImpl to some common place.
- * 
  * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
  * @version $Revision: 793245 $ $Date: 2009-07-11 18:50:53 -0500 (Sat, 11 Jul 2009) $
  * @since 2.0
+ * @deprecated replaced by org.apache.myfaces.application.StateCache
  *
  */
+@Deprecated
 class DefaultFaceletsStateManagementHelper
 {
     //private static final Log log = LogFactory.getLog(DefaultFaceletsStateManagementHelper.class);

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java?rev=1101720&r1=1101719&r2=1101720&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java Wed May 11 01:28:53 2011
@@ -34,13 +34,9 @@ import javax.faces.component.ContextCall
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewParameter;
 import javax.faces.component.UIViewRoot;
-import javax.faces.component.visit.VisitCallback;
-import javax.faces.component.visit.VisitContext;
-import javax.faces.component.visit.VisitResult;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PostAddToViewEvent;
-import javax.faces.event.PostRestoreStateEvent;
 import javax.faces.event.PreRemoveFromViewEvent;
 import javax.faces.event.SystemEvent;
 import javax.faces.event.SystemEventListener;
@@ -50,6 +46,9 @@ import javax.faces.view.ViewDeclarationL
 import javax.faces.view.ViewDeclarationLanguageFactory;
 import javax.faces.view.ViewMetadata;
 
+import org.apache.myfaces.application.StateCache;
+import org.apache.myfaces.application.StateCacheImpl;
+import org.apache.myfaces.application.StateManagerImpl;
 import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
 import org.apache.myfaces.shared_impl.util.ClassUtils;
 import org.apache.myfaces.shared_impl.util.HashMapUtils;
@@ -113,14 +112,19 @@ public class DefaultFaceletsStateManagem
      */
     public  static final String COMPONENT_ADDED_AFTER_BUILD_VIEW = "oam.COMPONENT_ADDED_AFTER_BUILD_VIEW"; 
     
+    private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
+        StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
+    
     private ViewDeclarationLanguageFactory _vdlFactory;
     
-    private DefaultFaceletsStateManagementHelper helper;
+    private StateCache stateCache;
     
     public DefaultFaceletsStateManagementStrategy ()
     {
         _vdlFactory = (ViewDeclarationLanguageFactory)FactoryFinder.getFactory(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY);
-        this.helper = new DefaultFaceletsStateManagementHelper();
+        //TODO: This object should be application scoped and shared
+        //between jsp and facelets
+        this.stateCache = new StateCacheImpl();
     }
     
     @SuppressWarnings("unchecked")
@@ -138,17 +142,8 @@ public class DefaultFaceletsStateManagem
         final boolean oldContextEventState = context.isProcessingEvents();
         // Get previous state from ResponseStateManager.
         manager = RendererUtils.getResponseStateManager (context, renderKitId);
-
-        if (context.getApplication().getStateManager().isSavingStateInClient(context))
-        {
-            state = (Object[]) manager.getState (context, viewId);
-        }
-        else
-        {
-            Integer serverStateId = helper.getServerStateId((Object[]) manager.getState(context, viewId));
-
-            state = (Object[]) ((serverStateId == null) ? null : helper.getSerializedViewFromServletSession(context, viewId, serverStateId));
-        }
+        
+        state = (Object[]) getStateCache().restoreSerializedView(context, viewId, manager.getState(context, viewId));
         
         if (state == null)
         {
@@ -429,7 +424,7 @@ public class DefaultFaceletsStateManagem
         ExternalContext externalContext = context.getExternalContext();
         
         Object serializedView = externalContext.getRequestMap()
-            .get(DefaultFaceletsStateManagementHelper.SERIALIZED_VIEW_REQUEST_ATTR);
+            .get(SERIALIZED_VIEW_REQUEST_ATTR);
         
         //Note on ajax case the method saveState could be called twice: once before start
         //document rendering and the other one when it is called StateManager.getViewState method.
@@ -468,6 +463,12 @@ public class DefaultFaceletsStateManagem
             // As required by ResponseStateManager, the return value is an Object array.  First
             // element is the structure object, second is the state map.
         
+            serializedView = new Object[] { null, states };
+            
+            externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
+                    getStateCache().encodeSerializedState(context, serializedView));
+
+            /*
             if (context.getApplication().getStateManager().isSavingStateInClient(context))
             {
                 serializedView = new Object[] { null, states };
@@ -482,12 +483,13 @@ public class DefaultFaceletsStateManagem
             }
             externalContext.getRequestMap().put(DefaultFaceletsStateManagementHelper.SERIALIZED_VIEW_REQUEST_ATTR,
                     serializedView);
+            */
         }
         
-        if (!context.getApplication().getStateManager().isSavingStateInClient(context))
-        {
-            helper.saveSerializedViewInServletSession(context, serializedView);
-        }
+        //if (!context.getApplication().getStateManager().isSavingStateInClient(context))
+        //{
+        getStateCache().saveSerializedView(context, serializedView);
+        //}
         
         return serializedView;
     }
@@ -874,6 +876,16 @@ public class DefaultFaceletsStateManagem
     }
     */
     
+    public StateCache getStateCache()
+    {
+        return stateCache;
+    }
+
+    public void setStateCache(StateCache stateCache)
+    {
+        this.stateCache = stateCache;
+    }
+
     public static class PostAddPreRemoveFromViewListener implements SystemEventListener
     {
 

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/StateManagerImplTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/StateManagerImplTest.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/StateManagerImplTest.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/StateManagerImplTest.java Wed May 11 01:28:53 2011
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.application;
+
+import java.io.BufferedWriter;
+import java.io.CharArrayWriter;
+
+import javax.faces.application.StateManager;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UIViewRoot;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.ResponseStateManager;
+
+import org.apache.myfaces.renderkit.html.HtmlResponseStateManager;
+import org.apache.myfaces.shared_impl.util.StateUtils;
+import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory;
+import org.apache.myfaces.test.base.junit4.AbstractMultipleRequestsJSFTestCase;
+import org.apache.myfaces.test.mock.MockRenderKit;
+import org.apache.myfaces.test.mock.MockResponseWriter;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.testng.Assert;
+
+@RunWith(JUnit4.class)
+public class StateManagerImplTest extends AbstractMultipleRequestsJSFTestCase
+{
+
+    public StateManagerImplTest()
+    {
+        super();
+    }
+
+    @Test
+    public void testWriteAndRestoreState() throws Exception
+    {
+        StateManager stateManager = null;
+        String viewStateParam = null;
+        
+        //renderKit.setResponseStateManager(new HtmlResponseStateManager());
+        //StateUtils.initSecret(servletContext);
+        //servletContext.setAttribute(StateUtils.SERIAL_FACTORY, new DefaultSerialFactory());
+        
+        try
+        {
+            setupRequest();
+            
+            facesContext.setResponseWriter(new MockResponseWriter(new BufferedWriter(new CharArrayWriter()), null, null));
+    
+            UIViewRoot viewRoot = facesContext.getViewRoot();
+            viewRoot.setViewId("/root");
+            stateManager = new StateManagerImpl();
+    
+            UIOutput output = new UIOutput();
+            output.setValue("foo");
+            output.setId("foo");
+    
+            stateManager.writeState(facesContext, stateManager.saveView(facesContext));
+            
+            viewStateParam = stateManager.getViewState(facesContext);
+        }
+        finally
+        {
+            tearDownRequest();
+        }
+
+        try
+        {
+            setupRequest();
+            
+            request.addParameter(ResponseStateManager.VIEW_STATE_PARAM, viewStateParam);
+    
+            UIViewRoot restoredViewRoot = stateManager.restoreView(facesContext, "/root", RenderKitFactory.HTML_BASIC_RENDER_KIT);
+            
+            Assert.assertNotNull(restoredViewRoot);
+        }
+        finally
+        {
+            tearDownRequest();
+        }
+    }
+
+    @Test
+    public void testWriteAndRestoreStateWithMyFacesRSM() throws Exception
+    {
+        StateManager stateManager = null;
+        String viewStateParam = null;
+        
+        ((MockRenderKit)renderKit).setResponseStateManager(new HtmlResponseStateManager());
+        StateUtils.initSecret(servletContext);
+        servletContext.setAttribute(StateUtils.SERIAL_FACTORY, new DefaultSerialFactory());
+        
+        try
+        {
+            setupRequest();
+            
+            facesContext.setResponseWriter(new MockResponseWriter(new BufferedWriter(new CharArrayWriter()), null, null));
+    
+            UIViewRoot viewRoot = facesContext.getViewRoot();
+            viewRoot.setViewId("/root");
+            stateManager = new StateManagerImpl();
+    
+            UIOutput output = new UIOutput();
+            output.setValue("foo");
+            output.setId("foo");
+    
+            stateManager.writeState(facesContext, stateManager.saveView(facesContext));
+            
+            viewStateParam = stateManager.getViewState(facesContext);
+        }
+        finally
+        {
+            tearDownRequest();
+        }
+
+        try
+        {
+            setupRequest();
+            
+            request.addParameter(ResponseStateManager.VIEW_STATE_PARAM, viewStateParam);
+    
+            UIViewRoot restoredViewRoot = stateManager.restoreView(facesContext, "/root", RenderKitFactory.HTML_BASIC_RENDER_KIT);
+            
+            Assert.assertNotNull(restoredViewRoot);
+        }
+        finally
+        {
+            tearDownRequest();
+        }
+    }
+}

Modified: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategyTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategyTest.java?rev=1101720&r1=1101719&r2=1101720&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategyTest.java (original)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategyTest.java Wed May 11 01:28:53 2011
@@ -33,7 +33,6 @@ import javax.faces.component.html.HtmlIn
 import javax.faces.component.html.HtmlOutputText;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PhaseId;
-import javax.faces.event.PostAddToViewEvent;
 import javax.faces.render.RenderKitFactory;
 import javax.faces.render.ResponseStateManager;
 import javax.faces.view.StateManagementStrategy;
@@ -42,6 +41,7 @@ import javax.faces.view.ViewDeclarationL
 import javax.faces.view.ViewMetadata;
 
 import org.apache.myfaces.application.ApplicationFactoryImpl;
+import org.apache.myfaces.application.StateManagerImpl;
 import org.apache.myfaces.component.visit.VisitContextFactoryImpl;
 import org.apache.myfaces.renderkit.html.HtmlButtonRenderer;
 import org.apache.myfaces.renderkit.html.HtmlFormRenderer;
@@ -52,8 +52,6 @@ import org.apache.myfaces.view.ViewMetad
 import org.junit.Assert;
 import org.junit.Test;
 
-import com.google.inject.cglib.proxy.Factory;
-
 public class DefaultFaceletsStateManagementStrategyTest extends
         AbstractJsfConfigurableMockTestCase
 {
@@ -423,7 +421,7 @@ public class DefaultFaceletsStateManagem
     public UIViewRoot saveAndRestore(StateManagementStrategy stateManagement, UIViewRoot viewRoot)
     {
         externalContext.getRequestMap()
-        .remove(DefaultFaceletsStateManagementHelper.SERIALIZED_VIEW_REQUEST_ATTR);        
+            .remove(StateManagerImpl.class.getName() + ".SERIALIZED_VIEW");        
         Object state1 = stateManagement.saveView(facesContext);
         stateToRestore = state1;
         facesContext.setViewRoot(null);

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletMultipleRequestsTestCase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletMultipleRequestsTestCase.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletMultipleRequestsTestCase.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/FaceletMultipleRequestsTestCase.java Wed May 11 01:28:53 2011
@@ -0,0 +1,414 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.view.facelets;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.net.URI;
+import java.net.URL;
+
+import javax.faces.FacesException;
+import javax.faces.FactoryFinder;
+import javax.faces.application.ProjectStage;
+import javax.faces.application.StateManager;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKitFactory;
+
+import org.apache.myfaces.application.ApplicationFactoryImpl;
+import org.apache.myfaces.application.ViewHandlerImpl;
+import org.apache.myfaces.config.FacesConfigDispenser;
+import org.apache.myfaces.config.FacesConfigUnmarshaller;
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.config.element.Behavior;
+import org.apache.myfaces.config.element.ClientBehaviorRenderer;
+import org.apache.myfaces.config.element.FacesConfig;
+import org.apache.myfaces.config.element.Renderer;
+import org.apache.myfaces.config.impl.digester.DigesterFacesConfigDispenserImpl;
+import org.apache.myfaces.config.impl.digester.DigesterFacesConfigUnmarshallerImpl;
+import org.apache.myfaces.context.PartialViewContextFactoryImpl;
+import org.apache.myfaces.shared_impl.application.ViewHandlerSupport;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.test.base.junit4.AbstractMultipleRequestsJSFTestCase;
+import org.apache.myfaces.test.el.MockExpressionFactory;
+import org.apache.myfaces.test.mock.MockExternalContext;
+import org.apache.myfaces.test.mock.MockFacesContext;
+import org.apache.myfaces.test.mock.MockFacesContextFactory;
+import org.apache.myfaces.test.mock.MockPropertyResolver;
+import org.apache.myfaces.test.mock.MockVariableResolver;
+import org.apache.myfaces.test.mock.visit.MockVisitContextFactory;
+import org.apache.myfaces.view.facelets.mock.MockViewDeclarationLanguageFactory;
+import org.apache.myfaces.view.facelets.tag.jsf.TagHandlerDelegateFactoryImpl;
+
+public abstract class FaceletMultipleRequestsTestCase extends AbstractMultipleRequestsJSFTestCase
+{
+    private final String filePath = this.getDirectory();
+    protected FacesConfigDispenser dispenser = null;
+    protected MockFaceletViewDeclarationLanguage vdl;
+
+
+    @Override
+    protected void setUpServletContextAndSession() throws Exception
+    {
+        super.setUpServletContextAndSession();
+        URI context = this.getContext();
+        servletContext.setDocumentRoot(new File(context));
+        
+        //This params are optional
+        servletContext.addInitParameter(StateManager.STATE_SAVING_METHOD_PARAM_NAME,
+                StateManager.STATE_SAVING_METHOD_CLIENT);
+        servletContext.addInitParameter("org.apache.myfaces.PRETTY_HTML","true");
+        servletContext.addInitParameter("org.apache.myfaces.ALLOW_JAVASCRIPT","true");
+        servletContext.addInitParameter("org.apache.myfaces.RENDER_CLEAR_JAVASCRIPT_FOR_BUTTON","false");
+        servletContext.addInitParameter("org.apache.myfaces.SAVE_FORM_SUBMIT_LINK_IE","false");
+        servletContext.addInitParameter("org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS","true");
+        servletContext.addInitParameter("org.apache.myfaces.RENDER_VIEWSTATE_ID","true");
+        servletContext.addInitParameter("org.apache.myfaces.STRICT_XHTML_LINKS","true");
+        servletContext.addInitParameter("org.apache.myfaces.CONFIG_REFRESH_PERIOD","0");
+        servletContext.addInitParameter("org.apache.myfaces.VIEWSTATE_JAVASCRIPT","false");
+        servletContext.addInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME, "UnitTest");
+    }
+    
+    @Override
+    protected void setUpServletRequestAndResponse() throws Exception
+    {
+        super.setUpServletRequestAndResponse();
+        URI context = this.getContext();
+        request.setPathElements(context.getPath(), null, context.getPath(), context.getQuery());
+    }
+
+    protected URI getContext()
+    {
+        try
+        {
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            URL url = cl.getResource(this.filePath);
+            if (url == null)
+            {
+                throw new FileNotFoundException(cl.getResource("").getFile()
+                        + this.filePath + " was not found");
+            }
+            else
+            {
+                return new URI(url.toString());
+            }
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Error Initializing Context", e);
+        }
+    }
+
+    protected URL getLocalFile(String name) throws FileNotFoundException
+    {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        URL url = cl.getResource(this.filePath + "/" + name);
+        if (url == null)
+        {
+            throw new FileNotFoundException(cl.getResource("").getFile() + name
+                    + " was not found");
+        }
+        return url;
+    }
+
+    private String getDirectory()
+    {
+        return this.getClass().getName().substring(0,
+                this.getClass().getName().lastIndexOf('.')).replace('.', '/')
+                + "/";
+    }
+
+    @Override
+    protected void setFactories() throws Exception
+    {
+        super.setFactories();
+
+        FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY,
+                ApplicationFactoryImpl.class.getName());
+        FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY,
+                "org.apache.myfaces.test.mock.MockFacesContextFactory");
+        FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY,
+                "org.apache.myfaces.test.mock.lifecycle.MockLifecycleFactory");
+        FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY,
+                "org.apache.myfaces.test.mock.MockRenderKitFactory");
+        FactoryFinder.setFactory(
+                FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY,
+                MockViewDeclarationLanguageFactory.class.getName());
+        FactoryFinder.setFactory(FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY,
+                TagHandlerDelegateFactoryImpl.class.getName());
+        FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
+                PartialViewContextFactoryImpl.class.getName());
+        FactoryFinder.setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY, 
+                MockVisitContextFactory.class.getName());
+    }
+    
+    @Override
+    protected void setUpExternalContext() throws Exception
+    {
+        super.setUpExternalContext();
+        
+        RuntimeConfig.getCurrentInstance(externalContext).setPropertyResolver(
+                new MockPropertyResolver());
+        RuntimeConfig.getCurrentInstance(externalContext).setVariableResolver(
+                new MockVariableResolver());
+        RuntimeConfig.getCurrentInstance(externalContext).setExpressionFactory(
+                new MockExpressionFactory());
+    }
+    
+    
+    
+    @Override
+    protected void setUpFacesContext() throws Exception
+    {
+        super.setUpFacesContext();
+
+        //Finally set the ResponseWriter
+        ResponseWriter rw = renderKit.createResponseWriter(
+                new StringWriter(), null, null);
+        facesContext.setResponseWriter(rw);
+    }
+
+    @Override
+    protected void setUpRenderKit() throws Exception
+    {
+        super.setUpRenderKit();
+        setupComponents();
+        setupConvertersAndValidators();
+        setupBehaviors();
+        setupRenderers();
+    }
+
+    @Override
+    protected void setUpView() throws Exception
+    {
+        UIViewRoot root = new UIViewRoot();
+        root.setViewId("/test");
+        root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
+        facesContext.setViewRoot(root);
+    }
+
+    @Override
+    protected void setUpApplication() throws Exception
+    {
+        FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY,
+            "org.apache.myfaces.test.mock.MockFacesContextFactory");
+        facesContextFactory = (MockFacesContextFactory) FactoryFinder
+            .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
+        facesContext = (MockFacesContext) facesContextFactory.getFacesContext(
+                servletContext, request, response, lifecycle);
+        if (facesContext.getExternalContext() != null)
+        {
+            externalContext = (MockExternalContext) facesContext
+                    .getExternalContext();
+        }
+
+        super.setUpApplication();
+        
+        ((MockFacesContext)facesContext).setApplication(application);
+        
+        ViewHandlerImpl viewHandler = (ViewHandlerImpl) application.getViewHandler();
+        viewHandler.setViewHandlerSupport(new ViewHandlerSupport(){
+
+            public String calculateActionURL(FacesContext facesContext,
+                    String viewId)
+            {
+                return viewId;
+            }
+
+            public String calculateViewId(FacesContext context, String viewId)
+            {
+                return viewId;
+            }
+            
+            public String calculateAndCheckViewId(FacesContext context, String viewId)
+            {
+                return viewId;
+            }
+            
+        }); 
+        
+        // Redirect resource request to the directory where the test class is,
+        // to make easier test composite components.
+        //((ResourceHandlerImpl)application.getResourceHandler()).
+        //    setResourceHandlerSupport(new MockResourceHandlerSupport(this.getClass()));
+    }
+    
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        //facesContext.setViewRoot(facesContext.getApplication().getViewHandler()
+        //        .createView(facesContext, "/test"));
+        
+        vdl = (MockFaceletViewDeclarationLanguage) application.getViewHandler().
+            getViewDeclarationLanguage(facesContext,"/test");
+        
+        externalContext = null;
+        facesContext = null;
+    }
+    
+    /*@Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+    }*/
+
+    protected void loadStandardFacesConfig() throws Exception
+    {
+        if (dispenser == null)
+        {
+            InputStream stream = ClassUtils
+            .getResourceAsStream("META-INF/standard-faces-config.xml");
+            FacesConfigUnmarshaller<? extends FacesConfig> unmarshaller = new DigesterFacesConfigUnmarshallerImpl(
+                    externalContext);
+            dispenser = new DigesterFacesConfigDispenserImpl();
+            dispenser.feed(unmarshaller.getFacesConfig(stream,
+                    "META-INF/standard-faces-config.xml"));
+        }
+    }
+    
+    /**
+     * Override this methods and add just what it is necessary
+     * reduce execution time.
+     */
+    protected void setupComponents() throws Exception
+    {
+        loadStandardFacesConfig();
+        for (String componentType : dispenser.getComponentTypes())
+        {
+            application.addComponent(componentType, dispenser
+                    .getComponentClass(componentType));
+        }
+    }
+    
+    protected void setupBehaviors() throws Exception
+    {
+        loadStandardFacesConfig();
+        for (Behavior behavior : dispenser.getBehaviors())
+        {
+            application.addBehavior(behavior.getBehaviorId(), behavior.getBehaviorClass());
+        }
+    }
+    
+    /**
+     * Override this methods and add just what it is necessary
+     * reduce execution time.
+     */
+    protected void setupRenderers() throws Exception
+    {
+        loadStandardFacesConfig();
+        for (Renderer element : dispenser
+                .getRenderers(RenderKitFactory.HTML_BASIC_RENDER_KIT))
+        {
+            javax.faces.render.Renderer renderer;
+            try
+            {
+                renderer = (javax.faces.render.Renderer) ClassUtils
+                        .newInstance(element.getRendererClass());
+            }
+            catch (Throwable e)
+            {
+                // ignore the failure so that the render kit is configured
+                continue;
+            }
+
+            renderKit.addRenderer(element.getComponentFamily(), element
+                    .getRendererType(), renderer);
+        }
+        
+        for (ClientBehaviorRenderer element : dispenser.getClientBehaviorRenderers(RenderKitFactory.HTML_BASIC_RENDER_KIT))
+        {
+            javax.faces.render.ClientBehaviorRenderer renderer;
+            
+            try
+            {
+                renderer = (javax.faces.render.ClientBehaviorRenderer) ClassUtils
+                        .newInstance(element.getRendererClass());
+            }
+            catch (Throwable e)
+            {
+                // ignore the failure so that the render kit is configured
+                continue;
+            }
+
+            renderKit.addClientBehaviorRenderer(element.getRendererType(), renderer);
+        }
+    }
+    
+    /**
+     * Override this methods and add just what it is necessary
+     * reduce execution time.
+     */
+    protected void setupConvertersAndValidators() throws Exception
+    {
+        loadStandardFacesConfig();
+        for (String validatorId : dispenser.getValidatorIds())
+        {
+            application.addValidator(validatorId, dispenser
+                    .getValidatorClass(validatorId));
+        }
+        for (String converterId : dispenser.getConverterIds())
+        {
+            application.addConverter(converterId, dispenser
+                    .getConverterClassById(converterId));
+        }
+        for (String validatorId : dispenser.getValidatorIds())
+        {
+            application.addValidator(validatorId, dispenser
+                    .getValidatorClass(validatorId));
+        }
+    }
+
+    public URL resolveUrl(String path)
+    {
+        try
+        {
+            return new URL(this.getContext().toURL(), path.substring(1));
+        }
+        catch (Exception e)
+        {
+            throw new FacesException(e);
+        }
+    }
+    
+    /**
+     * Sets the ProjectStage for the test case.
+     * @param stage
+     * @throws IllegalStateException
+     */
+    public void setProjectStage(ProjectStage stage) throws IllegalStateException
+    {
+        try
+        {
+            Field projectStageField = application.getClass().getDeclaredField("_projectStage");
+            projectStageField.setAccessible(true);
+            projectStageField.set(application, stage);
+        }
+        catch (Exception e)
+        {
+            throw new IllegalStateException("Could not configure ProjectStage for test case", e);
+        }
+    }
+
+}

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsClientSideTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsClientSideTest.java?rev=1101720&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsClientSideTest.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/view/facelets/StateManagerWithFaceletsClientSideTest.java Wed May 11 01:28:53 2011
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets;
+
+import javax.faces.application.StateManager;
+import javax.faces.component.UIViewRoot;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.ResponseStateManager;
+
+import org.apache.myfaces.application.StateManagerImpl;
+import org.apache.myfaces.renderkit.html.HtmlResponseStateManager;
+import org.apache.myfaces.shared_impl.util.StateUtils;
+import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory;
+import org.apache.myfaces.test.mock.MockRenderKit;
+import org.junit.Test;
+import org.testng.Assert;
+
+public class StateManagerWithFaceletsClientSideTest extends StateManagerWithFaceletsTest
+{
+
+    @Override
+    protected void setUpApplication() throws Exception
+    {
+        super.setUpApplication();
+        
+        application.setStateManager(new StateManagerImpl());
+    }
+
+    @Override
+    protected void setUpServletContextAndSession() throws Exception
+    {
+        super.setUpServletContextAndSession();
+        
+        servletContext.addInitParameter(StateManager.PARTIAL_STATE_SAVING_PARAM_NAME, "true");
+        servletContext.addInitParameter(StateManager.STATE_SAVING_METHOD_PARAM_NAME, StateManager.STATE_SAVING_METHOD_CLIENT);
+    }
+
+    @Override
+    public void testWriteAndRestoreState() throws Exception
+    {
+        super.testWriteAndRestoreState();
+    }
+
+    @Override
+    public void testWriteAndRestoreStateWithMyFacesRSM() throws Exception
+    {
+        super.testWriteAndRestoreStateWithMyFacesRSM();
+    }
+
+
+}