You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2008/10/03 12:19:35 UTC
svn commit: r701342 - in /myfaces/trinidad/branches/1.2.9.1-branch:
trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/co...
Author: matzew
Date: Fri Oct 3 03:19:33 2008
New Revision: 701342
URL: http://svn.apache.org/viewvc?rev=701342&view=rev
Log:
TRINIDAD-1245 - High Availability Testing Support
thanks to blake sullivan for his patch
Added:
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java
Modified:
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/PropertyKey.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/dispatch/DispatchResponseConfiguratorImpl.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.config.Configurator
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/PropertyKey.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/PropertyKey.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/PropertyKey.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/PropertyKey.java Fri Oct 3 03:19:33 2008
@@ -228,9 +228,9 @@
// warn if we are state saving non-serializable values, as this will cause client
// state saving and fail-over to fail. See JIRA 1236
- if (!(value instanceof Serializable) && _LOG.isWarning())
- _LOG.warning("Unserializable value:" + value + " on property key:" + this);
-
+ if ((value != null) && !(value instanceof Serializable) && _LOG.isWarning())
+ _LOG.warning(_LOG.getMessage("UNSERIALIZABLE_PROPERTY_VALUE", new Object[]{value, this}));
+
return value;
}
@@ -379,3 +379,4 @@
}
+
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/util/StateUtils.java Fri Oct 3 03:19:33 2008
@@ -18,16 +18,23 @@
*/
package org.apache.myfaces.trinidad.bean.util;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import javax.faces.component.StateHolder;
+import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.apache.myfaces.trinidad.bean.FacesBean;
@@ -40,8 +47,158 @@
/**
* Utilities for handling state persistance.
*/
-public class StateUtils
+public final class StateUtils
{
+ static
+ {
+ // initialize checks for serialization verification
+ boolean checkPropertyStateSerialization = false;
+ boolean checkComponentStateSerialization = false;
+ boolean checkComponentTreeStateSerialization = false;
+ boolean checkSessionSerialization = false;
+
+ String checkSerializationProperty;
+
+ // determine if we need to aggressively check the serialization of components
+ // we wrap the check in a try/catch in case of weird ecurity managers
+ try
+ {
+ checkSerializationProperty =
+ System.getProperty("org.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION");
+ }
+ catch (Throwable t)
+ {
+ checkSerializationProperty = null;
+ }
+
+ if (checkSerializationProperty != null)
+ {
+ checkSerializationProperty = checkSerializationProperty.toUpperCase();
+
+ String[] paramArray = checkSerializationProperty.split(",");
+
+ Set<String> serializationFlags = new HashSet<String>(Arrays.asList(paramArray));
+
+ if (!serializationFlags.contains("NONE"))
+ {
+ if (serializationFlags.contains("ALL"))
+ {
+ checkPropertyStateSerialization = true;
+ checkComponentStateSerialization = true;
+ checkComponentTreeStateSerialization = true;
+ checkSessionSerialization = true;
+ }
+ else
+ {
+ checkPropertyStateSerialization = serializationFlags.contains("PROPERTY");
+ checkComponentStateSerialization = serializationFlags.contains("COMPONENT");
+ checkComponentTreeStateSerialization = serializationFlags.contains("TREE");
+ checkSessionSerialization = serializationFlags.contains("SESSION");
+ }
+ }
+ }
+
+ _CHECK_PROPERTY_STATE_SERIALIZATION = checkPropertyStateSerialization;
+ _CHECK_COMPONENT_STATE_SERIALIZATION = checkComponentStateSerialization;
+ _CHECK_COMPONENT_TREE_STATE_SERIALIZATION = checkComponentTreeStateSerialization;
+ _CHECK_SESSION_SERIALIZATION = checkSessionSerialization;
+ }
+
+ private static final boolean _CHECK_COMPONENT_TREE_STATE_SERIALIZATION;
+ private static final boolean _CHECK_COMPONENT_STATE_SERIALIZATION;
+ private static final boolean _CHECK_PROPERTY_STATE_SERIALIZATION;
+ private static final boolean _CHECK_SESSION_SERIALIZATION;
+
+ /**
+ * Returns <code>true</code> if properties should be checked for
+ * serializability when when generating the view's state object.
+ * <p>
+ * By default property state serialization checking is off. It can be
+ * enabled by setting the system property
+ * <code>org.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION</code>
+ * to <code>all</code> or, more rately, adding <code>property</code> to the
+ * comma-separated list of serialization checks to perform.
+ * <p>
+ * As property serialization checking is expensive, it is usually
+ * only enabled after component tree serialization checking has detected
+ * a problem
+ * @return
+ * @see #checkComponentStateSerialization
+ * @see #checkComponentTreeStateSerialization
+ */
+ private static boolean _checkPropertyStateSerialization()
+ {
+ return _CHECK_PROPERTY_STATE_SERIALIZATION;
+ }
+
+ /**
+ * Returns <code>true</code> if components should be checked for
+ * serializability when when generating the view's state object.
+ * <p>
+ * By default component state serialization checking is off. It can be
+ * enabled by setting the system property
+ * <code>org.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION</code>
+ * to <code>all</code> or, more rarely, adding <code>component</code> to the
+ * comma-separated list of serialization checks to perform.
+ * <p>
+ * As property serialization checking is expensive, it is usually
+ * only enabled after component tree serialization checking has detected
+ * a problem. In addition, since component serialization checking only
+ * detects the problem component, it is usually combined with
+ * property state serialization checking either by specifying <code>all</code>.
+ * @return
+ * @see #checkComponentTreeStateSerialization
+ */
+ public static boolean checkComponentStateSerialization(FacesContext context)
+ {
+ return _CHECK_COMPONENT_STATE_SERIALIZATION;
+ }
+
+ /**
+ * Returns <code>true</code> if the component tree should be checked for
+ * serializability when when generating the view's state object.
+ * <p>
+ * By default component tree state serialization checking is off. It can be
+ * enabled by setting the system property
+ * <code>org.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION</code>
+ * to <code>all</code> or, more commonly, adding <code>tree</code> to the
+ * comma-separated list of serialization checks to perform.
+ * <p>
+ * Because unserializable objects defeat fail-over, it is important to
+ * check for serializability when testing applications. While component
+ * tree state serializability checking isn't cheap, it is much faster to
+ * initially only enable checking of the component tree and then switch
+ * to <code>all</code> testing to determine the problem component and
+ * property when the component tree testing determines a problem.
+ * @return
+ * @see #checkComponentStateSerialization
+ */
+ public static boolean checkComponentTreeStateSerialization(FacesContext context)
+ {
+ return _CHECK_COMPONENT_TREE_STATE_SERIALIZATION;
+ }
+
+ /**
+ * Returns <code>true</code> if Object written to the SessionMap should be checked for
+ * Serializability when <code>put</code> is called.
+ * <p>
+ * Configuring this property allows this aspect of high-availability to be tested without
+ * configuring the server to run in high-availability mode.
+ * <p>
+ * By default session serialization checking is off. It can be
+ * enabled by setting the system property
+ * <code>org.apache.myfaces.trinidad.CHECK_STATE_SERIALIZATION</code>
+ * to <code>all</code> or, more commonly, adding <code>session</code> to the
+ * comma-separated list of serialization checks to perform.
+ * @return
+ * @see #checkComponentStateSerialization
+ * @see #checkComponentTreeStateSerialization
+ */
+ public static boolean checkSessionSerialization(ExternalContext extContext)
+ {
+ return _CHECK_SESSION_SERIALIZATION;
+ }
+
/**
* Persists a property key.
*/
@@ -109,10 +266,30 @@
_LOG.finest("SAVE {" + key + "=" + value + "}");
}
+ Object saveValue;
+
if (useStateHolder)
- values[i + 1] = saveStateHolder(context, value);
+ saveValue = saveStateHolder(context, value);
else
- values[i + 1] = key.saveValue(context, value);
+ saveValue = key.saveValue(context, value);
+
+ // aggressively check the serializability of the value
+ if (_checkPropertyStateSerialization())
+ {
+ try
+ {
+ new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(saveValue);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(_LOG.getMessage("UNSERIALIZABLE_PROPERTY_VALUE",
+ new Object[]{saveValue, key}),
+ e);
+ }
+ }
+
+ values[i + 1] = saveValue;
+
i+=2;
}
@@ -385,3 +562,4 @@
}
+
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java Fri Oct 3 03:19:33 2008
@@ -18,8 +18,11 @@
*/
package org.apache.myfaces.trinidad.component;
+import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.io.ObjectOutputStream;
+
import java.net.URL;
import java.util.Iterator;
import java.util.List;
@@ -47,6 +50,7 @@
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.FacesBeanFactory;
import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.bean.util.StateUtils;
import org.apache.myfaces.trinidad.bean.util.ValueMap;
import org.apache.myfaces.trinidad.change.AttributeComponentChange;
import org.apache.myfaces.trinidad.context.RequestContext;
@@ -831,21 +835,56 @@
if (_LOG.isFiner())
_LOG.finer("processSaveState() on " + this);
-
- if (((_children == null) || _children.isEmpty()) &&
- ((_facets == null) || _facets.isEmpty()))
+
+ Object state = null;
+
+ try
{
- return saveState(context);
+ if (((_children == null) || _children.isEmpty()) &&
+ ((_facets == null) || _facets.isEmpty()))
+ {
+ state = saveState(context);
+ }
+ else
+ {
+ TreeState treeState = new TreeState();
+ treeState.saveState(context, this);
+ if (treeState.isEmpty())
+ state = null;
+
+ state = treeState;
+ }
}
- else
+ catch (RuntimeException e)
{
- TreeState state = new TreeState();
- state.saveState(context, this);
- if (state.isEmpty())
- return null;
-
- return state;
+ _LOG.warning(_LOG.getMessage("COMPONENT_CHILDREN_SAVED_STATE_FAILED", this));
+
+ System.out.println(_LOG.getMessage("COMPONENT_CHILDREN_SAVED_STATE_FAILED", this));
+
+ throw e;
}
+
+ // if component state serialization checking is on, attempt to Serialize the
+ // component state immediately in order to determine which component's state
+ // failed state saving. Note that since our parent will attempt this same
+ // serialization, turning this on is expensive and should only be used once
+ // a serialization error has been detected and we want to know which
+ // component's state failed
+ if (StateUtils.checkComponentStateSerialization(context))
+ {
+ try
+ {
+ new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(state);
+ }
+ catch (IOException e)
+ {
+ System.out.println(_LOG.getMessage("COMPONENT_SAVED_STATE_FAILED", this));
+
+ throw new RuntimeException(_LOG.getMessage("COMPONENT_SAVED_STATE_FAILED", this), e);
+ }
+ }
+
+ return state;
}
// TODO will have deep problems if UIComponent.saveState() ever
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java Fri Oct 3 03:19:33 2008
@@ -26,6 +26,7 @@
import javax.faces.model.DataModel;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.CollectionUtils;
/**
* Creates a MenuModel from a List of beans.
@@ -186,9 +187,10 @@
List<Object> path = (List<Object>) childKey;
if ((path == null) || (path.size() <= 1))
return null;
- // Make a copy of the sublist - subList does not return
- // a serializable object
- return new ArrayList<Object>(path.subList(0, path.size() - 1));
+
+ // wrap sublist in a Serializable copy, since sublist usually returns non-Serializable
+ // instances
+ return CollectionUtils.getSerializableList(path.subList(0, path.size() - 1));
}
@Override
@@ -411,4 +413,4 @@
private Object _focusRowKey;
private static final TrinidadLogger _LOG =
TrinidadLogger.createTrinidadLogger(ChildPropertyMenuModel.class);
-}
\ No newline at end of file
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyTreeModel.java Fri Oct 3 03:19:33 2008
@@ -26,6 +26,7 @@
import javax.faces.model.DataModel;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.CollectionUtils;
/**
* Creates a TreeModel from a List of beans.
@@ -188,9 +189,10 @@
List<Object> path = (List<Object>) childKey;
if ((path == null) || (path.size() <= 1))
return null;
- // Make a copy of the sublist - subList does not return
- // a serializable object
- return new ArrayList<Object>(path.subList(0, path.size() - 1));
+
+ // wrap sublist in a Serializable copy, since sublist usually returns non-Serializable
+ // instances
+ return CollectionUtils.getSerializableList(path.subList(0, path.size() - 1));
}
@Override
Added: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java?rev=701342&view=auto
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java (added)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/CollectionUtils.java Fri Oct 3 03:19:33 2008
@@ -0,0 +1,285 @@
+/*
+ * 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.trinidad.util;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+
+/**
+ * This class contains Collection utilities.
+ */
+public final class CollectionUtils
+{
+ private CollectionUtils()
+ {
+ // no-op
+ }
+
+ /**
+ * Returns a Collection based on the passed in Collection <code>c</code>,
+ * guaranteed to be Serializable. If <code>c</code> is Serializable,
+ * <code>c</code> will be returned, otherwise, <code>c</code> will be
+ * wrapped in a Collection that implements Serializable and upon
+ * Serialization the contents of <code>c</code> will be copied into
+ * the result.
+ * <p>
+ * The results is very similar to creating a new ArrayList with the
+ * contents of <code>c</code>, but no wrapper is created unless necessary
+ * and the actual creation of the Serializable copy is deferred until
+ * Serialization occurs.
+ * @param c The Collection to get a Serializable version of
+ * @return A Serializable version of Collection <code>c</code>
+ * @see #getSerializableList
+ */
+ public static <T> Collection<T> getSerializableCollection(Collection<T> c)
+ {
+ if (c instanceof Serializable)
+ return c;
+ else
+ return new SerializableCollection<T>(c);
+ }
+
+ /**
+ * Returns a List based on the passed in List <code>l</code>,
+ * guaranteed to be Serializable. If <code>l</code> is Serializable,
+ * <code>l</code> will be returned, otherwise, <code>l</code> will be
+ * wrapped in a List that implements Serializable and upon
+ * Serialization the contents of <code>l</code> will be copied into
+ * the result.
+ * <p>
+ * If <code>l</code> implements RandomAccess, any returned List will also
+ * implement RandomAccess.
+ * <p>
+ * The results is very similar to creating a new ArrayList with the
+ * contents of <code>l</code>, but no wrapper is created unless necessary
+ * and the actual creation of the Serializable copy is deferred until
+ * Serialization occurs.
+ * @param l The List to get a Serializable version of
+ * @return A Serializable version of List <code>l</code>
+ * @see #getSerializableCollection
+ */
+ public static <T> List<T> getSerializableList(List<T> l)
+ {
+ if (l instanceof Serializable)
+ return l;
+ else
+ {
+ if (l instanceof RandomAccess)
+ {
+ return new SerializableRandomAccessList<T>(l);
+ }
+ else
+ {
+ return new SerializableList<T>(l);
+ }
+ }
+ }
+
+
+ private static class SerializableCollection<E> implements Collection<E>, Serializable
+ {
+ SerializableCollection(Collection<E> delegate)
+ {
+ if (delegate == null)
+ throw new NullPointerException();
+
+ if (delegate instanceof Serializable)
+ throw new IllegalStateException();
+
+ _delegate = delegate;
+ }
+
+ public int size()
+ {
+ return _delegate.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return _delegate.isEmpty();
+ }
+
+ public boolean contains(Object o)
+ {
+ return _delegate.contains(o);
+ }
+
+ public Iterator<E> iterator()
+ {
+ return _delegate.iterator();
+ }
+
+ public Object[] toArray()
+ {
+ return _delegate.toArray();
+ }
+
+ public <T> T[] toArray(T[] a)
+ {
+ return _delegate.toArray(a);
+ }
+
+ public boolean add(E e)
+ {
+ return _delegate.add(e);
+ }
+
+ public boolean remove(Object o)
+ {
+ return _delegate.remove(0);
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return _delegate.containsAll(c);
+ }
+
+ public boolean addAll(Collection<? extends E> c)
+ {
+ return _delegate.addAll(c);
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ return _delegate.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ return _delegate.retainAll(c);
+ }
+
+ public void clear()
+ {
+ _delegate.clear();
+ }
+
+ protected Object writeReplace() throws ObjectStreamException
+ {
+ // copy delegate into a Serializable ArrayList on Serialization
+ return new ArrayList(_delegate);
+ }
+
+ /**
+ * All Collections
+ * @param o
+ * @return
+ */
+ public boolean equals(Object o)
+ {
+ return (o == this) || _delegate.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return _delegate.hashCode();
+ }
+
+ public String toString()
+ {
+ return _delegate.toString();
+ }
+
+ private static final long serialVersionUID = 0L;
+
+ private final transient Collection<E> _delegate;
+ }
+
+
+ private static class SerializableList<E> extends SerializableCollection<E> implements List<E>
+ {
+ SerializableList(List<E> delegate)
+ {
+ super(delegate);
+ _delegate = delegate;
+ }
+
+ public void add(int index, E element)
+ {
+ _delegate.add(index, element);
+ }
+
+ public E remove(int index)
+ {
+ return _delegate.remove(index);
+ }
+
+ public boolean addAll(int index, Collection<? extends E> c)
+ {
+ return _delegate.addAll(index, c);
+ }
+
+ public E get(int index)
+ {
+ return _delegate.get(index);
+ }
+
+ public E set(int index, E element)
+ {
+ return _delegate.set(index, element);
+ }
+
+ public int indexOf(Object o)
+ {
+ return _delegate.indexOf(o);
+ }
+
+ public int lastIndexOf(Object o)
+ {
+ return _delegate.lastIndexOf(o);
+ }
+
+ public ListIterator<E> listIterator()
+ {
+ return _delegate.listIterator();
+ }
+
+ public ListIterator<E> listIterator(int index)
+ {
+ return _delegate.listIterator(index);
+ }
+
+ public List<E> subList(int fromIndex, int toIndex)
+ {
+ return CollectionUtils.getSerializableList(_delegate.subList(fromIndex, toIndex));
+ }
+
+ private static final long serialVersionUID = 0L;
+
+ private final transient List<E> _delegate;
+ }
+
+ private static class SerializableRandomAccessList<E> extends SerializableList<E> implements RandomAccess
+ {
+ SerializableRandomAccessList(List<E> delegate)
+ {
+ super(delegate);
+ }
+
+ private static final long serialVersionUID = 0L;
+ }
+
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/xrts/org/apache/myfaces/trinidad/resource/LoggerBundle.xrts Fri Oct 3 03:19:33 2008
@@ -399,4 +399,16 @@
<!-- DEPRECATED_RELATIVE_ID_SYNTAX -->
<resource key="DEPRECATED_RELATIVE_ID_SYNTAX">Could not find the component with scopedId {0} from {1} with the supported syntax. The component was found with the deprecated syntax. Please use the supported syntax.</resource>
+<!-- UNSERIALIZABLE_PROPERTY_VALUE -->
+<resource key="UNSERIALIZABLE_PROPERTY_VALUE">Unserializable value:{0} on property key:{1}</resource>
+
+<!-- COMPONENT_SAVED_STATE_FAILED -->
+<resource key="COMPONENT_SAVED_STATE_FAILED">Failed to save state for component:{0}</resource>
+
+<!-- COMPONENT_CHILDREN_SAVED_STATE_FAILED -->
+<resource key="COMPONENT_CHILDREN_SAVED_STATE_FAILED">Failed to save state for children of component:{0}</resource>
+
+<!-- COMPONENT_TREE_SERIALIZATION_FAILED -->
+<resource key="COMPONENT_TREE_SERIALIZATION_FAILED">Failed to serialize component tree state</resource>
+
</resources>
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/application/StateManagerImpl.java Fri Oct 3 03:19:33 2008
@@ -48,6 +48,11 @@
import com.sun.facelets.FaceletViewHandler;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.myfaces.trinidad.bean.util.StateUtils;
+
/**
* StateManager that handles a hybrid client/server strategy: a
* SerializedView is stored on the server, and only a small token
@@ -978,6 +983,22 @@
{
_structure = structure;
_state = state;
+
+ // if component tree serialization checking is on (in order to validate
+ // fail over support, attempt to Serialize all of the component state
+ // immediately
+ if (StateUtils.checkComponentTreeStateSerialization(fc))
+ {
+ try
+ {
+ new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(state);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(_LOG.getMessage("COMPONENT_TREE_SERIALIZATION_FAILED"), e);
+ }
+ }
+
// we need this state, as we are going to recreate the UIViewRoot later. see
// the popRoot() method:
_cachedState = (root != null)
@@ -1066,53 +1087,6 @@
}
}
- /* =-=AEW A utility function to dump out all the state that's getting
- sent over. To compile, you need to make most of TreeState public */
- /*
- static private void _dumpState(Object state, int depth)
- {
- String out = _SPACES.substring(0, depth * 2);
- Object objectState = state;
-
- if (state instanceof org.apache.myfaces.trinidad.component.TreeState)
- objectState = ((org.apache.myfaces.trinidad.component.TreeState) state)._state;
-
- if (objectState == null)
- out += "null";
- else if (objectState instanceof Object[])
- out += "array";
- else
- out += objectState.toString() + "(" + objectState.getClass() + ")";
-
- if (objectState instanceof Object[])
- {
- Object[] array = (Object[]) objectState;
- for (int i = 0; i < array.length; i++)
- _dumpState(array[i], depth + 1);
- }
-
-
- if (state instanceof org.apache.myfaces.trinidad.component.TreeState)
- {
- Object[] array = ((org.apache.myfaces.trinidad.component.TreeState)state)._children;
- if (array != null)
- {
- for (int i = 0; i < array.length; i++)
- _dumpState(array[i], depth + 1);
- }
-
- array = ((org.apache.myfaces.trinidad.component.TreeState)state)._facets;
- if (array != null)
- {
- for (int i = 0; i < array.length; i++)
- _dumpState(array[i], depth + 1);
- }
- }
- }
-
- static private final String _SPACES = " ";
- */
-
private final StateManager _delegate;
private Boolean _useViewRootCache;
private Boolean _useApplicationViewCache;
Added: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java?rev=701342&view=auto
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java (added)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/CheckSerializationConfigurator.java Fri Oct 3 03:19:33 2008
@@ -0,0 +1,88 @@
+/*
+ * 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.trinidadinternal.config;
+
+import java.io.Serializable;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.trinidad.bean.util.StateUtils;
+import org.apache.myfaces.trinidad.config.Configurator;
+import org.apache.myfaces.trinidad.context.ExternalContextDecorator;
+
+/**
+ * Configurator that uses a wrapped ExternalContext to return a Session Map that validates that
+ * only Serializable Objects are placed in the Map.
+ * @version $Revision$ $Date$
+ */
+public final class CheckSerializationConfigurator extends Configurator
+{
+
+ /**
+ * Override to return our ExternalContext wrapped if session serialization checking is enabled
+ * @param externalContext
+ * @return
+ */
+ @Override
+ public ExternalContext getExternalContext(ExternalContext externalContext)
+ {
+ if (StateUtils.checkSessionSerialization(externalContext))
+ {
+ return new SessionSerializationChecker(externalContext);
+ }
+ else
+ {
+ return externalContext;
+ }
+ }
+
+ /**
+ * ExternalContextDecorator returning our wrapped SessionMap
+ */
+ private static class SessionSerializationChecker extends ExternalContextDecorator
+ {
+ public SessionSerializationChecker(ExternalContext extContext)
+ {
+ _extContext = extContext;
+
+ // skank using type erasure to finess the fact that Collections.checkedMap() expects and
+ // will return a Map<String, Serializable> when in fact, we should be returning a
+ // Map<String, Onject>. Using checkedMap also has the disadvantage that a ClassCastException
+ // is thrown when we would really prefer to throw a more-explanatory message
+ Map erasedMap = extContext.getSessionMap();
+ _sessionMap = (Map)Collections.checkedMap(erasedMap, String.class, Serializable.class);
+ }
+
+ protected ExternalContext getExternalContext()
+ {
+ return _extContext;
+ }
+
+ public Map getSessionMap()
+ {
+ return _sessionMap;
+ }
+
+ private final ExternalContext _extContext;
+ private final Map _sessionMap;
+ }
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/dispatch/DispatchResponseConfiguratorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/dispatch/DispatchResponseConfiguratorImpl.java?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/dispatch/DispatchResponseConfiguratorImpl.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/dispatch/DispatchResponseConfiguratorImpl.java Fri Oct 3 03:19:33 2008
@@ -18,22 +18,13 @@
*/
package org.apache.myfaces.trinidadinternal.config.dispatch;
-import java.io.IOException;
import java.util.Map;
-import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
-import javax.portlet.PortletContext;
-import javax.portlet.PortletException;
-import javax.portlet.PortletRequestDispatcher;
-import javax.portlet.RenderRequest;
-import javax.portlet.RenderResponse;
import org.apache.myfaces.trinidad.config.Configurator;
-import org.apache.myfaces.trinidad.context.ExternalContextDecorator;
import org.apache.myfaces.trinidad.util.ExternalContextUtils;
-import org.apache.myfaces.trinidadinternal.webapp.wrappers.PortletContextWrapper;
/**
* TODO: Document this
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.config.Configurator
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.config.Configurator?rev=701342&r1=701341&r2=701342&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.config.Configurator (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.config.Configurator Fri Oct 3 03:19:33 2008
@@ -1,2 +1,3 @@
org.apache.myfaces.trinidadinternal.config.upload.FileUploadConfiguratorImpl
org.apache.myfaces.trinidadinternal.config.dispatch.DispatchResponseConfiguratorImpl
+org.apache.myfaces.trinidadinternal.config.CheckSerializationConfigurator