[infinispan-commits] Infinispan SVN: r144 - in trunk/core/src: main/java/org/infinispan/commands and 21 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Fri Apr 17 14:34:11 EDT 2009


Author: manik.surtani at jboss.com
Date: 2009-04-17 14:34:10 -0400 (Fri, 17 Apr 2009)
New Revision: 144

Added:
   trunk/core/src/main/java/org/infinispan/factories/ResponseGeneratorFactory.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ArrayListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/DeltaAwareExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExceptionResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExtendedResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/GlobalTransactionExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ImmutableMapExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/InternalCachedEntryExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/JGroupsAddressExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/LinkedListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MapExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MarshalledValueExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ReplicableCommandExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/RequestIgnoredResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SetExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SingletonListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/StateTransferControlCommandExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SuccessfulResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/TransactionLogExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/UnsuccessfulResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/
   trunk/core/src/main/java/org/infinispan/remoting/responses/DefaultResponseGenerator.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/DistributionResponseGenerator.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/ExceptionResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/ExtendedResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/InvalidResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/RequestIgnoredResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/Response.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/ResponseGenerator.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/SuccessfulResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/UnsuccessfulResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/responses/ValidResponse.java
   trunk/core/src/test/java/org/infinispan/distribution/
   trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java
   trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java
   trunk/core/src/test/java/org/infinispan/distribution/DistAsyncFuncTest.java
   trunk/core/src/test/java/org/infinispan/distribution/DistAsyncTxFuncTest.java
   trunk/core/src/test/java/org/infinispan/distribution/DistSyncFuncTest.java
   trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java
Removed:
   trunk/core/src/main/java/org/infinispan/marshall/jboss/ArrayListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/DeltaAwareExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/ExtendedResponseExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/GlobalTransactionExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/ImmutableMapExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/InternalCachedEntryExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/JGroupsAddressExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/LinkedListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/MapExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshalledValueExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/ReplicableCommandExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/SetExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/SingletonListExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/StateTransferControlCommandExternalizer.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/TransactionLogExternalizer.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/ExtendedResponse.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/RequestIgnoredResponse.java
Modified:
   trunk/core/src/main/java/org/infinispan/Cache.java
   trunk/core/src/main/java/org/infinispan/CacheDelegate.java
   trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
   trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
   trunk/core/src/main/java/org/infinispan/config/parsing/XmlConfigurationParserImpl.java
   trunk/core/src/main/java/org/infinispan/container/entries/AbstractInternalCacheEntry.java
   trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java
   trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java
   trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java
   trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
   trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
   trunk/core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java
   trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
   trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java
   trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
   trunk/core/src/main/java/org/infinispan/loader/cluster/ClusterCacheLoader.java
   trunk/core/src/main/java/org/infinispan/marshall/MarshallerImpl.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/CustomObjectTable.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/ExternalizerClassFactory.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/MagicNumberClassTable.java
   trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshallUtil.java
   trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandler.java
   trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java
   trunk/core/src/main/java/org/infinispan/remoting/ResponseFilter.java
   trunk/core/src/main/java/org/infinispan/remoting/RpcManager.java
   trunk/core/src/main/java/org/infinispan/remoting/RpcManagerImpl.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/Transport.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/CommandAwareRpcDispatcher.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsResponseFilterAdapter.java
   trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsTransport.java
   trunk/core/src/test/java/org/infinispan/atomic/ClusteredAPITest.java
   trunk/core/src/test/java/org/infinispan/expiry/ReplicatedExpiryTest.java
   trunk/core/src/test/java/org/infinispan/invalidation/BaseInvalidationTest.java
   trunk/core/src/test/java/org/infinispan/marshall/jboss/JBossMarshallerTest.java
   trunk/core/src/test/java/org/infinispan/replication/AsyncReplTest.java
   trunk/core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java
   trunk/core/src/test/java/org/infinispan/replication/ReplicationExceptionTest.java
   trunk/core/src/test/java/org/infinispan/replication/SyncCacheListenerTest.java
   trunk/core/src/test/java/org/infinispan/replication/SyncReplTest.java
   trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
Log:
[JBCACHE-30] (DIST - distributed cache mode) more headway on this - proper marshalling of response values + lots of tests

Modified: trunk/core/src/main/java/org/infinispan/Cache.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/Cache.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/Cache.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -32,11 +32,11 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * The central interface of Infinispan.  A Cache provides a highly concurrent, optionally distributed data structure with
- * additional features such as: <ul> <li>JTA transaction compatibility</li> <li>Eviction support to prevent evicting
- * entries from memory to prevent {@link OutOfMemoryError}s</li> <li>Persisting entries to a {@link
- * org.infinispan.loader.CacheStore}, either when they are evicted as an overflow, or all the time, to maintain persistent
- * copies that would withstand server failure or restarts.</li> </ul>
+ * The central interface of Infinispan.  A Cache provides a highly concurrent, optionally distributed data structure
+ * with additional features such as: <ul> <li>JTA transaction compatibility</li> <li>Eviction support to prevent
+ * evicting entries from memory to prevent {@link OutOfMemoryError}s</li> <li>Persisting entries to a {@link
+ * org.infinispan.loader.CacheStore}, either when they are evicted as an overflow, or all the time, to maintain
+ * persistent copies that would withstand server failure or restarts.</li> </ul>
  * <p/>
  * For convenience, Cache extends {@link java.util.concurrent.ConcurrentMap} and implements all methods accordingly,
  * although methods like {@link java.util.concurrent.ConcurrentMap#keySet()}, {@link
@@ -48,6 +48,20 @@
  * <p/>
  * Please see the <a href="http://www.jboss.org/infinispan/docs">Infinispan documentation</a> for more details.
  * <p/>
+ * A note about return values.  Certain methods on {@link Map} could have indeterminate return values, <i>if</i> the
+ * DISTRIBITION cache mode is used in an asynchronous manner <i>and</i> the invocation takes place on a cache instance
+ * where the entry involved is not local.  These methods are: <ul> <li>{@link #put(Object, Object)} and its variations,
+ * including {@link #putIfAbsent(Object, Object)}</li> <li>{@link #remove(Object)} and its variations</li> <li>{@link
+ * #replace(Object, Object)} and its variations</li> </ul> The methods still <i>behave</i> as expected, i.e., {@link
+ * #putIfAbsent(Object, Object)} will be a no-op if there is a value present, just that since remote calls are
+ * asynchronous and the operation needs to be executed on a remote cache, the calling cache will not wait for a return
+ * value.
+ * <p/>
+ * As such, as a general rule of thumb, return values to these methods should <i>not</i> be used if using DISTRIBUTION
+ * in asynchronous mode.
+ * <p/>
+ * For all other cache modes (including <i>synchronous</i> DISTRIBUTION) these return values are reliable and can be
+ * used.
  *
  * @author Mircea.Markus at jboss.com
  * @author Manik Surtani
@@ -159,11 +173,12 @@
    /**
     * An overloaded form of {@link #put(Object, Object)}, which takes in lifespan parameters.
     *
-    * @param key      key to use
-    * @param value    value to store
-    * @param lifespan lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
-    * @param lifespanUnit time unit for lifespan
-    * @param maxIdleTime the maximum amount of time this key is allowed to be idle for before it is considered as expired
+    * @param key             key to use
+    * @param value           value to store
+    * @param lifespan        lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
+    * @param lifespanUnit    time unit for lifespan
+    * @param maxIdleTime     the maximum amount of time this key is allowed to be idle for before it is considered as
+    *                        expired
     * @param maxIdleTimeUnit time unit for max idle time
     * @return the value being replaced, or null if nothing is being replaced.
     */
@@ -172,11 +187,12 @@
    /**
     * An overloaded form of {@link #putIfAbsent(Object, Object)}, which takes in lifespan parameters.
     *
-    * @param key      key to use
-    * @param value    value to store
-    * @param lifespan lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
-    * @param lifespanUnit time unit for lifespan
-    * @param maxIdleTime the maximum amount of time this key is allowed to be idle for before it is considered as expired
+    * @param key             key to use
+    * @param value           value to store
+    * @param lifespan        lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
+    * @param lifespanUnit    time unit for lifespan
+    * @param maxIdleTime     the maximum amount of time this key is allowed to be idle for before it is considered as
+    *                        expired
     * @param maxIdleTimeUnit time unit for max idle time
     * @return the value being replaced, or null if nothing is being replaced.
     */
@@ -186,10 +202,11 @@
     * An overloaded form of {@link #putAll(java.util.Map)}, which takes in lifespan parameters.  Note that the lifespan
     * is applied to all mappings in the map passed in.
     *
-    * @param map      map containing mappings to enter
-    * @param lifespan lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
-    * @param lifespanUnit time unit for lifespan
-    * @param maxIdleTime the maximum amount of time this key is allowed to be idle for before it is considered as expired
+    * @param map             map containing mappings to enter
+    * @param lifespan        lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
+    * @param lifespanUnit    time unit for lifespan
+    * @param maxIdleTime     the maximum amount of time this key is allowed to be idle for before it is considered as
+    *                        expired
     * @param maxIdleTimeUnit time unit for max idle time
     */
    void putAll(Map<? extends K, ? extends V> map, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit maxIdleTimeUnit);
@@ -197,11 +214,12 @@
    /**
     * An overloaded form of {@link #replace(Object, Object)}, which takes in lifespan parameters.
     *
-    * @param key      key to use
-    * @param value    value to store
-    * @param lifespan lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
-    * @param lifespanUnit time unit for lifespan
-    * @param maxIdleTime the maximum amount of time this key is allowed to be idle for before it is considered as expired
+    * @param key             key to use
+    * @param value           value to store
+    * @param lifespan        lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
+    * @param lifespanUnit    time unit for lifespan
+    * @param maxIdleTime     the maximum amount of time this key is allowed to be idle for before it is considered as
+    *                        expired
     * @param maxIdleTimeUnit time unit for max idle time
     * @return the value being replaced, or null if nothing is being replaced.
     */
@@ -210,12 +228,13 @@
    /**
     * An overloaded form of {@link #replace(Object, Object, Object)}, which takes in lifespan parameters.
     *
-    * @param key      key to use
-    * @param oldValue value to replace
-    * @param value    value to store
-    * @param lifespan lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
-    * @param lifespanUnit time unit for lifespan
-    * @param maxIdleTime the maximum amount of time this key is allowed to be idle for before it is considered as expired
+    * @param key             key to use
+    * @param oldValue        value to replace
+    * @param value           value to store
+    * @param lifespan        lifespan of the entry.  Negative values are intepreted as unlimited lifespan.
+    * @param lifespanUnit    time unit for lifespan
+    * @param maxIdleTime     the maximum amount of time this key is allowed to be idle for before it is considered as
+    *                        expired
     * @param maxIdleTimeUnit time unit for max idle time
     * @return true if the value was replaced, false otherwise
     */

Modified: trunk/core/src/main/java/org/infinispan/CacheDelegate.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/CacheDelegate.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/CacheDelegate.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -45,8 +45,8 @@
 import org.infinispan.factories.annotations.NonVolatile;
 import org.infinispan.interceptors.InterceptorChain;
 import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.invocation.Flag;
 import org.infinispan.invocation.InvocationContextContainer;
-import org.infinispan.invocation.Flag;
 import org.infinispan.lifecycle.ComponentStatus;
 import org.infinispan.logging.Log;
 import org.infinispan.logging.LogFactory;
@@ -55,6 +55,7 @@
 import org.infinispan.marshall.Marshaller;
 import org.infinispan.notifications.cachelistener.CacheNotifier;
 import org.infinispan.remoting.RpcManager;
+import org.infinispan.remoting.responses.ResponseGenerator;
 import org.infinispan.statetransfer.StateTransferManager;
 
 import javax.transaction.Transaction;
@@ -89,6 +90,8 @@
    private CacheManager cacheManager;
    // this is never used here but should be injected - this is a hack to make sure the StateTransferManager is properly constructed if needed.
    private StateTransferManager stateTransferManager;
+   // as above for ResponseGenerator
+   private ResponseGenerator responseGenerator;
    private long defaultLifespan, defaultMaxIdleTime;
 
    public CacheDelegate(String name) {
@@ -106,7 +109,7 @@
                                   TransactionManager transactionManager,
                                   BatchContainer batchContainer,
                                   RpcManager rpcManager, DataContainer dataContainer,
-                                  Marshaller marshaller,
+                                  Marshaller marshaller, ResponseGenerator responseGenerator,
                                   CacheManager cacheManager, StateTransferManager stateTransferManager) {
       this.invocationContextContainer = invocationContextContainer;
       this.commandsFactory = commandsFactory;
@@ -121,6 +124,7 @@
       this.dataContainer = dataContainer;
       this.marshaller = marshaller;
       this.cacheManager = cacheManager;
+      this.responseGenerator = responseGenerator;
       this.stateTransferManager = stateTransferManager;
    }
 

Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -24,6 +24,7 @@
 import org.infinispan.commands.control.StateTransferControlCommand;
 import org.infinispan.commands.read.GetKeyValueCommand;
 import org.infinispan.commands.read.SizeCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
 import org.infinispan.commands.remote.MultipleRpcCommand;
 import org.infinispan.commands.remote.SingleRpcCommand;
 import org.infinispan.commands.tx.CommitCommand;
@@ -76,8 +77,8 @@
    RollbackCommand buildRollbackCommand(GlobalTransaction gtx);
 
    /**
-    * Initializes a {@link org.infinispan.commands.ReplicableCommand} read from a data stream with components specific to
-    * the target cache instance.
+    * Initializes a {@link org.infinispan.commands.ReplicableCommand} read from a data stream with components specific
+    * to the target cache instance.
     * <p/>
     * Implementations should also be deep, in that if the command contains other commands, these should be recursed
     * into.
@@ -92,4 +93,6 @@
    SingleRpcCommand buildSingleRpcCommand(ReplicableCommand call);
 
    StateTransferControlCommand buildStateTransferControlCommand(boolean block);
+
+   ClusteredGetCommand buildClusteredGetCommand(Object key);
 }

Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -136,6 +136,10 @@
       return new StateTransferControlCommand(block);
    }
 
+   public ClusteredGetCommand buildClusteredGetCommand(Object key) {
+      return new ClusteredGetCommand(key, cache.getName());
+   }
+
    public void initializeReplicableCommand(ReplicableCommand c) {
       if (c == null) return;
       switch (c.getCommandId()) {
@@ -160,7 +164,7 @@
             SingleRpcCommand src = (SingleRpcCommand) c;
             src.setInterceptorChain(interceptorChain);
             if (src.getCommand() != null)
-                  initializeReplicableCommand(src.getCommand());
+               initializeReplicableCommand(src.getCommand());
 
             break;
          case InvalidateCommand.COMMAND_ID:

Modified: trunk/core/src/main/java/org/infinispan/config/parsing/XmlConfigurationParserImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/parsing/XmlConfigurationParserImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/config/parsing/XmlConfigurationParserImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -177,8 +177,10 @@
          cacheMode = Configuration.CacheMode.REPL_SYNC;
       else if (mode.startsWith("I"))
          cacheMode = Configuration.CacheMode.INVALIDATION_SYNC;
+      else if (mode.startsWith("D"))
+         throw new ConfigurationException("DIST is unsupported in this release.  Please use REPL or INVAL.");
       else
-         cacheMode = Configuration.CacheMode.DIST_SYNC; // the default
+         cacheMode = Configuration.CacheMode.REPL_SYNC; // the default
 
       Element asyncEl = getSingleElementInCoreNS("async", e);
       Element syncEl = getSingleElementInCoreNS("sync", e);
@@ -213,7 +215,7 @@
          tmp = getAttributeValue(hash, "rehashWait");
          if (existsAttribute(tmp)) config.setRehashWaitTime(getLong(tmp));
 
-         config.setFetchInMemoryState(false);         
+         config.setFetchInMemoryState(false);
 
          // sanity check against the presence of a stateRetrieval element
          Element ste = null;
@@ -306,7 +308,7 @@
          String enabled = getAttributeValue(element, "enabled");
          if (existsAttribute(enabled)) {
             config.setExposeJmxStatistics(getBoolean(enabled));
-         } 
+         }
       }
    }
 

Modified: trunk/core/src/main/java/org/infinispan/container/entries/AbstractInternalCacheEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/AbstractInternalCacheEntry.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/container/entries/AbstractInternalCacheEntry.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -76,4 +76,11 @@
    public final Object getValue() {
       return value;
    }
+
+   @Override
+   public String toString() {
+      return getClass().getSimpleName() + "{" +
+            "key=" + key +
+            '}';
+   }
 }

Modified: trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/container/entries/ImmortalCacheEntry.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -87,4 +87,6 @@
       result = 31 * result + (value != null ? value.hashCode() : 0);
       return result;
    }
+
+
 }

Modified: trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/distribution/ConsistentHash.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -15,9 +15,9 @@
 public interface ConsistentHash {
 
    void setCaches(Collection<Address> caches);
-   
+
    List<Address> locate(Object key, int replCount);
 
-   Map<Object, List<Address>> locate(Collection<Object> keys, int replCount);
-   
+   Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount);
+
 }

Modified: trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/distribution/DefaultConsistentHash.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -15,7 +15,7 @@
 public class DefaultConsistentHash implements ConsistentHash {
    private SortedMap<Integer, Address> caches = new TreeMap<Integer, Address>();
    // must be > max number of nodes in a cluster.  Assume no more than a million nodes in a cluster?  :-)
-   private final static int HASH_SPACE = 1000000;
+   final static int HASH_SPACE = 1000000;
 
 
    public void setCaches(Collection<Address> caches) {
@@ -23,7 +23,7 @@
       // evenly distribute the caches across this space.
       int increaseFactor = HASH_SPACE / caches.size();
       int nextIndex = increaseFactor;
-      for (Address a: caches) {
+      for (Address a : caches) {
          this.caches.put(nextIndex, a);
          nextIndex += increaseFactor;
       }
@@ -57,9 +57,9 @@
       return Immutables.immutableListConvert(results);
    }
 
-   public Map<Object, List<Address>> locate(Collection<Object> keys, int replCount) {
+   public Map<Object, List<Address>> locateAll(Collection<Object> keys, int replCount) {
       Map<Object, List<Address>> locations = new HashMap<Object, List<Address>>();
-      for (Object k: keys) locations.put(k, locate(k, replCount));
+      for (Object k : keys) locations.put(k, locate(k, replCount));
       return locations;
    }
 }

Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -4,6 +4,7 @@
 import org.infinispan.factories.scopes.Scopes;
 import org.infinispan.remoting.transport.Address;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -13,17 +14,18 @@
  * @author Manik Surtani
  * @since 4.0
  */
- at Scope(Scopes.GLOBAL)
+ at Scope(Scopes.NAMED_CACHE)
 public interface DistributionManager {
 
-   void rehash();
+   void rehash(Collection<Address> newList);
 
    boolean isLocal(Object key);
 
    /**
-    * Locates a key in a cluster.  The returned addresses <i>may not</i> be owners of the keys if a rehash happens to
-    * be in progress or is pending, so when querying these servers, invalid responses should be checked for and the
-    * next address checked accordingly.
+    * Locates a key in a cluster.  The returned addresses <i>may not</i> be owners of the keys if a rehash happens to be
+    * in progress or is pending, so when querying these servers, invalid responses should be checked for and the next
+    * address checked accordingly.
+    *
     * @param key key to test
     * @return a list of addresses where the key may reside
     */
@@ -33,9 +35,10 @@
     * Locates a list of keys in a cluster.  Like {@link #locate(Object)} the returned addresses <i>may not</i> be owners
     * of the keys if a rehash happens to be in progress or is pending, so when querying these servers, invalid responses
     * should be checked for and the next address checked accordingly.
+    *
     * @param keys list of keys to test
     * @return a list of addresses where the key may reside
     */
-   Map<Object, List<Address>> locate(List<Object> keys);
+   Map<Object, List<Address>> locateAll(Collection<Object> keys);
 }
 

Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,12 +1,20 @@
 package org.infinispan.distribution;
 
-import org.infinispan.Cache;
 import org.infinispan.config.Configuration;
 import org.infinispan.factories.annotations.Inject;
 import org.infinispan.factories.annotations.Start;
+import org.infinispan.factories.annotations.Stop;
+import org.infinispan.logging.Log;
+import org.infinispan.logging.LogFactory;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachemanagerlistener.CacheManagerNotifier;
+import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged;
+import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent;
 import org.infinispan.remoting.RpcManager;
 import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.Util;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -17,39 +25,62 @@
  * @since 4.0
  */
 public class DistributionManagerImpl implements DistributionManager {
-
+   private final Log log = LogFactory.getLog(DistributionManagerImpl.class);
+   private final boolean trace = log.isTraceEnabled();
    Configuration configuration;
    ConsistentHash consistentHash;
    RpcManager rpcManager;
+   CacheManagerNotifier notifier;
    int replCount;
-   Cache cache;
+   ViewChangeListener listener;
 
    @Inject
-   public void init(Cache cache, Configuration configuration, RpcManager rpcManager) {
-      this.cache = cache;
+   public void init(Configuration configuration, RpcManager rpcManager, CacheManagerNotifier notifier) {
       this.configuration = configuration;
       this.rpcManager = rpcManager;
+      this.notifier = notifier;
    }
 
-   @Start
-   public void start() {
-      replCount = 2; // TODO read this from the configuration
-      consistentHash = new DefaultConsistentHash(); // TODO read this from the configuration
+   // needs to be AFTER the RpcManager
+   @Start(priority = 20)
+   public void start() throws Exception {
+      replCount = configuration.getNumOwners();
+      consistentHash = (ConsistentHash) Util.getInstance(configuration.getConsistentHashClass());
+      consistentHash.setCaches(rpcManager.getTransport().getMembers());
+      listener = new ViewChangeListener();
+      notifier.addListener(listener);
    }
 
-   public void rehash() {
-      // TODO: Customise this generated block
+   @Stop(priority = 20)
+   public void stop() {
+      notifier.removeListener(listener);
    }
 
+   public void rehash(Collection<Address> newList) {
+      // on view change, we should update our view
+      consistentHash.setCaches(newList);
+   }
+
    public boolean isLocal(Object key) {
       return consistentHash.locate(key, replCount).contains(rpcManager.getLocalAddress());
    }
 
    public List<Address> locate(Object key) {
-      return null;  // TODO: Customise this generated block
+      List<Address> adds = consistentHash.locate(key, replCount);
+      if (trace) log.trace("Located {0} addresses for key {1}.  Repl count is {2}, addresses are {3}", adds.size(),
+                           key, replCount, adds);
+      return adds;
    }
 
-   public Map<Object, List<Address>> locate(List<Object> keys) {
-      return null;  // TODO: Customise this generated block
+   public Map<Object, List<Address>> locateAll(Collection<Object> keys) {
+      return consistentHash.locateAll(keys, replCount);
    }
+
+   @Listener
+   public class ViewChangeListener {
+      @ViewChanged
+      public void handleViewChange(ViewChangedEvent e) {
+         rehash(e.getNewMemberList());
+      }
+   }
 }

Modified: trunk/core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/factories/AbstractComponentRegistry.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -67,7 +67,8 @@
  * The registry can exist in one of several states, as defined by the {@link org.infinispan.lifecycle.ComponentStatus}
  * enumeration. In terms of the cache, state changes in the following manner: <ul> <li>INSTANTIATED - when first
  * constructed</li> <li>CONSTRUCTED - when created using the DefaultCacheFactory</li> <li>STARTED - when {@link
- * org.infinispan.Cache#start()} is called</li> <li>STOPPED - when {@link org.infinispan.Cache#stop()} is called</li> </ul>
+ * org.infinispan.Cache#start()} is called</li> <li>STOPPED - when {@link org.infinispan.Cache#stop()} is called</li>
+ * </ul>
  * <p/>
  * Cache configuration can only be changed and will only be reinjected if the cache is not in the {@link
  * org.infinispan.lifecycle.ComponentStatus#RUNNING} state.
@@ -79,7 +80,7 @@
 @Scope(Scopes.NAMED_CACHE)
 public abstract class AbstractComponentRegistry implements Lifecycle {
 
-   // Be careful when changing this to 'true'.  It should *never* go into the code repo with this flag set to 'true'!
+   // TODO remove this debug code as it is HUGELY inefficient 
    private static final boolean DEBUG_DEPENDENCIES = true;
    private Stack<String> debugStack = DEBUG_DEPENDENCIES ? new Stack<String>() : null;
 
@@ -153,6 +154,7 @@
       s.add(NamedExecutorsFactory.class);
       s.add(TransportFactory.class);
       s.add(MarshallerFactory.class);
+      s.add(ResponseGeneratorFactory.class);
       return s;
    }
 
@@ -585,8 +587,9 @@
    }
 
    /**
-    * Stops the cache and sets the cache status to {@link org.infinispan.lifecycle.ComponentStatus#TERMINATED} once it is
-    * done.  If the cache is not in the {@link org.infinispan.lifecycle.ComponentStatus#RUNNING} state, this is a no-op.
+    * Stops the cache and sets the cache status to {@link org.infinispan.lifecycle.ComponentStatus#TERMINATED} once it
+    * is done.  If the cache is not in the {@link org.infinispan.lifecycle.ComponentStatus#RUNNING} state, this is a
+    * no-op.
     */
    public void stop() {
       if (!state.stopAllowed()) {
@@ -615,8 +618,8 @@
     * Destroys the cache and frees up any resources.  Sets the cache status to {@link
     * org.infinispan.lifecycle.ComponentStatus#TERMINATED} when it is done.
     * <p/>
-    * If the cache is in {@link org.infinispan.lifecycle.ComponentStatus#RUNNING} when this method is called, it will first
-    * call {@link #stop()} to stop the cache.
+    * If the cache is in {@link org.infinispan.lifecycle.ComponentStatus#RUNNING} when this method is called, it will
+    * first call {@link #stop()} to stop the cache.
     */
    private void destroy() {
       try {
@@ -728,8 +731,8 @@
     * org.infinispan.lifecycle.ComponentStatus#INITIALIZING}, this method will block for up to {@link
     * Configuration#getStateRetrievalTimeout()} millis, checking for a valid state.
     *
-    * @param originLocal true if the call originates locally (i.e., from the {@link org.infinispan.CacheDelegate} or false
-    *                    if it originates remotely, i.e., from the {@link org.infinispan.remoting.InboundInvocationHandler}.
+    * @param originLocal true if the call originates locally (i.e., from the {@link org.infinispan.CacheDelegate} or
+    *                    false if it originates remotely, i.e., from the {@link org.infinispan.remoting.InboundInvocationHandler}.
     * @return true if invocations are allowed, false otherwise.
     */
    public boolean invocationsAllowed(boolean originLocal) {

Modified: trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/factories/EmptyConstructorNamedCacheFactory.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -25,6 +25,8 @@
 import org.infinispan.batch.BatchContainer;
 import org.infinispan.commands.CommandsFactory;
 import org.infinispan.config.ConfigurationException;
+import org.infinispan.distribution.DistributionManager;
+import org.infinispan.eviction.EvictionManager;
 import org.infinispan.factories.annotations.DefaultFactoryFor;
 import org.infinispan.factories.context.ContextFactory;
 import org.infinispan.invocation.InvocationContextContainer;
@@ -32,9 +34,8 @@
 import org.infinispan.marshall.Marshaller;
 import org.infinispan.marshall.VersionAwareMarshaller;
 import org.infinispan.notifications.cachelistener.CacheNotifier;
+import org.infinispan.transaction.TransactionLog;
 import org.infinispan.transaction.TransactionTable;
-import org.infinispan.transaction.TransactionLog;
-import org.infinispan.eviction.EvictionManager;
 
 /**
  * Simple factory that just uses reflection and an empty constructor of the component type.
@@ -45,7 +46,7 @@
 @DefaultFactoryFor(classes = {CacheNotifier.class, EntryFactory.class, CommandsFactory.class,
                               CacheLoaderManager.class, InvocationContextContainer.class,
                               TransactionTable.class, BatchContainer.class, ContextFactory.class,
-                              TransactionLog.class, EvictionManager.class})
+                              TransactionLog.class, EvictionManager.class, DistributionManager.class})
 public class EmptyConstructorNamedCacheFactory extends AbstractNamedCacheComponentFactory implements AutoInstantiableFactory {
    @Override
    public <T> T construct(Class<T> componentType) {

Modified: trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/factories/InterceptorChainFactory.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -93,6 +93,10 @@
          case INVALIDATION_ASYNC:
             interceptorChain.appendIntereceptor(createInterceptor(InvalidationInterceptor.class));
             break;
+         case DIST_SYNC:
+         case DIST_ASYNC:
+            interceptorChain.appendIntereceptor(createInterceptor(DistributionInterceptor.class));
+            break;
          case LOCAL:
             //Nothing...
       }
@@ -107,7 +111,7 @@
          }
       }
       interceptorChain.appendIntereceptor(createInterceptor(LockingInterceptor.class));
-      
+
       CommandInterceptor callInterceptor = createInterceptor(CallInterceptor.class);
       interceptorChain.appendIntereceptor(callInterceptor);
       if (log.isTraceEnabled()) log.trace("Finished building default interceptor chain.");

Added: trunk/core/src/main/java/org/infinispan/factories/ResponseGeneratorFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/factories/ResponseGeneratorFactory.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/factories/ResponseGeneratorFactory.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,24 @@
+package org.infinispan.factories;
+
+import org.infinispan.factories.annotations.DefaultFactoryFor;
+import org.infinispan.remoting.responses.DefaultResponseGenerator;
+import org.infinispan.remoting.responses.DistributionResponseGenerator;
+import org.infinispan.remoting.responses.ResponseGenerator;
+
+/**
+ * Creates a ResponseGenerator
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+ at DefaultFactoryFor(classes = ResponseGenerator.class)
+public class ResponseGeneratorFactory extends AbstractNamedCacheComponentFactory implements AutoInstantiableFactory {
+
+   @SuppressWarnings("unchecked")
+   public <T> T construct(Class<T> componentType) {
+      if (configuration.getCacheMode().isDistributed())
+         return (T) new DistributionResponseGenerator();
+      else
+         return (T) new DefaultResponseGenerator();
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/factories/ResponseGeneratorFactory.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,8 +1,38 @@
 package org.infinispan.interceptors;
 
+import org.infinispan.commands.CommandsFactory;
+import org.infinispan.commands.DataCommand;
+import org.infinispan.commands.read.GetKeyValueCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.commands.tx.CommitCommand;
+import org.infinispan.commands.tx.PrepareCommand;
+import org.infinispan.commands.tx.RollbackCommand;
+import org.infinispan.commands.write.ClearCommand;
+import org.infinispan.commands.write.InvalidateCommand;
+import org.infinispan.commands.write.PutKeyValueCommand;
+import org.infinispan.commands.write.PutMapCommand;
+import org.infinispan.commands.write.RemoveCommand;
+import org.infinispan.commands.write.ReplaceCommand;
+import org.infinispan.commands.write.WriteCommand;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.context.TransactionContext;
+import org.infinispan.distribution.DistributionManager;
+import org.infinispan.factories.annotations.Inject;
 import org.infinispan.interceptors.base.BaseRpcInterceptor;
-import org.infinispan.distribution.DistributionManager;
+import org.infinispan.remoting.ResponseMode;
+import org.infinispan.remoting.responses.Response;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.transaction.GlobalTransaction;
+import org.infinispan.util.Immutables;
 
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * // TODO: Document this
  *
@@ -10,7 +40,240 @@
  * @since 4.0
  */
 public class DistributionInterceptor extends BaseRpcInterceptor {
+   DistributionManager dm;
+   CommandsFactory cf;
+   // TODO move this to the transaction context.  Will scale better there.
+   private final Map<GlobalTransaction, List<Address>> txRecipients = new ConcurrentHashMap<GlobalTransaction, List<Address>>();
+   static final RecipientGenerator CLEAR_COMMAND_GENERATOR = new RecipientGenerator() {
 
-   DistributionManager dm;
-   
+      public List<Address> generateRecipients() {
+         return null;
+      }
+
+      public Object[] getKeys() {
+         return null;
+      }
+   };
+
+   @Inject
+   public void injectDependencies(DistributionManager distributionManager, CommandsFactory cf) {
+      this.dm = distributionManager;
+      this.cf = cf;
+   }
+
+   // ---- READ commands
+
+   // if we don't have the key locally, fetch from one of the remote servers
+   // and if L1 is enabled, cache in L1
+   // then return
+
+   @Override
+   public Object visitGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand command) throws Throwable {
+      Object returnValue = invokeNextInterceptor(ctx, command);
+      if (returnValue == null) {
+         // attempt a remote lookup
+         // TODO update ClusteredGetCommand (maybe a new command?) to ensure we get back ICEs.
+         ClusteredGetCommand get = cf.buildClusteredGetCommand(command.getKey());
+         // TODO use a RspFilter to filter responses         
+         List<Response> responses = rpcManager.invokeRemotely(dm.locate(command.getKey()), get, ResponseMode.SYNCHRONOUS,
+                                                              configuration.getSyncReplTimeout(), false, false);
+
+         // the first response is all that matters
+         if (responses.isEmpty()) return returnValue;
+
+         for (Object response : responses) {
+            if (!(response instanceof Throwable)) {
+               InternalCacheEntry ice = (InternalCacheEntry) response;
+               if (configuration.isL1CacheEnabled()) {
+                  long lifespan = ice.getLifespan() < 0 ? configuration.getL1Lifespan() : Math.min(ice.getLifespan(), configuration.getL1Lifespan());
+                  PutKeyValueCommand put = cf.buildPutKeyValueCommand(ice.getKey(), ice.getValue(), lifespan, -1);
+                  invokeNextInterceptor(ctx, put);
+               }
+               return ice.getValue();
+            }
+         }
+         return null;
+      }
+      return returnValue;
+   }
+
+   // ---- WRITE commands
+
+   @Override
+   public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
+      return handleWriteCommand(ctx, command,
+                                new SingleKeyRecipientGenerator(command.getKey()));
+   }
+
+   @Override
+   public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
+      return handleWriteCommand(ctx, command,
+                                new MultipleKeysRecipientGenerator(command.getMap().keySet()));
+   }
+
+   @Override
+   public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
+      return handleWriteCommand(ctx, command,
+                                new SingleKeyRecipientGenerator(command.getKey()));
+   }
+
+   @Override
+   public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
+      return handleWriteCommand(ctx, command, CLEAR_COMMAND_GENERATOR);
+   }
+
+   @Override
+   public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
+      return handleWriteCommand(ctx, command,
+                                new SingleKeyRecipientGenerator(command.getKey()));
+   }
+
+   // ---- TX boundard commands
+   @Override
+   public Object visitCommitCommand(InvocationContext ctx, CommitCommand command) throws Throwable {
+      try {
+         if (!skipReplicationOfTransactionMethod(ctx)) {
+            List<Address> recipients = txRecipients.get(command.getGlobalTransaction());
+            if (recipients != null) replicateCall(ctx, recipients, command, configuration.isSyncCommitPhase(), true);
+         }
+         return invokeNextInterceptor(ctx, command);
+      } finally {
+         txRecipients.remove(command.getGlobalTransaction());
+      }
+   }
+
+   @Override
+   public Object visitPrepareCommand(InvocationContext ctx, PrepareCommand command) throws Throwable {
+      Object retVal = invokeNextInterceptor(ctx, command);
+      TransactionContext transactionContext = ctx.getTransactionContext();
+      if (transactionContext.hasLocalModifications()) {
+         PrepareCommand replicablePrepareCommand = command.copy(); // make sure we remove any "local" transactions
+         replicablePrepareCommand.removeModifications(transactionContext.getLocalModifications());
+         command = replicablePrepareCommand;
+      }
+
+      if (!skipReplicationOfTransactionMethod(ctx)) {
+         boolean sync = configuration.getCacheMode().isSynchronous();
+         if (trace) {
+            log.trace("[" + rpcManager.getTransport().getAddress() + "] Running remote prepare for global tx {1}.  Synchronous? {2}",
+                      rpcManager.getTransport().getAddress(), command.getGlobalTransaction(), sync);
+         }
+
+         List<Address> recipients = determineRecipients(command);
+         txRecipients.put(command.getGlobalTransaction(), recipients);
+
+         // this method will return immediately if we're the only member (because exclude_self=true)
+         replicateCall(ctx, command, sync);
+      }
+
+      return retVal;
+   }
+
+   @Override
+   public Object visitRollbackCommand(InvocationContext ctx, RollbackCommand command) throws Throwable {
+      try {
+         if (!skipReplicationOfTransactionMethod(ctx) && !ctx.isLocalRollbackOnly()) {
+            List<Address> recipients = txRecipients.get(command.getGlobalTransaction());
+            if (recipients != null) replicateCall(ctx, recipients, command, configuration.isSyncRollbackPhase(), true);
+         }
+         return invokeNextInterceptor(ctx, command);
+      } finally {
+         txRecipients.remove(command.getGlobalTransaction());
+      }
+   }
+
+   private List<Address> determineRecipients(PrepareCommand cmd) {
+      Set<Address> r = new HashSet<Address>();
+      boolean toAll = false;
+      for (WriteCommand c : cmd.getModifications()) {
+         if (c instanceof ClearCommand) {
+            toAll = true;
+            break;
+         } else {
+            if (c instanceof DataCommand) {
+               r.addAll(dm.locate(((DataCommand) c).getKey()));
+            } else if (c instanceof PutMapCommand) {
+               r.addAll(new MultipleKeysRecipientGenerator(((PutMapCommand) c).getMap().keySet()).generateRecipients());
+            }
+         }
+      }
+
+      return toAll ? null : Immutables.immutableListConvert(r);
+   }
+
+
+   /**
+    * If we are within one transaction we won't do any replication as replication would only be performed at commit
+    * time. If the operation didn't originate locally we won't do any replication either.
+    */
+   private Object handleWriteCommand(InvocationContext ctx, WriteCommand command, RecipientGenerator recipientGenerator) throws Throwable {
+      boolean local = isLocalModeForced(ctx);
+      if (local && ctx.getTransaction() == null) return invokeNextInterceptor(ctx, command);
+      // FIRST pass this call up the chain.  Only if it succeeds (no exceptions) locally do we attempt to replicate.
+
+      Object returnValue = invokeNextInterceptor(ctx, command);
+
+      if (command.isSuccessful()) {
+         if (ctx.getTransaction() == null && ctx.isOriginLocal()) {
+            if (trace) {
+               log.trace("invoking method " + command.getClass().getSimpleName() + ", members=" + rpcManager.getTransport().getMembers() + ", mode=" +
+                     configuration.getCacheMode() + ", exclude_self=" + true + ", timeout=" +
+                     configuration.getSyncReplTimeout());
+            }
+
+            List<Address> rec = recipientGenerator.generateRecipients();
+            // if L1 caching is used make sure we broadcast an invalidate message
+            if (configuration.isL1CacheEnabled() && rec != null) {
+               InvalidateCommand ic = cf.buildInvalidateCommand(recipientGenerator.getKeys());
+               replicateCall(ctx, ic, isSynchronous(ctx), false);
+            }
+            replicateCall(ctx, rec, command, isSynchronous(ctx), false);
+         } else {
+            if (local) ctx.getTransactionContext().addLocalModification(command);
+         }
+      }
+      return returnValue;
+   }
+
+   interface RecipientGenerator {
+      List<Address> generateRecipients();
+
+      Object[] getKeys();
+   }
+
+   class SingleKeyRecipientGenerator implements RecipientGenerator {
+      Object key;
+
+      SingleKeyRecipientGenerator(Object key) {
+         this.key = key;
+      }
+
+      public List<Address> generateRecipients() {
+         return dm.locate(key);
+      }
+
+      public Object[] getKeys() {
+         return new Object[]{key};
+      }
+   }
+
+   class MultipleKeysRecipientGenerator implements RecipientGenerator {
+
+      Collection<Object> keys;
+
+      MultipleKeysRecipientGenerator(Collection<Object> keys) {
+         this.keys = keys;
+      }
+
+      public List<Address> generateRecipients() {
+         Set<Address> addresses = new HashSet<Address>();
+         Map<Object, List<Address>> recipients = dm.locateAll(keys);
+         for (List<Address> a : recipients.values()) addresses.addAll(a);
+         return Immutables.immutableListConvert(addresses);
+      }
+
+      public Object[] getKeys() {
+         return keys.toArray();
+      }
+   }
 }

Modified: trunk/core/src/main/java/org/infinispan/loader/cluster/ClusterCacheLoader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loader/cluster/ClusterCacheLoader.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/loader/cluster/ClusterCacheLoader.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -12,9 +12,11 @@
 import org.infinispan.logging.Log;
 import org.infinispan.logging.LogFactory;
 import org.infinispan.marshall.Marshaller;
-import org.infinispan.remoting.RpcManager;
 import org.infinispan.remoting.ResponseFilter;
 import org.infinispan.remoting.ResponseMode;
+import org.infinispan.remoting.RpcManager;
+import org.infinispan.remoting.responses.Response;
+import org.infinispan.remoting.responses.SuccessfulResponse;
 import org.infinispan.remoting.transport.Address;
 
 import java.util.ArrayList;
@@ -23,17 +25,13 @@
 import java.util.Set;
 
 /**
- *  Cache loader that consults other members in the cluster for values. A
- * <code>timeout</code> property is required, a <code>long</code> that
- * specifies in milliseconds how long to wait for results before returning a
- * null.
+ * Cache loader that consults other members in the cluster for values. A <code>timeout</code> property is required, a
+ * <code>long</code> that specifies in milliseconds how long to wait for results before returning a null.
  *
  * @author Mircea.Markus at jboss.com
  */
 public class ClusterCacheLoader extends AbstractCacheLoader {
-
    private static Log log = LogFactory.getLog(ClusterCacheLoader.class);
-   private static boolean trace = log.isTraceEnabled();
 
    private ClusterCacheLoaderConfig config;
    private RpcManager rpcManager;
@@ -48,14 +46,18 @@
    public InternalCacheEntry load(Object key) throws CacheLoaderException {
       if (!(isCacheReady() && isLocalCall())) return null;
       ClusteredGetCommand clusteredGetCommand = new ClusteredGetCommand(key, cache.getName());
-      List<Object> response = doRemoteCall(clusteredGetCommand);
+      List<Response> response = doRemoteCall(clusteredGetCommand);
       if (response.isEmpty()) return null;
       if (response.size() > 1)
          throw new CacheLoaderException("Response length is always 0 or 1, received: " + response);
-      Object firstResponse = response.get(0);
-      if (firstResponse instanceof InternalCacheEntry)
-         return (InternalCacheEntry) firstResponse;
-      return (InternalCacheEntry) unknownResponse(firstResponse);
+      Response firstResponse = response.get(0);
+      if (firstResponse.isSuccessful() && firstResponse instanceof SuccessfulResponse) {
+         return (InternalCacheEntry) ((SuccessfulResponse) firstResponse).getResponseValue();
+      }
+
+      String message = "Unknown response from remote cache: " + response;
+      log.error(message);
+      throw new CacheLoaderException(message);
    }
 
    @SuppressWarnings(value = "unchecked")
@@ -63,12 +65,6 @@
       return Collections.EMPTY_SET;
    }
 
-   private Object unknownResponse(Object response) throws CacheLoaderException {
-      String message = "Unknown response from remote cache: " + response;
-      log.error(message);
-      throw new CacheLoaderException(message);
-   }
-
    public void start() throws CacheLoaderException {
       //nothing to do here
    }
@@ -93,14 +89,11 @@
          this.pendingResponders.remove(localAddress);
       }
 
-      public boolean isAcceptable(Object object, Address address) {
+      public boolean isAcceptable(Response response, Address address) {
          pendingResponders.remove(address);
 
-         if (object instanceof List) {
-            List response = (List) object;
-            Boolean foundResult = (Boolean) response.get(0);
-            if (foundResult) numValidResponses++;
-         }
+         if (response instanceof SuccessfulResponse) numValidResponses++;
+
          // always return true to make sure a response is logged by the JGroups RpcDispatcher.
          return true;
       }
@@ -111,7 +104,7 @@
 
    }
 
-   private List<Object> doRemoteCall(ClusteredGetCommand clusteredGetCommand) throws CacheLoaderException {
+   private List<Response> doRemoteCall(ClusteredGetCommand clusteredGetCommand) throws CacheLoaderException {
       ResponseValidityFilter filter = new ResponseValidityFilter(rpcManager.getTransport().getMembers(), rpcManager.getLocalAddress());
       try {
          return rpcManager.invokeRemotely(null, clusteredGetCommand, ResponseMode.WAIT_FOR_VALID_RESPONSE, config.getRemoteCallTimeout(), false, filter, false);

Modified: trunk/core/src/main/java/org/infinispan/marshall/MarshallerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/MarshallerImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/MarshallerImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -22,20 +22,24 @@
 package org.infinispan.marshall;
 
 import org.infinispan.CacheException;
-import org.infinispan.container.entries.InternalCacheEntry;
-import org.infinispan.container.entries.InternalEntryFactory;
 import org.infinispan.atomic.DeltaAware;
 import org.infinispan.commands.RemoteCommandFactory;
 import org.infinispan.commands.ReplicableCommand;
 import org.infinispan.commands.write.WriteCommand;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.container.entries.InternalEntryFactory;
 import org.infinispan.io.ByteBuffer;
 import org.infinispan.io.ExposedByteArrayOutputStream;
 import org.infinispan.logging.Log;
 import org.infinispan.logging.LogFactory;
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.Response;
+import org.infinispan.remoting.responses.SuccessfulResponse;
+import org.infinispan.remoting.responses.UnsuccessfulResponse;
 import org.infinispan.remoting.transport.Address;
-import org.infinispan.remoting.transport.jgroups.ExtendedResponse;
 import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
-import org.infinispan.remoting.transport.jgroups.RequestIgnoredResponse;
 import org.infinispan.transaction.GlobalTransaction;
 import org.infinispan.transaction.TransactionLog;
 import org.infinispan.util.FastCopyHashMap;
@@ -91,8 +95,14 @@
    protected static final int MAGICNUMBER_COMMAND = 24;
    protected static final int MAGICNUMBER_TRANSACTION_LOG = 25;
    protected static final int MAGICNUMBER_INTERNAL_CACHED_ENTRY = 26;
+
+   // ---- responses
    protected static final int MAGICNUMBER_REQUEST_IGNORED_RESPONSE = 27;
-   protected static final int MAGICNUMBER_EXTENDED_RESPONSE = 28;   
+   protected static final int MAGICNUMBER_EXTENDED_RESPONSE = 28;
+   protected static final int MAGICNUMBER_EXCEPTION_RESPONSE = 29;
+   protected static final int MAGICNUMBER_SUCCESSFUL_RESPONSE = 30;
+   protected static final int MAGICNUMBER_UNSUCCESSFUL_RESPONSE = 31;
+
    protected static final int MAGICNUMBER_NULL = 99;
    protected static final int MAGICNUMBER_SERIALIZABLE = 100;
    protected static final int MAGICNUMBER_REF = 101;
@@ -160,13 +170,8 @@
          } else if (o instanceof JGroupsAddress) {
             out.writeByte(MAGICNUMBER_JG_ADDRESS);
             marshallJGroupsAddress((JGroupsAddress) o, out);
-         } else if (o instanceof RequestIgnoredResponse) {
-            out.writeByte(MAGICNUMBER_REQUEST_IGNORED_RESPONSE);
-         } else if (o instanceof ExtendedResponse) {
-            out.writeByte(MAGICNUMBER_EXTENDED_RESPONSE);
-            ExtendedResponse er = (ExtendedResponse) o;
-            out.writeBoolean(er.isReplayIgnoredRequests());
-            marshallObject(er.getResponse(), out, refMap);
+         } else if (o instanceof Response) {
+            marshallResponse((Response) o, out, refMap);
          } else if (o instanceof InternalCacheEntry) {
             out.writeByte(MAGICNUMBER_INTERNAL_CACHED_ENTRY);
             InternalCacheEntry ice = (InternalCacheEntry) o;
@@ -299,8 +304,49 @@
       }
    }
 
+   private void marshallResponse(Response response, ObjectOutput out, Map<Object, Integer> refMap) throws IOException {
+      if (response instanceof RequestIgnoredResponse) {
+         out.writeByte(MAGICNUMBER_REQUEST_IGNORED_RESPONSE);
+      } else if (response instanceof ExtendedResponse) {
+         out.writeByte(MAGICNUMBER_EXTENDED_RESPONSE);
+         ExtendedResponse er = (ExtendedResponse) response;
+         out.writeBoolean(er.isReplayIgnoredRequests());
+         marshallObject(er.getResponse(), out, refMap);
+      } else if (response instanceof UnsuccessfulResponse) {
+         out.writeByte(MAGICNUMBER_UNSUCCESSFUL_RESPONSE);
+      } else if (response instanceof SuccessfulResponse) {
+         out.writeByte(MAGICNUMBER_SUCCESSFUL_RESPONSE);
+         marshallObject(((SuccessfulResponse) response).getResponseValue(), out, refMap);
+      } else if (response instanceof ExceptionResponse) {
+         out.writeByte(MAGICNUMBER_EXCEPTION_RESPONSE);
+         marshallObject(((ExceptionResponse) response).getException(), out, refMap);
+      }
+   }
+
    // --------- Unmarshalling methods
 
+   private Response unmarshallResponse(int magic, ObjectInput in, UnmarshalledReferences refMap) throws IOException, ClassNotFoundException {
+
+      switch (magic) {
+         case MAGICNUMBER_REQUEST_IGNORED_RESPONSE:
+            return RequestIgnoredResponse.INSTANCE;
+         case MAGICNUMBER_UNSUCCESSFUL_RESPONSE:
+            return UnsuccessfulResponse.INSTANCE;
+         case MAGICNUMBER_SUCCESSFUL_RESPONSE:
+            Object retval = unmarshallObject(in, refMap);
+            return new SuccessfulResponse(retval);
+         case MAGICNUMBER_EXCEPTION_RESPONSE:
+            Exception e = (Exception) unmarshallObject(in, refMap);
+            return new ExceptionResponse(e);
+         case MAGICNUMBER_EXTENDED_RESPONSE:
+            boolean replay = in.readBoolean();
+            Response response = (Response) unmarshallObject(in, refMap);
+            return new ExtendedResponse(response, replay);
+         default:
+            return null;
+      }
+   }
+
    protected Object unmarshallObject(ObjectInput in, ClassLoader loader, UnmarshalledReferences refMap, boolean overrideContextClassloaderOnThread) throws IOException, ClassNotFoundException {
       if (loader == null) {
          return unmarshallObject(in, refMap);
@@ -353,11 +399,11 @@
                return InternalEntryFactory.create(k, v);
             }
          case MAGICNUMBER_REQUEST_IGNORED_RESPONSE:
-            return RequestIgnoredResponse.INSTANCE;
          case MAGICNUMBER_EXTENDED_RESPONSE:
-            boolean replayIgnoredRequests = in.readBoolean();
-            Object response = unmarshallObject(in, refMap);
-            return new ExtendedResponse(response, replayIgnoredRequests);
+         case MAGICNUMBER_EXCEPTION_RESPONSE:
+         case MAGICNUMBER_UNSUCCESSFUL_RESPONSE:
+         case MAGICNUMBER_SUCCESSFUL_RESPONSE:
+            return unmarshallResponse(magicNumber, in, refMap);
          case MAGICNUMBER_COMMAND:
             retVal = unmarshallCommand(in, refMap);
             return retVal;
@@ -802,11 +848,11 @@
    public ObjectOutput startObjectOutput(OutputStream os) throws IOException {
       return new ObjectOutputStream(os);
    }
-   
+
    public void finishObjectOutput(ObjectOutput oo) {
       Util.flushAndCloseOutput(oo);
    }
-   
+
    public void objectToObjectStream(Object o, ObjectOutput out) throws IOException {
       Map<Object, Integer> refMap = useRefs ? new IdentityHashMap<Object, Integer>() : null;
       ClassLoader toUse = defaultClassLoader;
@@ -822,11 +868,11 @@
          current.setContextClassLoader(old);
       }
    }
-   
+
    public ObjectInput startObjectInput(InputStream is) throws IOException {
       return new ObjectInputStream(is);
    }
-   
+
    public void finishObjectInput(ObjectInput oi) {
       Util.closeInput(oi);
    }

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/ArrayListExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ArrayListExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ArrayListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,64 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import net.jcip.annotations.Immutable;
-
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * List externalizer dealing with ArrayList and LinkedList implementations.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class ArrayListExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = 589638638644295615L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      MarshallUtil.marshallCollection((Collection) subject, output);
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      int size = MarshallUtil.readUnsignedInt(input);
-      ArrayList l = new ArrayList(size);
-      for (int i = 0; i < size; i++) l.add(input.readObject());
-      return l;
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op since size was needed both for the creation and list population, 
-      // so all the work was done in createExternal 
-   }
-}
\ No newline at end of file

Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/CustomObjectTable.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/CustomObjectTable.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/CustomObjectTable.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,44 +21,43 @@
  */
 package org.infinispan.marshall.jboss;
 
+import net.jcip.annotations.Immutable;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.jboss.marshalling.Marshaller;
+import org.jboss.marshalling.ObjectTable;
+import org.jboss.marshalling.Unmarshaller;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.remoting.transport.jgroups.RequestIgnoredResponse;
-import org.jboss.marshalling.Marshaller;
-import org.jboss.marshalling.ObjectTable;
-import org.jboss.marshalling.Unmarshaller;
-
 /**
  * CustomObjectTable.
- * 
+ *
  * @author Galder Zamarreño
  * @since 4.0
  */
 public class CustomObjectTable implements ObjectTable {
-   
+
    private final List<Object> objects = new ArrayList<Object>();
    private final Map<Object, Writer> writers = new IdentityHashMap<Object, Writer>();
    private byte index;
-   
+
    public void init() {
       objects.add(RequestIgnoredResponse.INSTANCE);
       writers.put(RequestIgnoredResponse.INSTANCE, new CustomObjectWriter(index++));
    }
-   
+
    public void stop() {
       writers.clear();
       objects.clear();
    }
-   
+
    public void add(Object o) {
       objects.add(o);
-      writers.put(o, new CustomObjectWriter(index++));      
+      writers.put(o, new CustomObjectWriter(index++));
    }
 
    public Writer getObjectWriter(Object o) throws IOException {
@@ -76,9 +75,9 @@
       CustomObjectWriter(byte objectId) {
          this.id = objectId;
       }
-      
+
       public void writeObject(Marshaller marshaller, Object object) throws IOException {
          marshaller.write(id);
-      }      
+      }
    }
 }

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/DeltaAwareExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/DeltaAwareExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/DeltaAwareExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,60 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.atomic.DeltaAware;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * DeltaAwareExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class DeltaAwareExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -1635913024455984627L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      DeltaAware dw = (DeltaAware) subject;
-      output.writeObject(dw.delta());
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      return input.readObject();
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op
-   }
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/ExtendedResponseExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ExtendedResponseExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ExtendedResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,62 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.remoting.transport.jgroups.ExtendedResponse;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * ExtendedResponseExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class ExtendedResponseExternalizer implements Externalizer {
-   /** The serialVersionUID */
-   private static final long serialVersionUID = 1529506931234856884L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      ExtendedResponse er = (ExtendedResponse) subject;
-      output.writeBoolean(er.isReplayIgnoredRequests());
-      output.writeObject(er.getResponse());
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      boolean replayIgnoredRequests = input.readBoolean();
-      Object response = input.readObject();
-      return new ExtendedResponse(response, replayIgnoredRequests);
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op
-   }
-}

Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/ExternalizerClassFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ExternalizerClassFactory.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ExternalizerClassFactory.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,96 +21,133 @@
  */
 package org.infinispan.marshall.jboss;
 
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-
 import net.jcip.annotations.Immutable;
-
 import org.infinispan.CacheException;
+import org.infinispan.atomic.AtomicHashMap;
+import org.infinispan.commands.control.StateTransferControlCommand;
+import org.infinispan.commands.read.GetKeyValueCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.commands.remote.MultipleRpcCommand;
+import org.infinispan.commands.remote.SingleRpcCommand;
+import org.infinispan.commands.tx.CommitCommand;
+import org.infinispan.commands.tx.PrepareCommand;
+import org.infinispan.commands.tx.RollbackCommand;
+import org.infinispan.commands.write.ClearCommand;
+import org.infinispan.commands.write.InvalidateCommand;
+import org.infinispan.commands.write.PutKeyValueCommand;
+import org.infinispan.commands.write.PutMapCommand;
+import org.infinispan.commands.write.RemoveCommand;
+import org.infinispan.commands.write.ReplaceCommand;
+import org.infinispan.container.entries.ImmortalCacheEntry;
+import org.infinispan.container.entries.MortalCacheEntry;
+import org.infinispan.container.entries.TransientCacheEntry;
+import org.infinispan.container.entries.TransientMortalCacheEntry;
+import org.infinispan.marshall.MarshalledValue;
+import org.infinispan.marshall.jboss.externalizers.*;
 import org.infinispan.remoting.RpcManager;
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.SuccessfulResponse;
+import org.infinispan.remoting.responses.UnsuccessfulResponse;
+import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
+import org.infinispan.transaction.GlobalTransaction;
+import org.infinispan.util.FastCopyHashMap;
 import org.infinispan.util.Util;
 import org.jboss.marshalling.ClassExternalizerFactory;
 import org.jboss.marshalling.Externalizer;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
 /**
  * CustomExternalizerFactory.
- * 
+ *
  * @author Galder Zamarreño
  * @since 4.0
  */
 @Immutable
 public class ExternalizerClassFactory implements ClassExternalizerFactory {
    private static final Map<String, String> EXTERNALIZERS = new HashMap<String, String>();
-   
+
    static {
-      EXTERNALIZERS.put("org.infinispan.transaction.GlobalTransaction", "org.infinispan.marshall.jboss.GlobalTransactionExternalizer"); 
-      EXTERNALIZERS.put("org.infinispan.remoting.transport.jgroups.JGroupsAddress", "org.infinispan.marshall.jboss.JGroupsAddressExternalizer"); 
-      EXTERNALIZERS.put("java.util.ArrayList", "org.infinispan.marshall.jboss.ArrayListExternalizer");
-      EXTERNALIZERS.put("java.util.LinkedList", "org.infinispan.marshall.jboss.LinkedListExternalizer");
-      EXTERNALIZERS.put("java.util.HashMap", "org.infinispan.marshall.jboss.MapExternalizer");
-      EXTERNALIZERS.put("java.util.TreeMap", "org.infinispan.marshall.jboss.MapExternalizer");
-      EXTERNALIZERS.put("java.util.HashSet", "org.infinispan.marshall.jboss.SetExternalizer");
-      EXTERNALIZERS.put("java.util.TreeSet", "org.infinispan.marshall.jboss.SetExternalizer");
-      EXTERNALIZERS.put("org.infinispan.util.Immutables$ImmutableMapWrapper", "org.infinispan.marshall.jboss.ImmutableMapExternalizer");
-      EXTERNALIZERS.put("org.infinispan.marshall.MarshalledValue", "org.infinispan.marshall.jboss.MarshalledValueExternalizer");
-      EXTERNALIZERS.put("org.infinispan.util.FastCopyHashMap", "org.infinispan.marshall.jboss.MapExternalizer");
-      EXTERNALIZERS.put("java.util.Collections$SingletonList", "org.infinispan.marshall.jboss.SingletonListExternalizer");
-      EXTERNALIZERS.put("org.infinispan.transaction.TransactionLog$LogEntry", "org.infinispan.marshall.jboss.TransactionLogExternalizer");
-      EXTERNALIZERS.put("org.infinispan.remoting.transport.jgroups.ExtendedResponse", "org.infinispan.marshall.jboss.ExtendedResponseExternalizer");
-      EXTERNALIZERS.put("org.infinispan.atomic.AtomicHashMap", "org.infinispan.marshall.jboss.DeltaAwareExternalizer");
+      EXTERNALIZERS.put(GlobalTransaction.class.getName(), GlobalTransactionExternalizer.class.getName());
+      EXTERNALIZERS.put(JGroupsAddress.class.getName(), JGroupsAddressExternalizer.class.getName());
+      EXTERNALIZERS.put(ArrayList.class.getName(), ArrayListExternalizer.class.getName());
+      EXTERNALIZERS.put(LinkedList.class.getName(), LinkedListExternalizer.class.getName());
+      EXTERNALIZERS.put(HashMap.class.getName(), MapExternalizer.class.getName());
+      EXTERNALIZERS.put(TreeMap.class.getName(), MapExternalizer.class.getName());
+      EXTERNALIZERS.put(HashSet.class.getName(), SetExternalizer.class.getName());
+      EXTERNALIZERS.put(TreeSet.class.getName(), SetExternalizer.class.getName());
+      EXTERNALIZERS.put("org.infinispan.util.Immutables$ImmutableMapWrapper", ImmutableMapExternalizer.class.getName());
+      EXTERNALIZERS.put(MarshalledValue.class.getName(), MarshalledValueExternalizer.class.getName());
+      EXTERNALIZERS.put(FastCopyHashMap.class.getName(), MapExternalizer.class.getName());
+      EXTERNALIZERS.put("java.util.Collections$SingletonList", SingletonListExternalizer.class.getName());
+      EXTERNALIZERS.put("org.infinispan.transaction.TransactionLog$LogEntry", TransactionLogExternalizer.class.getName());
+      EXTERNALIZERS.put(ExtendedResponse.class.getName(), ExtendedResponseExternalizer.class.getName());
+      EXTERNALIZERS.put(RequestIgnoredResponse.class.getName(), RequestIgnoredResponseExternalizer.class.getName());
+      EXTERNALIZERS.put(SuccessfulResponse.class.getName(), SuccessfulResponseExternalizer.class.getName());
+      EXTERNALIZERS.put(UnsuccessfulResponse.class.getName(), UnsuccessfulResponseExternalizer.class.getName());
+      EXTERNALIZERS.put(ExceptionResponse.class.getName(), ExceptionResponseExternalizer.class.getName());
+      EXTERNALIZERS.put(AtomicHashMap.class.getName(), DeltaAwareExternalizer.class.getName());
 
-      EXTERNALIZERS.put("org.infinispan.commands.control.StateTransferControlCommand", "org.infinispan.marshall.jboss.StateTransferControlCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.remote.ClusteredGetCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.remote.MultipleRpcCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.remote.SingleRpcCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");      
-      EXTERNALIZERS.put("org.infinispan.commands.read.GetKeyValueCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.PutKeyValueCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.RemoveCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.InvalidateCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.ReplaceCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.ClearCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.write.PutMapCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.tx.PrepareCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.tx.CommitCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
-      EXTERNALIZERS.put("org.infinispan.commands.tx.RollbackCommand", "org.infinispan.marshall.jboss.ReplicableCommandExternalizer");
+      EXTERNALIZERS.put(StateTransferControlCommand.class.getName(), StateTransferControlCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(ClusteredGetCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(MultipleRpcCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(SingleRpcCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(GetKeyValueCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(PutKeyValueCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(RemoveCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(InvalidateCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(ReplaceCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(ClearCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(PutMapCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(PrepareCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(CommitCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
+      EXTERNALIZERS.put(RollbackCommand.class.getName(), ReplicableCommandExternalizer.class.getName());
 
-      EXTERNALIZERS.put("org.infinispan.container.entries.ImmortalCacheEntry", "org.infinispan.marshall.jboss.InternalCachedEntryExternalizer");
-      EXTERNALIZERS.put("org.infinispan.container.entries.MortalCacheEntry", "org.infinispan.marshall.jboss.InternalCachedEntryExternalizer");
-      EXTERNALIZERS.put("org.infinispan.container.entries.TransientCacheEntry", "org.infinispan.marshall.jboss.InternalCachedEntryExternalizer");
-      EXTERNALIZERS.put("org.infinispan.container.entries.TransientMortalCacheEntry", "org.infinispan.marshall.jboss.InternalCachedEntryExternalizer");
+      EXTERNALIZERS.put(ImmortalCacheEntry.class.getName(), InternalCachedEntryExternalizer.class.getName());
+      EXTERNALIZERS.put(MortalCacheEntry.class.getName(), InternalCachedEntryExternalizer.class.getName());
+      EXTERNALIZERS.put(TransientCacheEntry.class.getName(), InternalCachedEntryExternalizer.class.getName());
+      EXTERNALIZERS.put(TransientMortalCacheEntry.class.getName(), InternalCachedEntryExternalizer.class.getName());
    }
-   
+
    private final Map<Class<?>, Externalizer> externalizers = new WeakHashMap<Class<?>, Externalizer>();
    private final RpcManager rpcManager;
    private final CustomObjectTable objectTable;
-   
+
    public ExternalizerClassFactory(RpcManager rpcManager, CustomObjectTable objectTable) {
       this.rpcManager = rpcManager;
       this.objectTable = objectTable;
    }
-   
+
    public void init() {
-	try {
-	   for (Map.Entry<String, String> entry : EXTERNALIZERS.entrySet()) {
-		Class typeClazz = Util.loadClass(entry.getKey());
-		Externalizer ext = (Externalizer) Util.getInstance(entry.getValue());
-		if (ext instanceof StateTransferControlCommandExternalizer) {
-		   ((StateTransferControlCommandExternalizer) ext).init(rpcManager);
-		}
-		externalizers.put(typeClazz, ext);
-		objectTable.add(ext);
-	   }
-	} catch (IOException e) {
-	   throw new CacheException("Unable to open load magicnumbers.properties", e);
-	} catch (ClassNotFoundException e) {
-	   throw new CacheException("Unable to load one of the classes defined in the magicnumbers.properties", e);
-	} catch (Exception e) {
-	   throw new CacheException("Unable to instantiate Externalizer class", e);
-	}	
+      try {
+         for (Map.Entry<String, String> entry : EXTERNALIZERS.entrySet()) {
+            Class typeClazz = Util.loadClass(entry.getKey());
+            Externalizer ext = (Externalizer) Util.getInstance(entry.getValue());
+            if (ext instanceof StateTransferControlCommandExternalizer) {
+               ((StateTransferControlCommandExternalizer) ext).init(rpcManager);
+            }
+            externalizers.put(typeClazz, ext);
+            objectTable.add(ext);
+         }
+      } catch (IOException e) {
+         throw new CacheException("Unable to open load magicnumbers.properties", e);
+      } catch (ClassNotFoundException e) {
+         throw new CacheException("Unable to load one of the classes defined in the magicnumbers.properties", e);
+      } catch (Exception e) {
+         throw new CacheException("Unable to instantiate Externalizer class", e);
+      }
    }
-   
+
    public void stop() {
       externalizers.clear();
    }

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/GlobalTransactionExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/GlobalTransactionExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/GlobalTransactionExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,66 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.transaction.GlobalTransaction;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * GlobalTransactionExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class GlobalTransactionExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -8677909497367726531L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      GlobalTransaction gtx = (GlobalTransaction) subject;
-      output.writeLong(gtx.getId());
-      output.writeObject(gtx.getAddress());
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
-            throws IOException, ClassNotFoundException {
-      return new GlobalTransaction();
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      GlobalTransaction gtx = (GlobalTransaction) subject;
-      long id = input.readLong();
-      Object address = input.readObject();
-      gtx.setId(id);
-      gtx.setAddress((Address) address);
-   }
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/ImmutableMapExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ImmutableMapExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ImmutableMapExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,63 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.HashMap;
-import java.util.Map;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.util.Immutables;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * ImmutableExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class ImmutableMapExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -3592193723750924806L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      MarshallUtil.marshallMap((Map)subject, output);
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      Map map = new HashMap();
-      MarshallUtil.unmarshallMap(map, input);
-      return Immutables.immutableMapWrap(map);
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op since all the work is done in createExternal in order to be able to change identity.
-   }
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/InternalCachedEntryExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/InternalCachedEntryExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/InternalCachedEntryExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,82 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.container.entries.InternalCacheEntry;
-import org.infinispan.container.entries.InternalEntryFactory;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * InternalCachedEntryExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class InternalCachedEntryExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -3475239737916428837L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      InternalCacheEntry ice = (InternalCacheEntry) subject;
-      output.writeObject(ice.getKey());
-      output.writeObject(ice.getValue());
-      if (ice.canExpire()) {
-         output.writeBoolean(true);
-         MarshallUtil.writeUnsignedLong(output, ice.getCreated());
-         output.writeLong(ice.getLifespan()); // could be negative so should not use unsigned longs
-         MarshallUtil.writeUnsignedLong(output, ice.getLastUsed());
-         output.writeLong(ice.getMaxIdle()); // could be negative so should not use unsigned longs
-      } else {
-         output.writeBoolean(false);
-      }
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      Object k = input.readObject();
-      Object v = input.readObject();
-      boolean canExpire = input.readBoolean();
-      if (canExpire) {
-         long created = MarshallUtil.readUnsignedLong(input);
-         long lifespan = input.readLong(); // could be negative so should not use unsigned longs
-         long lastUsed = MarshallUtil.readUnsignedLong(input);
-         long maxIdle = input.readLong(); // could be negative so should not use unsigned longs
-         return InternalEntryFactory.create(k, v, created, lifespan, lastUsed, maxIdle);
-      } else {
-         return InternalEntryFactory.create(k, v);
-      }
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op
-   }
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/JGroupsAddressExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/JGroupsAddressExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/JGroupsAddressExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * JGroupsAddressExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class JGroupsAddressExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = 2400716389425727329L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      JGroupsAddress address = (JGroupsAddress) subject;
-      address.writeExternal(output);
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      return new JGroupsAddress();
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      JGroupsAddress address = (JGroupsAddress) subject;
-      address.readExternal(input);
-   }
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/LinkedListExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/LinkedListExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/LinkedListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,65 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collection;
-import java.util.LinkedList;
-
-import net.jcip.annotations.Immutable;
-
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * LinkedListExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class LinkedListExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -3222803557498456230L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      MarshallUtil.marshallCollection((Collection) subject, output);
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      int size = MarshallUtil.readUnsignedInt(input);
-      LinkedList l = new LinkedList();
-      for (int i = 0; i < size; i++) l.add(input.readObject());
-      return l;
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op since size was needed both for the creation and list population, 
-      // so work was done in createExternal 
-   }
-
-}

Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/MagicNumberClassTable.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/MagicNumberClassTable.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/MagicNumberClassTable.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,70 +21,108 @@
  */
 package org.infinispan.marshall.jboss;
 
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-
 import net.jcip.annotations.Immutable;
-
 import org.infinispan.CacheException;
+import org.infinispan.atomic.AtomicHashMap;
+import org.infinispan.commands.control.StateTransferControlCommand;
+import org.infinispan.commands.read.GetKeyValueCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.commands.remote.MultipleRpcCommand;
+import org.infinispan.commands.remote.SingleRpcCommand;
+import org.infinispan.commands.tx.CommitCommand;
+import org.infinispan.commands.tx.PrepareCommand;
+import org.infinispan.commands.tx.RollbackCommand;
+import org.infinispan.commands.write.ClearCommand;
+import org.infinispan.commands.write.InvalidateCommand;
+import org.infinispan.commands.write.PutKeyValueCommand;
+import org.infinispan.commands.write.PutMapCommand;
+import org.infinispan.commands.write.RemoveCommand;
+import org.infinispan.commands.write.ReplaceCommand;
+import org.infinispan.container.entries.ImmortalCacheEntry;
+import org.infinispan.container.entries.MortalCacheEntry;
+import org.infinispan.container.entries.TransientCacheEntry;
+import org.infinispan.container.entries.TransientMortalCacheEntry;
+import org.infinispan.marshall.MarshalledValue;
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.SuccessfulResponse;
+import org.infinispan.remoting.responses.UnsuccessfulResponse;
+import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
+import org.infinispan.transaction.GlobalTransaction;
+import org.infinispan.util.FastCopyHashMap;
 import org.infinispan.util.Util;
 import org.jboss.marshalling.ClassTable;
 import org.jboss.marshalling.Marshaller;
 import org.jboss.marshalling.Unmarshaller;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
 /**
  * MagicNumberClassTable.
- * 
+ *
  * @author Galder Zamarreño
  * @since 4.0
  */
 @Immutable
 public class MagicNumberClassTable implements ClassTable {
    private static final Map<String, Integer> MAGIC_NUMBERS = new WeakHashMap<String, Integer>();
-   
+
    static {
-      MAGIC_NUMBERS.put("org.infinispan.transaction.GlobalTransaction", 1);
-      MAGIC_NUMBERS.put("org.infinispan.remoting.transport.jgroups.JGroupsAddress", 2);
-      MAGIC_NUMBERS.put("java.util.ArrayList", 3);
-      MAGIC_NUMBERS.put("java.util.LinkedList", 8);
-      MAGIC_NUMBERS.put("java.util.HashMap", 9);
-      MAGIC_NUMBERS.put("java.util.TreeMap", 10);
-      MAGIC_NUMBERS.put("java.util.HashSet", 11);
-      MAGIC_NUMBERS.put("java.util.TreeSet", 12);
-      MAGIC_NUMBERS.put("org.infinispan.util.Immutables$ImmutableMapWrapper", 14);
-      MAGIC_NUMBERS.put("org.infinispan.marshall.MarshalledValue", 15);
-      MAGIC_NUMBERS.put("org.infinispan.util.FastCopyHashMap", 16);
-      MAGIC_NUMBERS.put("java.util.Collections$SingletonList", 23);
-      MAGIC_NUMBERS.put("org.infinispan.transaction.TransactionLog$LogEntry", 25);
-      MAGIC_NUMBERS.put("org.infinispan.remoting.transport.jgroups.ExtendedResponse", 28);
-      MAGIC_NUMBERS.put("org.infinispan.atomic.AtomicHashMap", 29);
+      MAGIC_NUMBERS.put(GlobalTransaction.class.getName(), 1);
+      MAGIC_NUMBERS.put(JGroupsAddress.class.getName(), 2);
+      MAGIC_NUMBERS.put(ArrayList.class.getName(), 3);
+      MAGIC_NUMBERS.put(LinkedList.class.getName(), 4);
+      MAGIC_NUMBERS.put(HashMap.class.getName(), 5);
+      MAGIC_NUMBERS.put(TreeMap.class.getName(), 6);
+      MAGIC_NUMBERS.put(HashSet.class.getName(), 7);
+      MAGIC_NUMBERS.put(TreeSet.class.getName(), 8);
+      MAGIC_NUMBERS.put("org.infinispan.util.Immutables$ImmutableMapWrapper", 9);
+      MAGIC_NUMBERS.put(MarshalledValue.class.getName(), 10);
+      MAGIC_NUMBERS.put(FastCopyHashMap.class.getName(), 11);
+      MAGIC_NUMBERS.put("java.util.Collections$SingletonList", 12);
+      MAGIC_NUMBERS.put("org.infinispan.transaction.TransactionLog$LogEntry", 13);
 
-      MAGIC_NUMBERS.put("org.infinispan.commands.control.StateTransferControlCommand", 30);
-      MAGIC_NUMBERS.put("org.infinispan.commands.remote.ClusteredGetCommand", 31);
-      MAGIC_NUMBERS.put("org.infinispan.commands.remote.MultipleRpcCommand", 32);
-      MAGIC_NUMBERS.put("org.infinispan.commands.remote.SingleRpcCommand", 33);
-      MAGIC_NUMBERS.put("org.infinispan.commands.read.GetKeyValueCommand", 34);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.PutKeyValueCommand", 35);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.RemoveCommand", 36);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.InvalidateCommand", 38);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.ReplaceCommand", 39);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.ClearCommand", 40);
-      MAGIC_NUMBERS.put("org.infinispan.commands.write.PutMapCommand", 41);
-      MAGIC_NUMBERS.put("org.infinispan.commands.tx.PrepareCommand", 42);
-      MAGIC_NUMBERS.put("org.infinispan.commands.tx.CommitCommand", 43);
-      MAGIC_NUMBERS.put("org.infinispan.commands.tx.RollbackCommand", 44);
+      MAGIC_NUMBERS.put(RequestIgnoredResponse.class.getName(), 14);
+      MAGIC_NUMBERS.put(ExtendedResponse.class.getName(), 15);
+      MAGIC_NUMBERS.put(ExceptionResponse.class.getName(), 16);
+      MAGIC_NUMBERS.put(SuccessfulResponse.class.getName(), 17);
+      MAGIC_NUMBERS.put(UnsuccessfulResponse.class.getName(), 18);
 
-      MAGIC_NUMBERS.put("org.infinispan.container.entries.ImmortalCacheEntry", 45);
-      MAGIC_NUMBERS.put("org.infinispan.container.entries.MortalCacheEntry", 46);
-      MAGIC_NUMBERS.put("org.infinispan.container.entries.TransientCacheEntry", 47);
-      MAGIC_NUMBERS.put("org.infinispan.container.entries.TransientMortalCacheEntry", 48);      
+
+      MAGIC_NUMBERS.put(AtomicHashMap.class.getName(), 19);
+      MAGIC_NUMBERS.put(StateTransferControlCommand.class.getName(), 20);
+      MAGIC_NUMBERS.put(ClusteredGetCommand.class.getName(), 21);
+      MAGIC_NUMBERS.put(MultipleRpcCommand.class.getName(), 22);
+      MAGIC_NUMBERS.put(SingleRpcCommand.class.getName(), 23);
+      MAGIC_NUMBERS.put(GetKeyValueCommand.class.getName(), 24);
+      MAGIC_NUMBERS.put(PutKeyValueCommand.class.getName(), 25);
+      MAGIC_NUMBERS.put(RemoveCommand.class.getName(), 26);
+      MAGIC_NUMBERS.put(InvalidateCommand.class.getName(), 27);
+      MAGIC_NUMBERS.put(ReplaceCommand.class.getName(), 28);
+      MAGIC_NUMBERS.put(ClearCommand.class.getName(), 29);
+      MAGIC_NUMBERS.put(PutMapCommand.class.getName(), 30);
+      MAGIC_NUMBERS.put(PrepareCommand.class.getName(), 31);
+      MAGIC_NUMBERS.put(CommitCommand.class.getName(), 32);
+      MAGIC_NUMBERS.put(RollbackCommand.class.getName(), 33);
+
+      MAGIC_NUMBERS.put(ImmortalCacheEntry.class.getName(), 34);
+      MAGIC_NUMBERS.put(MortalCacheEntry.class.getName(), 35);
+      MAGIC_NUMBERS.put(TransientCacheEntry.class.getName(), 36);
+      MAGIC_NUMBERS.put(TransientMortalCacheEntry.class.getName(), 37);
    }
-      
+
    private final Map<Class<?>, Writer> writers = new WeakHashMap<Class<?>, Writer>();
    private final Map<Byte, Class<?>> classes = new HashMap<Byte, Class<?>>();
-   
+
    public void init() {
       try {
          for (Map.Entry<String, Integer> entry : MAGIC_NUMBERS.entrySet()) {
@@ -92,13 +130,13 @@
             Byte magicNumber = entry.getValue().byteValue();
             Writer writer = createWriter(magicNumber);
             writers.put(clazz, writer);
-            classes.put(magicNumber, clazz);         
-         }         
+            classes.put(magicNumber, clazz);
+         }
       } catch (ClassNotFoundException e) {
          throw new CacheException("Unable to load one of the classes defined in the magicnumbers.properties", e);
       }
    }
-   
+
    public void stop() {
       writers.clear();
       classes.clear();
@@ -112,7 +150,7 @@
       byte magicNumber = unmarshaller.readByte();
       return classes.get(magicNumber);
    }
-   
+
    protected Writer createWriter(byte magicNumber) {
       return new MagicNumberWriter(magicNumber);
    }

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/MapExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/MapExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/MapExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,66 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Map;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.CacheException;
-import org.infinispan.util.Util;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * Map externalizer for all map implementations except immutable maps and singleton maps, 
- * i.e. FastCopyHashMap, HashMap, TreeMap.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class MapExternalizer implements Externalizer {
-   
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -532896252671303391L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      MarshallUtil.marshallMap((Map) subject, output);
-   }
-   
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      try {
-         return Util.getInstance(subjectType);        
-      } catch(Exception e) {
-         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
-      }
-   }
-   
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      MarshallUtil.unmarshallMap((Map) subject, input);
-   }
-}

Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshallUtil.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshallUtil.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshallUtil.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,6 +21,8 @@
  */
 package org.infinispan.marshall.jboss;
 
+import net.jcip.annotations.Immutable;
+
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
@@ -28,15 +30,14 @@
 import java.util.Map;
 import java.util.Set;
 
-import net.jcip.annotations.Immutable;
-
 /**
  * MarshallUtil.
- * 
+ *
  * @author Galder Zamarreño
  * @since 4.0
  */
 @Immutable
+ at SuppressWarnings("unchecked")
 public class MarshallUtil {
 
    /**
@@ -45,7 +46,7 @@
     *
     * @param i int to write
     */
-   protected static void writeUnsignedInt(ObjectOutput out, int i) throws IOException {
+   public static void writeUnsignedInt(ObjectOutput out, int i) throws IOException {
       while ((i & ~0x7F) != 0) {
          out.writeByte((byte) ((i & 0x7f) | 0x80));
          i >>>= 7;
@@ -57,7 +58,7 @@
     * Reads an int stored in variable-length format.  Reads between one and five bytes.  Smaller values take fewer
     * bytes.  Negative numbers are not supported.
     */
-   protected static int readUnsignedInt(ObjectInput in) throws IOException {
+   public static int readUnsignedInt(ObjectInput in) throws IOException {
       byte b = in.readByte();
       int i = b & 0x7F;
       for (int shift = 7; (b & 0x80) != 0; shift += 7) {
@@ -66,15 +67,15 @@
       }
       return i;
    }
-   
-   protected static void marshallCollection(Collection c, ObjectOutput out) throws IOException {
+
+   public static void marshallCollection(Collection c, ObjectOutput out) throws IOException {
       writeUnsignedInt(out, c.size());
       for (Object o : c) {
          out.writeObject(o);
       }
    }
-   
-   protected static void marshallMap(Map map, ObjectOutput out) throws IOException {
+
+   public static void marshallMap(Map map, ObjectOutput out) throws IOException {
       int mapSize = map.size();
       writeUnsignedInt(out, mapSize);
       if (mapSize == 0) return;
@@ -84,8 +85,8 @@
          out.writeObject(me.getValue());
       }
    }
-   
-   protected static void unmarshallMap(Map map, ObjectInput in) throws IOException, ClassNotFoundException{
+
+   public static void unmarshallMap(Map map, ObjectInput in) throws IOException, ClassNotFoundException {
       int size = MarshallUtil.readUnsignedInt(in);
       for (int i = 0; i < size; i++) map.put(in.readObject(), in.readObject());
    }
@@ -96,7 +97,7 @@
     *
     * @param i int to write
     */
-   protected static void writeUnsignedLong(ObjectOutput out, long i) throws IOException {
+   public static void writeUnsignedLong(ObjectOutput out, long i) throws IOException {
       while ((i & ~0x7F) != 0) {
          out.writeByte((byte) ((i & 0x7f) | 0x80));
          i >>>= 7;
@@ -108,7 +109,7 @@
     * Reads a long stored in variable-length format.  Reads between one and nine bytes.  Smaller values take fewer
     * bytes.  Negative numbers are not supported.
     */
-   protected static long readUnsignedLong(ObjectInput in) throws IOException {
+   public static long readUnsignedLong(ObjectInput in) throws IOException {
       byte b = in.readByte();
       long i = b & 0x7F;
       for (int shift = 7; (b & 0x80) != 0; shift += 7) {
@@ -116,5 +117,5 @@
          i |= (b & 0x7FL) << shift;
       }
       return i;
-   }   
+   }
 }

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshalledValueExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshalledValueExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshalledValueExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,60 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.marshall.MarshalledValue;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * MarshalledValueExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class MarshalledValueExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = 8473423584918714661L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      ((MarshalledValue) subject).writeExternal(output);
-   }
-   
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      return new MarshalledValue();
-   }
-   
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      ((MarshalledValue) subject).readExternal(input);
-   }
-   
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/ReplicableCommandExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ReplicableCommandExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ReplicableCommandExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,85 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.CacheException;
-import org.infinispan.commands.ReplicableCommand;
-import org.infinispan.util.Util;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * ReplicableCommandExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class ReplicableCommandExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = 6915200269446867084L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      ReplicableCommand command = (ReplicableCommand) subject;
-      output.writeShort(command.getCommandId());
-      Object[] args = command.getParameters();
-      byte numArgs = (byte) (args == null ? 0 : args.length);
-      output.writeByte(numArgs);
-      for (int i = 0; i < numArgs; i++) {
-         output.writeObject(args[i]);
-      }
-   }
-
-   /**
-    * In this case, subjectType will contain the class name of the ReplicableCommand subclass to 
-    * create. Note that StateTransferControlCommand might need to be treated differently!!! 
-    */
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      try {
-         ReplicableCommand command = (ReplicableCommand) Util.getInstance(subjectType);        
-         return command;
-      } catch(Exception e) {
-         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
-      }
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      ReplicableCommand command = (ReplicableCommand) subject;
-      short methodId = input.readShort();
-      byte numArgs = input.readByte();
-      Object[] args = null;
-      if (numArgs > 0) {
-         args = new Object[numArgs];
-         for (int i = 0; i < numArgs; i++) args[i] = input.readObject();
-      }
-      command.setParameters(methodId, args);
-   }
-}
\ No newline at end of file

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/SetExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/SetExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/SetExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,68 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collection;
-import java.util.Set;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.CacheException;
-import org.infinispan.util.Util;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * Set externalizer for all set implementations, i.e. HashSet and TreeSet
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class SetExternalizer implements Externalizer {
-   
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -3147427397000304867L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      MarshallUtil.marshallCollection((Collection) subject, output);
-   }
-   
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      try {
-         return Util.getInstance(subjectType);        
-      } catch(Exception e) {
-         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
-      }
-   }
-   
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      Set set = (Set) subject;
-      int size = MarshallUtil.readUnsignedInt(input);
-      for (int i = 0; i < size; i++) set.add(input.readObject());
-   }
-}
\ No newline at end of file

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/SingletonListExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/SingletonListExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/SingletonListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collections;
-import java.util.List;
-
-import net.jcip.annotations.Immutable;
-
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * SingletonListExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class SingletonListExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -714785461531351642L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      output.writeObject(((List) subject).get(0));
-   }
-   
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      return Collections.singletonList(input.readObject());
-   }
-   
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op since all the work is done during create.
-   }
-
-}

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/StateTransferControlCommandExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/StateTransferControlCommandExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/StateTransferControlCommandExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-
-import org.infinispan.commands.control.StateTransferControlCommand;
-import org.infinispan.remoting.RpcManager;
-import org.jboss.marshalling.Creator;
-
-/**
- * StateTransferControlCommandExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
-public class StateTransferControlCommandExternalizer extends ReplicableCommandExternalizer {
-   
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -3743458410265076691L;
-   
-   private RpcManager rpcManager;
-
-   public void init(RpcManager rpcManager) {
-      this.rpcManager = rpcManager;
-   }
-   
-   /**
-    * In this case, subjectType will contain the class name of the ReplicableCommand subclass to 
-    * create. 
-    * 
-    * Note that StateTransferControlCommand might need to be treated differently!!! 
-    * Todo: check outcome of email sent to dev list.
-    */
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      StateTransferControlCommand command = new StateTransferControlCommand();
-      command.init(rpcManager);
-      return command;
-   }
-}
\ No newline at end of file

Deleted: trunk/core/src/main/java/org/infinispan/marshall/jboss/TransactionLogExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/TransactionLogExternalizer.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/TransactionLogExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,70 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.marshall.jboss;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-import net.jcip.annotations.Immutable;
-
-import org.infinispan.commands.write.WriteCommand;
-import org.infinispan.transaction.GlobalTransaction;
-import org.infinispan.transaction.TransactionLog;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-
-/**
- * TransactionLogExternalizer.
- * 
- * @author Galder Zamarreño
- * @since 4.0
- */
- at Immutable
-public class TransactionLogExternalizer implements Externalizer {
-
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -7341096933735222157L;
-
-   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
-      TransactionLog.LogEntry le = (TransactionLog.LogEntry) subject;
-      output.writeObject(le.getTransaction());
-      WriteCommand[] cmds = le.getModifications();
-      MarshallUtil.writeUnsignedInt(output, cmds.length);
-      for (WriteCommand c : cmds)
-         output.writeObject(c);
-   }
-
-   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator) 
-            throws IOException, ClassNotFoundException {
-      GlobalTransaction gtx = (GlobalTransaction) input.readObject();
-      int numCommands = MarshallUtil.readUnsignedInt(input);
-      WriteCommand[] cmds = new WriteCommand[numCommands];
-      for (int i = 0; i < numCommands; i++) cmds[i] = (WriteCommand) input.readObject();
-      return new TransactionLog.LogEntry(gtx, cmds);
-   }
-
-   public void readExternal(Object subject, ObjectInput input) throws IOException,
-            ClassNotFoundException {
-      // No-op since the initialisation the creation and read happens during the create phase.
-   }
-}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ArrayListExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/ArrayListExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ArrayListExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ArrayListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * List externalizer dealing with ArrayList and LinkedList implementations.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class ArrayListExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = 589638638644295615L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      MarshallUtil.marshallCollection((Collection) subject, output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      int size = MarshallUtil.readUnsignedInt(input);
+      ArrayList l = new ArrayList(size);
+      for (int i = 0; i < size; i++) l.add(input.readObject());
+      return l;
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op since size was needed both for the creation and list population, 
+      // so all the work was done in createExternal 
+   }
+}
\ No newline at end of file

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/DeltaAwareExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/DeltaAwareExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/DeltaAwareExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/DeltaAwareExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.atomic.DeltaAware;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * DeltaAwareExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class DeltaAwareExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -1635913024455984627L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      DeltaAware dw = (DeltaAware) subject;
+      output.writeObject(dw.delta());
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      return input.readObject();
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op
+   }
+}

Added: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExceptionResponseExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExceptionResponseExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExceptionResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,31 @@
+package org.infinispan.marshall.jboss.externalizers;
+
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Externalizes an ExceptionResponse
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class ExceptionResponseExternalizer implements Externalizer {
+   public void writeExternal(Object o, ObjectOutput objectOutput) throws IOException {
+      ExceptionResponse er = (ExceptionResponse) o;
+      objectOutput.writeObject(er.getException());
+   }
+
+   public Object createExternal(Class<?> aClass, ObjectInput objectInput, Creator creator) throws IOException, ClassNotFoundException {
+      return new ExceptionResponse();
+   }
+
+   public void readExternal(Object o, ObjectInput objectInput) throws IOException, ClassNotFoundException {
+      ExceptionResponse er = (ExceptionResponse) o;
+      er.setException((Exception) objectInput.readObject());
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExceptionResponseExternalizer.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExtendedResponseExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/ExtendedResponseExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExtendedResponseExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ExtendedResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.Response;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * ExtendedResponseExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class ExtendedResponseExternalizer implements Externalizer {
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = 1529506931234856884L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      ExtendedResponse er = (ExtendedResponse) subject;
+      output.writeBoolean(er.isReplayIgnoredRequests());
+      output.writeObject(er.getResponse());
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      boolean replayIgnoredRequests = input.readBoolean();
+      Response response = (Response) input.readObject();
+      return new ExtendedResponse(response, replayIgnoredRequests);
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/GlobalTransactionExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/GlobalTransactionExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/GlobalTransactionExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/GlobalTransactionExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.transaction.GlobalTransaction;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * GlobalTransactionExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class GlobalTransactionExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -8677909497367726531L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      GlobalTransaction gtx = (GlobalTransaction) subject;
+      output.writeLong(gtx.getId());
+      output.writeObject(gtx.getAddress());
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      return new GlobalTransaction();
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      GlobalTransaction gtx = (GlobalTransaction) subject;
+      long id = input.readLong();
+      Object address = input.readObject();
+      gtx.setId(id);
+      gtx.setAddress((Address) address);
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ImmutableMapExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/ImmutableMapExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ImmutableMapExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ImmutableMapExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.infinispan.util.Immutables;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ImmutableExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class ImmutableMapExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -3592193723750924806L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      MarshallUtil.marshallMap((Map) subject, output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      Map map = new HashMap();
+      MarshallUtil.unmarshallMap(map, input);
+      return Immutables.immutableMapWrap(map);
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op since all the work is done in createExternal in order to be able to change identity.
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/InternalCachedEntryExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/InternalCachedEntryExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/InternalCachedEntryExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/InternalCachedEntryExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.container.entries.InternalEntryFactory;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * InternalCachedEntryExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class InternalCachedEntryExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -3475239737916428837L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      InternalCacheEntry ice = (InternalCacheEntry) subject;
+      output.writeObject(ice.getKey());
+      output.writeObject(ice.getValue());
+      if (ice.canExpire()) {
+         output.writeBoolean(true);
+         MarshallUtil.writeUnsignedLong(output, ice.getCreated());
+         output.writeLong(ice.getLifespan()); // could be negative so should not use unsigned longs
+         MarshallUtil.writeUnsignedLong(output, ice.getLastUsed());
+         output.writeLong(ice.getMaxIdle()); // could be negative so should not use unsigned longs
+      } else {
+         output.writeBoolean(false);
+      }
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      Object k = input.readObject();
+      Object v = input.readObject();
+      boolean canExpire = input.readBoolean();
+      if (canExpire) {
+         long created = MarshallUtil.readUnsignedLong(input);
+         long lifespan = input.readLong(); // could be negative so should not use unsigned longs
+         long lastUsed = MarshallUtil.readUnsignedLong(input);
+         long maxIdle = input.readLong(); // could be negative so should not use unsigned longs
+         return InternalEntryFactory.create(k, v, created, lifespan, lastUsed, maxIdle);
+      } else {
+         return InternalEntryFactory.create(k, v);
+      }
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/JGroupsAddressExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/JGroupsAddressExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/JGroupsAddressExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/JGroupsAddressExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * JGroupsAddressExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class JGroupsAddressExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = 2400716389425727329L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      JGroupsAddress address = (JGroupsAddress) subject;
+      address.writeExternal(output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      return new JGroupsAddress();
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      JGroupsAddress address = (JGroupsAddress) subject;
+      address.readExternal(input);
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/LinkedListExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/LinkedListExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/LinkedListExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/LinkedListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * LinkedListExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class LinkedListExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -3222803557498456230L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      MarshallUtil.marshallCollection((Collection) subject, output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      int size = MarshallUtil.readUnsignedInt(input);
+      LinkedList l = new LinkedList();
+      for (int i = 0; i < size; i++) l.add(input.readObject());
+      return l;
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op since size was needed both for the creation and list population, 
+      // so work was done in createExternal 
+   }
+
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MapExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/MapExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MapExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MapExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.CacheException;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.infinispan.util.Util;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+
+/**
+ * Map externalizer for all map implementations except immutable maps and singleton maps, i.e. FastCopyHashMap, HashMap,
+ * TreeMap.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class MapExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -532896252671303391L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      MarshallUtil.marshallMap((Map) subject, output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      try {
+         return Util.getInstance(subjectType);
+      } catch (Exception e) {
+         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
+      }
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      MarshallUtil.unmarshallMap((Map) subject, input);
+   }
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MarshalledValueExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/MarshalledValueExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MarshalledValueExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/MarshalledValueExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.marshall.MarshalledValue;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * MarshalledValueExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class MarshalledValueExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = 8473423584918714661L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      ((MarshalledValue) subject).writeExternal(output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      return new MarshalledValue();
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      ((MarshalledValue) subject).readExternal(input);
+   }
+
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ReplicableCommandExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/ReplicableCommandExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ReplicableCommandExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/ReplicableCommandExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.CacheException;
+import org.infinispan.commands.ReplicableCommand;
+import org.infinispan.util.Util;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * ReplicableCommandExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class ReplicableCommandExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = 6915200269446867084L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      ReplicableCommand command = (ReplicableCommand) subject;
+      output.writeShort(command.getCommandId());
+      Object[] args = command.getParameters();
+      byte numArgs = (byte) (args == null ? 0 : args.length);
+      output.writeByte(numArgs);
+      for (int i = 0; i < numArgs; i++) {
+         output.writeObject(args[i]);
+      }
+   }
+
+   /**
+    * In this case, subjectType will contain the class name of the ReplicableCommand subclass to create. Note that
+    * StateTransferControlCommand might need to be treated differently!!!
+    */
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      try {
+         ReplicableCommand command = (ReplicableCommand) Util.getInstance(subjectType);
+         return command;
+      } catch (Exception e) {
+         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
+      }
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      ReplicableCommand command = (ReplicableCommand) subject;
+      short methodId = input.readShort();
+      byte numArgs = input.readByte();
+      Object[] args = null;
+      if (numArgs > 0) {
+         args = new Object[numArgs];
+         for (int i = 0; i < numArgs; i++) args[i] = input.readObject();
+      }
+      command.setParameters(methodId, args);
+   }
+}
\ No newline at end of file

Added: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/RequestIgnoredResponseExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/RequestIgnoredResponseExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/RequestIgnoredResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,27 @@
+package org.infinispan.marshall.jboss.externalizers;
+
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Externalizes RequestIgnoredResponses
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class RequestIgnoredResponseExternalizer implements Externalizer {
+   public void writeExternal(Object o, ObjectOutput objectOutput) throws IOException {
+   }
+
+   public Object createExternal(Class<?> aClass, ObjectInput objectInput, Creator creator) throws IOException, ClassNotFoundException {
+      return RequestIgnoredResponse.INSTANCE;
+   }
+
+   public void readExternal(Object o, ObjectInput objectInput) throws IOException, ClassNotFoundException {
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/RequestIgnoredResponseExternalizer.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SetExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/SetExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SetExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SetExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.CacheException;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.infinispan.util.Util;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Set externalizer for all set implementations, i.e. HashSet and TreeSet
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class SetExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -3147427397000304867L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      MarshallUtil.marshallCollection((Collection) subject, output);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      try {
+         return Util.getInstance(subjectType);
+      } catch (Exception e) {
+         throw new CacheException("Unable to create new instance of ReplicableCommand", e);
+      }
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      Set set = (Set) subject;
+      int size = MarshallUtil.readUnsignedInt(input);
+      for (int i = 0; i < size; i++) set.add(input.readObject());
+   }
+}
\ No newline at end of file

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SingletonListExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/SingletonListExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SingletonListExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SingletonListExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * SingletonListExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class SingletonListExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -714785461531351642L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      output.writeObject(((List) subject).get(0));
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      return Collections.singletonList(input.readObject());
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op since all the work is done during create.
+   }
+
+}

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/StateTransferControlCommandExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/StateTransferControlCommandExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/StateTransferControlCommandExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/StateTransferControlCommandExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import org.infinispan.commands.control.StateTransferControlCommand;
+import org.infinispan.remoting.RpcManager;
+import org.jboss.marshalling.Creator;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+
+/**
+ * StateTransferControlCommandExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+public class StateTransferControlCommandExternalizer extends ReplicableCommandExternalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -3743458410265076691L;
+
+   private RpcManager rpcManager;
+
+   public void init(RpcManager rpcManager) {
+      this.rpcManager = rpcManager;
+   }
+
+   /**
+    * In this case, subjectType will contain the class name of the ReplicableCommand subclass to create.
+    * <p/>
+    * Note that StateTransferControlCommand might need to be treated differently!!! Todo: check outcome of email sent to
+    * dev list.
+    */
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      StateTransferControlCommand command = new StateTransferControlCommand();
+      command.init(rpcManager);
+      return command;
+   }
+}
\ No newline at end of file

Added: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SuccessfulResponseExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SuccessfulResponseExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SuccessfulResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,31 @@
+package org.infinispan.marshall.jboss.externalizers;
+
+import org.infinispan.remoting.responses.SuccessfulResponse;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Externalizes a SuccessfulResponse
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class SuccessfulResponseExternalizer implements Externalizer {
+   public void writeExternal(Object o, ObjectOutput objectOutput) throws IOException {
+      SuccessfulResponse sr = (SuccessfulResponse) o;
+      objectOutput.writeObject(sr.getResponseValue());
+   }
+
+   public Object createExternal(Class<?> aClass, ObjectInput objectInput, Creator creator) throws IOException, ClassNotFoundException {
+      return new SuccessfulResponse();
+   }
+
+   public void readExternal(Object o, ObjectInput objectInput) throws IOException, ClassNotFoundException {
+      SuccessfulResponse sr = (SuccessfulResponse) o;
+      sr.setResponseValue(objectInput.readObject());
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/SuccessfulResponseExternalizer.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/TransactionLogExternalizer.java (from rev 142, trunk/core/src/main/java/org/infinispan/marshall/jboss/TransactionLogExternalizer.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/TransactionLogExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/TransactionLogExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.marshall.jboss.externalizers;
+
+import net.jcip.annotations.Immutable;
+import org.infinispan.commands.write.WriteCommand;
+import org.infinispan.marshall.jboss.MarshallUtil;
+import org.infinispan.transaction.GlobalTransaction;
+import org.infinispan.transaction.TransactionLog;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * TransactionLogExternalizer.
+ *
+ * @author Galder Zamarreño
+ * @since 4.0
+ */
+ at Immutable
+public class TransactionLogExternalizer implements Externalizer {
+
+   /**
+    * The serialVersionUID
+    */
+   private static final long serialVersionUID = -7341096933735222157L;
+
+   public void writeExternal(Object subject, ObjectOutput output) throws IOException {
+      TransactionLog.LogEntry le = (TransactionLog.LogEntry) subject;
+      output.writeObject(le.getTransaction());
+      WriteCommand[] cmds = le.getModifications();
+      MarshallUtil.writeUnsignedInt(output, cmds.length);
+      for (WriteCommand c : cmds)
+         output.writeObject(c);
+   }
+
+   public Object createExternal(Class<?> subjectType, ObjectInput input, Creator defaultCreator)
+         throws IOException, ClassNotFoundException {
+      GlobalTransaction gtx = (GlobalTransaction) input.readObject();
+      int numCommands = MarshallUtil.readUnsignedInt(input);
+      WriteCommand[] cmds = new WriteCommand[numCommands];
+      for (int i = 0; i < numCommands; i++) cmds[i] = (WriteCommand) input.readObject();
+      return new TransactionLog.LogEntry(gtx, cmds);
+   }
+
+   public void readExternal(Object subject, ObjectInput input) throws IOException,
+                                                                      ClassNotFoundException {
+      // No-op since the initialisation the creation and read happens during the create phase.
+   }
+}

Added: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/UnsuccessfulResponseExternalizer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/UnsuccessfulResponseExternalizer.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/UnsuccessfulResponseExternalizer.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,27 @@
+package org.infinispan.marshall.jboss.externalizers;
+
+import org.infinispan.remoting.responses.UnsuccessfulResponse;
+import org.jboss.marshalling.Creator;
+import org.jboss.marshalling.Externalizer;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Externalizes an UnsuccessfulResponse
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class UnsuccessfulResponseExternalizer implements Externalizer {
+   public void writeExternal(Object o, ObjectOutput objectOutput) throws IOException {
+   }
+
+   public Object createExternal(Class<?> aClass, ObjectInput objectInput, Creator creator) throws IOException, ClassNotFoundException {
+      return UnsuccessfulResponse.INSTANCE;
+   }
+
+   public void readExternal(Object o, ObjectInput objectInput) throws IOException, ClassNotFoundException {
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/marshall/jboss/externalizers/UnsuccessfulResponseExternalizer.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandler.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandler.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandler.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -3,6 +3,7 @@
 import org.infinispan.commands.remote.CacheRpcCommand;
 import org.infinispan.factories.scopes.Scope;
 import org.infinispan.factories.scopes.Scopes;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.statetransfer.StateTransferException;
 
 import java.io.InputStream;
@@ -10,8 +11,8 @@
 
 /**
  * A globally scoped component, that is able to locate named caches and invoke remotely originating calls on the
- * appropriate cache.  The primary goal of this component is to act as a bridge between the globally scoped {@link RpcManager}
- * and named-cache scoped components.
+ * appropriate cache.  The primary goal of this component is to act as a bridge between the globally scoped {@link
+ * RpcManager} and named-cache scoped components.
  *
  * @author Manik Surtani
  * @since 4.0
@@ -26,24 +27,24 @@
     * @return results, if any, from the invocation
     * @throws Throwable in the event of problems executing the command
     */
-   Object handle(CacheRpcCommand command) throws Throwable;
+   Response handle(CacheRpcCommand command) throws Throwable;
 
    /**
     * Applies state onto a named cache.  State to be read from the stream.  Implementations should NOT close the stream
     * after use.
     *
     * @param cacheName name of cache to apply state
-    * @param i stream to read from
+    * @param i         stream to read from
     * @throws StateTransferException in the event of problems
     */
    void applyState(String cacheName, InputStream i) throws StateTransferException;
 
    /**
-    * Generates state from a named cache.  State to be written to the stream.  Implementations should NOT close the stream
-    * after use.
+    * Generates state from a named cache.  State to be written to the stream.  Implementations should NOT close the
+    * stream after use.
     *
     * @param cacheName name of cache from which to generate state
-    * @param o stream to write state to
+    * @param o         stream to write state to
     * @throws StateTransferException in the event of problems
     */
    void generateState(String cacheName, OutputStream o) throws StateTransferException;

Modified: trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,7 +1,7 @@
 package org.infinispan.remoting;
 
+import org.infinispan.commands.CommandsFactory;
 import org.infinispan.commands.remote.CacheRpcCommand;
-import org.infinispan.commands.CommandsFactory;
 import org.infinispan.config.Configuration;
 import org.infinispan.factories.ComponentRegistry;
 import org.infinispan.factories.GlobalComponentRegistry;
@@ -12,6 +12,10 @@
 import org.infinispan.invocation.InvocationContextContainer;
 import org.infinispan.logging.Log;
 import org.infinispan.logging.LogFactory;
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.Response;
+import org.infinispan.remoting.responses.ResponseGenerator;
 import org.infinispan.statetransfer.StateTransferException;
 import org.infinispan.statetransfer.StateTransferManager;
 
@@ -35,7 +39,7 @@
       this.gcr = gcr;
    }
 
-   public Object handle(CacheRpcCommand cmd) throws Throwable {
+   public Response handle(CacheRpcCommand cmd) throws Throwable {
       String cacheName = cmd.getCacheName();
       ComponentRegistry cr = gcr.getNamedComponentRegistry(cacheName);
       if (cr == null) {
@@ -48,8 +52,10 @@
       if (!cr.getStatus().allowInvocations()) {
          long giveupTime = System.currentTimeMillis() + localConfig.getStateRetrievalTimeout();
          while (cr.getStatus().startingUp() && System.currentTimeMillis() < giveupTime) Thread.sleep(100);
-         if (!cr.getStatus().allowInvocations())
-            throw new IllegalStateException("Cache named " + cacheName + " exists but isn't in a state to handle invocations.  Its state is " + cr.getStatus());
+         if (!cr.getStatus().allowInvocations()) {
+            log.warn("Cache named [{0}] exists but isn't in a state to handle invocations.  Its state is {1}.", cacheName, cr.getStatus());
+            return RequestIgnoredResponse.INSTANCE;
+         }
       }
 
       InvocationContextContainer icc = cr.getLocalComponent(InvocationContextContainer.class);
@@ -57,7 +63,13 @@
 
       // initialize this command with components specific to the intended cache instance
       commandsFactory.initializeReplicableCommand(cmd);
-      return cmd.perform(icc.get());
+
+      try {
+         Object retval = cmd.perform(icc.get());
+         return cr.getComponent(ResponseGenerator.class).getResponse(cmd, retval);
+      } catch (Exception e) {
+         return new ExceptionResponse(e);
+      }
    }
 
    public void applyState(String cacheName, InputStream i) throws StateTransferException {

Modified: trunk/core/src/main/java/org/infinispan/remoting/ResponseFilter.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/ResponseFilter.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/ResponseFilter.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,10 +1,11 @@
 package org.infinispan.remoting;
 
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.Address;
 
 /**
- * A mechanism of filtering RPC responses.  Used with {@link RpcManager#invokeRemotely(java.util.List,
- * org.infinispan.commands.ReplicableCommand, ResponseMode, long, boolean, ResponseFilter)}
+ * A mechanism of filtering RPC responses.  Used with {@link org.infinispan.remoting.RpcManager#invokeRemotely(java.util.List,
+ * org.infinispan.commands.ReplicableCommand, ResponseMode, long, boolean, ResponseFilter, boolean)}
  *
  * @author Manik Surtani
  * @since 4.0
@@ -18,11 +19,11 @@
     * @return True if we should add the response to the response list of a request, otherwise false. In the latter case,
     *         we don't add the response to the response list.
     */
-   boolean isAcceptable(Object response, Address sender);
+   boolean isAcceptable(Response response, Address sender);
 
    /**
-    * Right after calling {@link #isAcceptable(Object, Address)}, this method is called to see whether we are done with
-    * the request and can unblock the caller
+    * Right after calling {@link #isAcceptable(Response, Address)}, this method is called to see whether we are done
+    * with the request and can unblock the caller
     *
     * @return False if the request is done, otherwise true
     */

Modified: trunk/core/src/main/java/org/infinispan/remoting/RpcManager.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/RpcManager.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/RpcManager.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -26,6 +26,7 @@
 import org.infinispan.factories.scopes.Scope;
 import org.infinispan.factories.scopes.Scopes;
 import org.infinispan.lifecycle.Lifecycle;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.Address;
 import org.infinispan.remoting.transport.Transport;
 import org.infinispan.statetransfer.StateTransferException;
@@ -62,7 +63,7 @@
     * @return a list of responses from each member contacted.
     * @throws Exception in the event of problems.
     */
-   List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean stateTransferEnabled) throws Exception;
+   List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean stateTransferEnabled) throws Exception;
 
    /**
     * Invokes an RPC call on other caches in the cluster.
@@ -79,7 +80,7 @@
     * @return a list of responses from each member contacted.
     * @throws Exception in the event of problems.
     */
-   List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, boolean stateTransferEnabled) throws Exception;
+   List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, boolean stateTransferEnabled) throws Exception;
 
    /**
     * Invokes an RPC call on other caches in the cluster.
@@ -94,7 +95,7 @@
     * @return a list of responses from each member contacted.
     * @throws Exception in the event of problems.
     */
-   List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean stateTransferEnabled) throws Exception;
+   List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean stateTransferEnabled) throws Exception;
 
    /**
     * Initiates a state retrieval process from neighbouring caches.  This method will block until it either times out,

Modified: trunk/core/src/main/java/org/infinispan/remoting/RpcManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/RpcManagerImpl.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/RpcManagerImpl.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -15,6 +15,7 @@
 import org.infinispan.logging.LogFactory;
 import org.infinispan.marshall.Marshaller;
 import org.infinispan.notifications.cachemanagerlistener.CacheManagerNotifier;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.Address;
 import org.infinispan.remoting.transport.Transport;
 import org.infinispan.statetransfer.StateTransferException;
@@ -26,8 +27,9 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
- * This component really is just a wrapper around a {@link org.infinispan.remoting.transport.Transport} implementation, and
- * is used to set up the transport and provide lifecycle and dependency hooks into external transport implementations.
+ * This component really is just a wrapper around a {@link org.infinispan.remoting.transport.Transport} implementation,
+ * and is used to set up the transport and provide lifecycle and dependency hooks into external transport
+ * implementations.
  *
  * @author Manik Surtani
  * @since 4.0
@@ -62,9 +64,9 @@
       t.stop();
    }
 
-   public List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean stateTransferEnabled) throws Exception {
+   public List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean stateTransferEnabled) throws Exception {
       try {
-         List<Object> result = t.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter, stateTransferEnabled);
+         List<Response> result = t.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter, stateTransferEnabled);
          if (isStatisticsEnabled()) replicationCount.incrementAndGet();
          return result;
       } catch (Throwable e) {
@@ -73,11 +75,11 @@
       }
    }
 
-   public List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, boolean stateTransferEnabled) throws Exception {
+   public List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, boolean stateTransferEnabled) throws Exception {
       return invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, null, stateTransferEnabled);
    }
 
-   public List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean stateTransferEnabled) throws Exception {
+   public List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean stateTransferEnabled) throws Exception {
       return invokeRemotely(recipients, rpcCommand, mode, timeout, false, null, stateTransferEnabled);
    }
 

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/DefaultResponseGenerator.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/DefaultResponseGenerator.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/DefaultResponseGenerator.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,19 @@
+package org.infinispan.remoting.responses;
+
+import org.infinispan.commands.remote.CacheRpcCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+
+/**
+ * The default response generator for most cache modes
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class DefaultResponseGenerator implements ResponseGenerator {
+   public Response getResponse(CacheRpcCommand command, Object returnValue) {
+      if (returnValue != null && command instanceof ClusteredGetCommand)
+         return new SuccessfulResponse(returnValue);
+      else
+         return null; // saves on serializing a response!
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/DefaultResponseGenerator.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/DistributionResponseGenerator.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/DistributionResponseGenerator.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/DistributionResponseGenerator.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,37 @@
+package org.infinispan.remoting.responses;
+
+import org.infinispan.commands.ReplicableCommand;
+import org.infinispan.commands.remote.CacheRpcCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.commands.remote.SingleRpcCommand;
+import org.infinispan.commands.write.WriteCommand;
+
+/**
+ * A response generator for the DIST cache mode
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class DistributionResponseGenerator implements ResponseGenerator {
+   public Response getResponse(CacheRpcCommand command, Object returnValue) {
+      if (command instanceof ClusteredGetCommand) {
+         return returnValue == null ? null : new SuccessfulResponse(returnValue);
+      } else if (command instanceof SingleRpcCommand) {
+         SingleRpcCommand src = (SingleRpcCommand) command;
+         ReplicableCommand c = src.getCommand();
+
+         if (c instanceof WriteCommand) {
+            // check if this is successful.
+            if (((WriteCommand) c).isSuccessful())
+               return new SuccessfulResponse(returnValue);
+            else
+               return UnsuccessfulResponse.INSTANCE;
+         }
+      }
+
+      if (returnValue == null)
+         return UnsuccessfulResponse.INSTANCE;
+      else
+         return new SuccessfulResponse(returnValue);
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/DistributionResponseGenerator.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/ExceptionResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/ExceptionResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/ExceptionResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,26 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * A response that encapsulates an exception
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class ExceptionResponse extends InvalidResponse {
+   private Exception exception;
+
+   public ExceptionResponse() {
+   }
+
+   public ExceptionResponse(Exception exception) {
+      this.exception = exception;
+   }
+
+   public Exception getException() {
+      return exception;
+   }
+
+   public void setException(Exception exception) {
+      this.exception = exception;
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/ExceptionResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/remoting/responses/ExtendedResponse.java (from rev 134, trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/ExtendedResponse.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/ExtendedResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/ExtendedResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,49 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.infinispan.remoting.responses;
+
+/**
+ * A response with extended information
+ *
+ * @author Jason T. Greene
+ */
+public class ExtendedResponse extends ValidResponse {
+   private final boolean replayIgnoredRequests;
+   private final Response response;
+
+   public ExtendedResponse(Response response, boolean replayIgnoredRequests) {
+      this.response = response;
+      this.replayIgnoredRequests = replayIgnoredRequests;
+   }
+
+   public boolean isReplayIgnoredRequests() {
+      return replayIgnoredRequests;
+   }
+
+   public Response getResponse() {
+      return response;
+   }
+
+   public boolean isSuccessful() {
+      return response.isSuccessful();
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/ExtendedResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/InvalidResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/InvalidResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/InvalidResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,17 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * An invalid response
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public abstract class InvalidResponse implements Response {
+   public boolean isValid() {
+      return false;
+   }
+
+   public boolean isSuccessful() {
+      return false;
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/InvalidResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Copied: trunk/core/src/main/java/org/infinispan/remoting/responses/RequestIgnoredResponse.java (from rev 134, trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/RequestIgnoredResponse.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/RequestIgnoredResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/RequestIgnoredResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,39 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.infinispan.remoting.responses;
+
+/**
+ * Indicates that the request was ignored,
+ *
+ * @author Jason T. Greene
+ */
+public class RequestIgnoredResponse extends InvalidResponse {
+   public static final RequestIgnoredResponse INSTANCE = new RequestIgnoredResponse();
+
+   private RequestIgnoredResponse() {
+   }
+
+   @Override
+   public String toString() {
+      return "RequestIgnoredResponse";
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/RequestIgnoredResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/Response.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/Response.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/Response.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,14 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * A response to be sent back to a remote caller
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public interface Response {
+
+   boolean isSuccessful();
+
+   boolean isValid();
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/Response.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/ResponseGenerator.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/ResponseGenerator.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/ResponseGenerator.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,16 @@
+package org.infinispan.remoting.responses;
+
+import org.infinispan.commands.remote.CacheRpcCommand;
+import org.infinispan.factories.scopes.Scope;
+import org.infinispan.factories.scopes.Scopes;
+
+/**
+ * A component that generates responses as is expected by different cache setups
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+ at Scope(Scopes.NAMED_CACHE)
+public interface ResponseGenerator {
+   Response getResponse(CacheRpcCommand command, Object returnValue);
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/ResponseGenerator.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/SuccessfulResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/SuccessfulResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/SuccessfulResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,48 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * A successful response
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class SuccessfulResponse extends ValidResponse {
+
+   private Object responseValue;
+
+   public SuccessfulResponse() {
+   }
+
+   public SuccessfulResponse(Object responseValue) {
+      this.responseValue = responseValue;
+   }
+
+   public boolean isSuccessful() {
+      return true;
+   }
+
+   public Object getResponseValue() {
+      return responseValue;
+   }
+
+   public void setResponseValue(Object responseValue) {
+      this.responseValue = responseValue;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      SuccessfulResponse that = (SuccessfulResponse) o;
+
+      if (responseValue != null ? !responseValue.equals(that.responseValue) : that.responseValue != null) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      return responseValue != null ? responseValue.hashCode() : 0;
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/SuccessfulResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/UnsuccessfulResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/UnsuccessfulResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/UnsuccessfulResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,28 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * An unsuccessful response
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class UnsuccessfulResponse extends ValidResponse {
+   public static final UnsuccessfulResponse INSTANCE = new UnsuccessfulResponse();
+
+   private UnsuccessfulResponse() {
+   }
+
+   public boolean isSuccessful() {
+      return false;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      return o.getClass().equals(UnsuccessfulResponse.class);
+   }
+
+   @Override
+   public int hashCode() {
+      return 13;
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/UnsuccessfulResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/main/java/org/infinispan/remoting/responses/ValidResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/responses/ValidResponse.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/remoting/responses/ValidResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,14 @@
+package org.infinispan.remoting.responses;
+
+/**
+ * A valid response
+ *
+ * @author manik
+ * @since 4.0
+ */
+public abstract class ValidResponse implements Response {
+
+   public boolean isValid() {
+      return true;
+   }
+}


Property changes on: trunk/core/src/main/java/org/infinispan/remoting/responses/ValidResponse.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/core/src/main/java/org/infinispan/remoting/transport/Transport.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/Transport.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/Transport.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -11,6 +11,7 @@
 import org.infinispan.remoting.InboundInvocationHandler;
 import org.infinispan.remoting.ResponseFilter;
 import org.infinispan.remoting.ResponseMode;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.statetransfer.StateTransferException;
 
 import java.util.List;
@@ -58,7 +59,7 @@
     * @return a list of responses from each member contacted.
     * @throws Exception in the event of problems.
     */
-   List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean supportReplay) throws Exception;
+   List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter, boolean supportReplay) throws Exception;
 
    /**
     * @return true if the current Channel is the coordinator of the cluster.
@@ -106,6 +107,7 @@
 
    /**
     * Tests whether the transport supports state transfer
+    *
     * @return true if the implementation supports state transfer, false otherwise.
     */
    boolean isSupportStateTransfer();

Modified: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/CommandAwareRpcDispatcher.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/CommandAwareRpcDispatcher.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/CommandAwareRpcDispatcher.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -22,12 +22,14 @@
 package org.infinispan.remoting.transport.jgroups;
 
 import org.infinispan.CacheException;
-import org.infinispan.commands.remote.CacheRpcCommand;
 import org.infinispan.commands.ReplicableCommand;
-import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.commands.remote.CacheRpcCommand;
 import org.infinispan.logging.Log;
 import org.infinispan.logging.LogFactory;
 import org.infinispan.remoting.InboundInvocationHandler;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.DistributedSync;
 import org.jgroups.Address;
 import org.jgroups.Channel;
@@ -144,7 +146,7 @@
       }
    }
 
-   protected Object executeCommand(CacheRpcCommand cmd, Message req) throws Throwable {
+   protected Response executeCommand(CacheRpcCommand cmd, Message req) throws Throwable {
       if (cmd == null) throw new NullPointerException("Unable to execute a null command!  Message was " + req);
       if (trace) log.trace("Attempting to execute command: {0} [sender={1}]", cmd, req.getSrc());
 
@@ -159,27 +161,18 @@
          boolean replayIgnored = sr == DistributedSync.SyncResponse.STATE_ACHIEVED;
          if (trace) log.trace("Enough waiting; replayIgnored = {0}, sr {1}", replayIgnored, sr);
 
-         Object retval;
-         try {
-            retval = inboundInvocationHandler.handle(cmd);
-         } catch (IllegalStateException ise) {
-            newCacheStarting.set(true);
-            if (trace) log.trace("Unable to execute command, cache not in a receptive state: " + ise.getMessage());
-            // cache not in a started state, request replay
-            return RequestIgnoredResponse.INSTANCE;
-         }
+         Response resp = inboundInvocationHandler.handle(cmd);
 
-         if (replayIgnored) {
-            return new ExtendedResponse(retval, true);
+         // A null response is valid and OK ...
+         if (resp == null || resp.isValid()) {
+            if (replayIgnored) resp = new ExtendedResponse(resp, true);
          } else {
-
-            // Do we really need a response?!?  The caller would only ever expect a response for certain types of
-            // commands, such as a ClusteredGet
-            if (cmd instanceof ClusteredGetCommand)
-               return retval;
-            else
-               return null; // saves on serializing a response!
+            // invalid response
+            newCacheStarting.set(true);
+            if (trace) log.trace("Unable to execute command, got invalid response");
          }
+
+         return resp;
       } finally {
          if (unlock) distributedSync.releaseProcessingLock();
       }

Deleted: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/ExtendedResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/ExtendedResponse.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/ExtendedResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,45 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.infinispan.remoting.transport.jgroups;
-
-/**
- * A response with extended information
- *
- * @author Jason T. Greene
- */
-public class ExtendedResponse {
-   private final boolean replayIgnoredRequests;
-   private final Object response;
-
-   public ExtendedResponse(Object response, boolean replayIgnoredRequests) {
-      this.response = response;
-      this.replayIgnoredRequests = replayIgnoredRequests;
-   }
-
-   public boolean isReplayIgnoredRequests() {
-      return replayIgnoredRequests;
-   }
-
-   public Object getResponse() {
-      return response;
-   }
-}

Modified: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsResponseFilterAdapter.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsResponseFilterAdapter.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsResponseFilterAdapter.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,6 +1,7 @@
 package org.infinispan.remoting.transport.jgroups;
 
 import org.infinispan.remoting.ResponseFilter;
+import org.infinispan.remoting.responses.Response;
 import org.jgroups.Address;
 import org.jgroups.blocks.RspFilter;
 
@@ -24,7 +25,7 @@
    }
 
    public boolean isAcceptable(Object response, Address sender) {
-      return r.isAcceptable(response, new JGroupsAddress(sender));
+      return r.isAcceptable((Response) response, new JGroupsAddress(sender));
    }
 
    public boolean needMoreResponses() {

Modified: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsTransport.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsTransport.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/JGroupsTransport.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -13,6 +13,8 @@
 import org.infinispan.remoting.ReplicationException;
 import org.infinispan.remoting.ResponseFilter;
 import org.infinispan.remoting.ResponseMode;
+import org.infinispan.remoting.responses.ExceptionResponse;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.Address;
 import org.infinispan.remoting.transport.DistributedSync;
 import org.infinispan.remoting.transport.Transport;
@@ -254,7 +256,7 @@
          log.warn("Channel not set up properly!");
          return false;
       }
-      
+
       return true;
    }
 
@@ -269,8 +271,8 @@
    // outbound RPC
    // ------------------------------------------------------------------------------------------------------------------
 
-   public List<Object> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout,
-                                      boolean usePriorityQueue, ResponseFilter responseFilter, boolean supportReplay)
+   public List<Response> invokeRemotely(List<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout,
+                                        boolean usePriorityQueue, ResponseFilter responseFilter, boolean supportReplay)
          throws Exception {
 
       if (recipients != null && recipients.isEmpty()) {
@@ -300,25 +302,28 @@
 
          // short-circuit no-return-value calls.
          if (rsps == null) return Collections.emptyList();
-         List<Object> retval = new ArrayList<Object>(rsps.size());
+         List<Response> retval = new ArrayList<Response>(rsps.size());
 
          for (Rsp rsp : rsps.values()) {
             if (rsp.wasSuspected() || !rsp.wasReceived()) {
-               CacheException ex;
                if (rsp.wasSuspected()) {
-                  ex = new SuspectException("Suspected member: " + rsp.getSender());
+                  throw new SuspectException("Suspected member: " + rsp.getSender());
                } else {
-                  ex = new TimeoutException("Replication timeout for " + rsp.getSender());
+                  throw new TimeoutException("Replication timeout for " + rsp.getSender());
                }
-               retval.add(new ReplicationException("rsp=" + rsp, ex));
             } else {
-               Object value = rsp.getValue();
-               if (value instanceof Exception && !(value instanceof ReplicationException)) {
-                  // if we have any application-level exceptions make sure we throw them!!
-                  if (trace) log.trace("Recieved exception'" + value + "' from " + rsp.getSender());
-                  throw (Exception) value;
+               if (rsp.getValue() != null) {
+                  Response value = (Response) rsp.getValue();
+                  if (value instanceof ExceptionResponse) {
+                     Exception e = ((ExceptionResponse) value).getException();
+                     if (!(e instanceof ReplicationException)) {
+                        // if we have any application-level exceptions make sure we throw them!!
+                        if (trace) log.trace("Recieved exception '{0}' from {1}", e, rsp.getSender());
+                        throw e;
+                     }
+                  }
+                  retval.add(value);
                }
-               retval.add(value);
             }
          }
          return retval;

Deleted: trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/RequestIgnoredResponse.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/RequestIgnoredResponse.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/main/java/org/infinispan/remoting/transport/jgroups/RequestIgnoredResponse.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,39 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.infinispan.remoting.transport.jgroups;
-
-/**
- * Indicates that the request was ignored,
- *
- * @author Jason T. Greene
- */
-public class RequestIgnoredResponse {
-   public static final RequestIgnoredResponse INSTANCE = new RequestIgnoredResponse();
-
-   private RequestIgnoredResponse() {
-   }
-
-   @Override
-   public String toString() {
-      return "RequestIgnoredResponse";
-   }
-}

Modified: trunk/core/src/test/java/org/infinispan/atomic/ClusteredAPITest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/atomic/ClusteredAPITest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/atomic/ClusteredAPITest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,7 +21,7 @@
       c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
       c.setInvocationBatchingEnabled(true);
 
-      List<Cache> caches = createClusteredCaches(2, "atomic", c);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "atomic", c);
       cache1 = (AtomicMapCache) caches.get(0);
       cache2 = (AtomicMapCache) caches.get(1);
    }

Added: trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,178 @@
+package org.infinispan.distribution;
+
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import static org.infinispan.config.Configuration.CacheMode.DIST_ASYNC;
+import static org.infinispan.config.Configuration.CacheMode.DIST_SYNC;
+import org.infinispan.container.DataContainer;
+import org.infinispan.container.entries.ImmortalCacheEntry;
+import org.infinispan.container.entries.InternalCacheEntry;
+import org.infinispan.container.entries.MortalCacheEntry;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.DummyTransactionManagerLookup;
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+ at Test(groups = "functional", testName = "distribution.BaseDistFunctionalTest")
+public abstract class BaseDistFunctionalTest extends MultipleCacheManagersTest {
+   protected Cache<Object, String> c1, c2, c3, c4;
+   protected List<Cache<Object, String>> caches;
+   protected boolean sync = true;
+   protected boolean tx = false;
+
+   protected void createCacheManagers() throws Throwable {
+      Configuration c = getDefaultClusteredConfig(sync ? DIST_SYNC : DIST_ASYNC);
+      if (tx) c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+      caches = createClusteredCaches(4, "dist", c);
+      c1 = caches.get(0);
+      c2 = caches.get(0);
+      c3 = caches.get(0);
+      c4 = caches.get(0);
+   }
+
+   // ----------------- HELPERS ----------------
+
+   protected void initAndTest() {
+      for (Cache<Object, String> c : caches) assert c.isEmpty();
+
+      c1.put("k1", "value");
+      asyncWait();
+      for (Cache<Object, String> c : caches) assert c.get("k1").equals("value");
+      assertOwnershipAndNonOwnership("k1");
+   }
+
+   protected Cache<Object, String> getFirstNonOwner(String key) {
+      return getNonOwners(key).get(0);
+   }
+
+   protected void assertOnAllCachesAndOwnership(Object key, String value) {
+      for (Cache<Object, String> c : caches) {
+         if (value == null)
+            assert c.get(key) == null;
+         else
+            assert value.equals(c.get(key));
+      }
+      assertOwnershipAndNonOwnership("k1");
+   }
+
+   protected void assertOwnershipAndNonOwnership(Object key) {
+      for (Cache<Object, String> c : caches) {
+         DataContainer dc = c.getAdvancedCache().getDataContainer();
+         if (isOwner(c, key)) {
+            assert dc.get(key) instanceof ImmortalCacheEntry : "Fail on cache " + c.getCacheManager().getAddress() + ": dc.get(" + key + ") returned " + dc.get(key);
+         } else {
+            if (dc.containsKey(key)) {
+               assert dc.get(key) instanceof MortalCacheEntry : "Fail on cache " + c.getCacheManager().getAddress() + ": dc.get(" + key + ") returned " + dc.get(key);
+               assert dc.get(key).getLifespan() == c1.getConfiguration().getL1Lifespan();
+            }
+         }
+      }
+   }
+
+   protected void assertIsInL1(Cache<?, ?> cache, Object key) {
+      DataContainer dc = cache.getAdvancedCache().getDataContainer();
+      InternalCacheEntry ice = dc.get(key);
+      assert ice != null : "Entry for key [" + key + "] should be in data container on cache at [" + cache.getCacheManager().getAddress() + "]!";
+      assert !(ice instanceof ImmortalCacheEntry) : "Entry for key [" + key + "] should have a lifespan on cache at [" + cache.getCacheManager().getAddress() + "]!";
+   }
+
+   protected void assertIsNotInL1(Cache<?, ?> cache, Object key) {
+      DataContainer dc = cache.getAdvancedCache().getDataContainer();
+      InternalCacheEntry ice = dc.get(key);
+      assert ice == null : "Entry for key [" + key + "] should not be in data container on cache at [" + cache.getCacheManager().getAddress() + "]!";
+   }
+
+   protected void assertIsInContainerImmortal(Cache<?, ?> cache, Object key) {
+      DataContainer dc = cache.getAdvancedCache().getDataContainer();
+      InternalCacheEntry ice = dc.get(key);
+      assert ice != null : "Entry for key [" + key + "] should be in data container on cache at [" + cache.getCacheManager().getAddress() + "]!";
+      assert ice instanceof ImmortalCacheEntry : "Entry for key [" + key + "] on cache at [" + cache.getCacheManager().getAddress() + "] should be immortal but was [" + ice + "]!";
+   }
+
+   protected static boolean isOwner(Cache<?, ?> c, Object key) {
+      DistributionManager dm = c.getAdvancedCache().getComponentRegistry().getComponent(DistributionManager.class);
+      List<Address> ownerAddresses = dm.locate(key);
+      for (Address a : ownerAddresses) {
+         if (c.getCacheManager().getAddress().equals(a)) return true;
+      }
+      return false;
+   }
+
+   protected List<Cache<Object, String>> getOwners(Object key) {
+      List<Cache<Object, String>> owners = new ArrayList<Cache<Object, String>>();
+      for (Cache<Object, String> c : caches) {
+         if (isOwner(c, key)) owners.add(c);
+      }
+      return owners;
+   }
+
+   protected List<Cache<Object, String>> getNonOwners(Object key) {
+      List<Cache<Object, String>> nonOwners = new ArrayList<Cache<Object, String>>();
+      for (Cache<Object, String> c : caches) {
+         if (!isOwner(c, key)) nonOwners.add(c);
+      }
+      return nonOwners;
+   }
+
+   protected List<Address> residentAddresses(Object key) {
+      DistributionManager dm = c1.getAdvancedCache().getComponentRegistry().getComponent(DistributionManager.class);
+      return dm.locate(key);
+   }
+
+   protected void asyncWait() {
+      // no op.
+   }
+
+   protected TransactionManager getTransactionManager(Cache<?, ?> cache) {
+      return TestingUtil.getTransactionManager(cache);
+   }
+
+   /**
+    * A special type of key that if passed a cache in its constructor, will ensure it will always be assigned to that
+    * cache (plus however many additional caches in the hash space)
+    */
+   protected static class MagicKey implements Serializable {
+      int hashcode;
+      String address;
+
+      public MagicKey(Cache<?, ?> toMapTo) {
+         address = toMapTo.getCacheManager().getAddress().toString();
+         // generate a hashcode that will always map it to the specified cache.
+         for (int i = 0; i < DefaultConsistentHash.HASH_SPACE; i += 100) {
+            // create a dummy object with this hashcode
+            final int hc = i;
+            Object dummy = new Object() {
+               @Override
+               public int hashCode() {
+                  return hc;
+               }
+            };
+
+            if (BaseDistFunctionalTest.isOwner(toMapTo, dummy)) {
+               // we have found a hashcode that works!
+               hashcode = hc;
+               break;
+            }
+         }
+      }
+
+      @Override
+      public int hashCode() {
+         return hashcode;
+      }
+
+      @Override
+      public String toString() {
+         return "MagicKey{" +
+               "hashcode=" + hashcode +
+               ", address='" + address + '\'' +
+               '}';
+      }
+   }
+}


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/BaseDistFunctionalTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,110 @@
+package org.infinispan.distribution;
+
+import org.infinispan.remoting.transport.Address;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+ at Test(groups = "unit", testName = "distribution.DefaultConsistentHashTest", enabled = false)
+public class DefaultConsistentHashTest {
+
+   List<Address> servers;
+   ConsistentHash ch;
+
+   @BeforeTest
+   public void setUp() {
+      servers = new LinkedList<Address>();
+      int numServers = 5;
+      for (int i = 0; i < numServers; i++) {
+         servers.add(new TestAddress(i));
+      }
+
+      ch = new DefaultConsistentHash();
+      ch.setCaches(servers);
+   }
+
+   @AfterTest
+   public void tearDown() {
+      servers = null;
+      ch = null;
+   }
+
+   public void testSimpleHashing() {
+      Object o = new Object();
+      List<Address> l1 = ch.locate(o, 2);
+      List<Address> l2 = ch.locate(o, 2);
+
+      assert l1.size() == 2;
+      assert l1.equals(l2);
+      assert l1 != l2;
+
+      Object o2 = new Object() {
+         @Override
+         public int hashCode() {
+            return 4567890;
+         }
+      };
+
+      Object o3 = new Object() {
+         @Override
+         public int hashCode() {
+            return 4567890;
+         }
+      };
+
+      assert o2 != o3;
+      assert !o2.equals(o3);
+      assert ch.locate(o2, 4).equals(ch.locate(o3, 4));
+   }
+
+   public void testMultipleKeys() {
+      Object k1 = "key1", k2 = "key2", k3 = "key3";
+      Collection<Object> keys = Arrays.asList(k1, k2, k3);
+      Map<Object, List<Address>> locations = ch.locateAll(keys, 3);
+
+      assert locations.size() == 3;
+      for (Object k : keys) {
+         assert locations.containsKey(k);
+         assert locations.get(k).size() == 3;
+      }
+   }
+}
+
+class TestAddress implements Address {
+   int addressNum;
+
+   TestAddress(int addressNum) {
+      this.addressNum = addressNum;
+   }
+
+   public int getAddressNum() {
+      return addressNum;
+   }
+
+   public void setAddressNum(int addressNum) {
+      this.addressNum = addressNum;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      TestAddress that = (TestAddress) o;
+
+      if (addressNum != that.addressNum) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      return addressNum;
+   }
+}


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/DefaultConsistentHashTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/test/java/org/infinispan/distribution/DistAsyncFuncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistAsyncFuncTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistAsyncFuncTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,24 @@
+package org.infinispan.distribution;
+
+import org.testng.annotations.Test;
+
+ at Test(groups = "functional", testName = "distribution.DistAsyncFuncTest", enabled = false)
+public class DistAsyncFuncTest extends DistSyncFuncTest {
+
+   public DistAsyncFuncTest() {
+      sync = false;
+      tx = false;
+   }
+
+   @Override
+   protected void asyncWait() {
+      // we need to wait for an async event to happen on *each* cache?
+      // TODO figure this out properly!
+      try {
+         Thread.sleep(2000);
+      } catch (InterruptedException e) {
+         e.printStackTrace();  // TODO: Customise this generated block
+      }
+   }
+
+}
\ No newline at end of file


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/DistAsyncFuncTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/test/java/org/infinispan/distribution/DistAsyncTxFuncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistAsyncTxFuncTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistAsyncTxFuncTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,24 @@
+package org.infinispan.distribution;
+
+import org.testng.annotations.Test;
+
+ at Test(groups = "functional", testName = "distribution.DistAsyncTxFuncTest", enabled = false)
+public class DistAsyncTxFuncTest extends DistSyncTxFuncTest {
+
+   public DistAsyncTxFuncTest() {
+      sync = false;
+      tx = true;
+      cleanup = CleanupPhase.AFTER_METHOD; // ensure any stale TXs are wiped
+   }
+
+   @Override
+   protected void asyncWait() {
+      // we need to wait for an async event to happen on *each* cache?
+      // TODO figure this out properly!
+      try {
+         Thread.sleep(2000);
+      } catch (InterruptedException e) {
+         e.printStackTrace();  // TODO: Customise this generated block
+      }
+   }
+}
\ No newline at end of file


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/DistAsyncTxFuncTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/test/java/org/infinispan/distribution/DistSyncFuncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistSyncFuncTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistSyncFuncTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,147 @@
+package org.infinispan.distribution;
+
+import org.infinispan.Cache;
+import org.testng.annotations.Test;
+
+ at Test(groups = "functional", testName = "distribution.DistSyncFuncTest", enabled = false)
+public class DistSyncFuncTest extends BaseDistFunctionalTest {
+
+   public DistSyncFuncTest() {
+      sync = true;
+      tx = false;
+   }
+
+   public void testBasicDistribution() {
+      for (Cache<Object, String> c : caches) assert c.isEmpty();
+
+      c1.put("k1", "value");
+
+      asyncWait();
+
+      for (Cache<Object, String> c : caches) {
+         if (isOwner(c, "k1")) {
+            assertIsInContainerImmortal(c, "k1");
+         } else {
+            assertIsNotInL1(c, "k1");
+         }
+      }
+
+      // should be available everywhere!
+      assertOnAllCachesAndOwnership("k1", "value");
+
+      // and should now be in L1
+
+      for (Cache<Object, String> c : caches) {
+         if (isOwner(c, "k1")) {
+            assertIsInContainerImmortal(c, "k1");
+         } else {
+            assertIsInL1(c, "k1");
+         }
+      }
+   }
+
+   public void testPutFromNonOwner() {
+      initAndTest();
+      Object retval = getFirstNonOwner("k1").put("k1", "value2");
+      asyncWait();
+      if (sync) assert "value".equals(retval);
+      assertOnAllCachesAndOwnership("k1", "value2");
+   }
+
+   public void testPutIfAbsentFromNonOwner() {
+      initAndTest();
+      Object retval = getFirstNonOwner("k1").putIfAbsent("k1", "value2");
+      asyncWait();
+      if (sync) assert "value".equals(retval);
+
+      assertOnAllCachesAndOwnership("k1", "value");
+
+      c1.clear();
+      asyncWait();
+
+      retval = getFirstNonOwner("k1").putIfAbsent("k1", "value2");
+      asyncWait();
+      if (sync) assert null == retval;
+
+      assertOnAllCachesAndOwnership("k1", "value2");
+   }
+
+   public void testRemoveFromNonOwner() {
+      initAndTest();
+      Object retval = getFirstNonOwner("k1").remove("k1");
+      asyncWait();
+      if (sync) assert "value".equals(retval);
+
+      assertOnAllCachesAndOwnership("k1", null);
+   }
+
+   public void testConditionalRemoveFromNonOwner() {
+      initAndTest();
+      boolean retval = getFirstNonOwner("k1").remove("k1", "value2");
+      asyncWait();
+      if (sync) assert !retval : "Should not have removed entry";
+
+      assertOnAllCachesAndOwnership("k1", "value");
+
+      retval = getFirstNonOwner("k1").remove("k1", "value");
+      asyncWait();
+      if (sync) assert retval : "Should have removed entry";
+
+      assertOnAllCachesAndOwnership("k1", null);
+   }
+
+   public void testReplaceFromNonOwner() {
+      initAndTest();
+      Object retval = getFirstNonOwner("k1").replace("k1", "value2");
+      asyncWait();
+      if (sync) assert "value".equals(retval);
+
+      assertOnAllCachesAndOwnership("k1", "value2");
+
+      c1.clear();
+      asyncWait();
+
+      retval = getFirstNonOwner("k1").replace("k1", "value2");
+      asyncWait();
+      if (sync) assert retval == null;
+
+      assertOnAllCachesAndOwnership("k1", null);
+   }
+
+   public void testConditionalReplaceFromNonOwner() {
+      initAndTest();
+      boolean retval = getFirstNonOwner("k1").replace("k1", "valueX", "value2");
+      asyncWait();
+      if (sync) assert !retval : "Should not have replaced";
+
+      assertOnAllCachesAndOwnership("k1", "value");
+
+      c1.clear();
+      asyncWait();
+
+      retval = getFirstNonOwner("k1").replace("k1", "value", "value2");
+      asyncWait();
+      if (sync) assert retval : "Should have replaced";
+
+      assertOnAllCachesAndOwnership("k1", "value2");
+   }
+
+   public void testClear() {
+      for (Cache<Object, String> c : caches) assert c.isEmpty();
+
+      for (int i = 0; i < 10; i++) {
+         c1.put("k" + i, "value" + i);
+         asyncWait();
+      }
+
+      // this will fill up L1 as well
+      for (int i = 0; i < 10; i++) assertOnAllCachesAndOwnership("k" + i, "value" + i);
+
+      for (Cache<Object, String> c : caches) assert !c.isEmpty();
+
+      c1.clear();
+      asyncWait();
+
+      for (Cache<Object, String> c : caches) assert c.isEmpty();
+   }
+}


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/DistSyncFuncTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -0,0 +1,104 @@
+package org.infinispan.distribution;
+
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+
+ at Test(groups = "functional", testName = "distribution.DistSyncTxFuncTest", enabled = false)
+public class DistSyncTxFuncTest extends BaseDistFunctionalTest {
+   public DistSyncTxFuncTest() {
+      sync = true;
+      tx = true;
+      cleanup = CleanupPhase.AFTER_METHOD; // ensure any stale TXs are wiped
+   }
+
+   private void init(MagicKey k1, MagicKey k2) {
+      // neither key maps on to c4
+      c2.put(k1, "value1");
+      c2.put(k2, "value2");
+
+      assertIsInContainerImmortal(c1, k1);
+      assertIsInContainerImmortal(c2, k1);
+      assertIsInContainerImmortal(c2, k2);
+      assertIsInContainerImmortal(c3, k2);
+
+      assertIsNotInL1(c4, k1);
+      assertIsNotInL1(c4, k2);
+      assertIsNotInL1(c1, k2);
+      assertIsNotInL1(c3, k1);
+   }
+
+   public void testTransactionsSpanningKeysCommit() throws Exception {
+      // we need 2 keys that reside on different caches...
+      MagicKey k1 = new MagicKey(c1); // maps on to c1 and c2
+      MagicKey k2 = new MagicKey(c2); // maps on to c2 and c3
+
+      init(k1, k2);
+
+      // now test a transaction that spans both keys.
+      TransactionManager tm4 = getTransactionManager(c4);
+      tm4.begin();
+      c4.put(k1, "new_value1");
+      c4.put(k2, "new_value2");
+      tm4.commit();
+
+      asyncWait();
+
+      assertIsInContainerImmortal(c1, k1);
+      assertIsInContainerImmortal(c2, k1);
+      assertIsInContainerImmortal(c2, k2);
+      assertIsInContainerImmortal(c3, k2);
+
+      assertIsInL1(c4, k1);
+      assertIsInL1(c4, k2);
+      assertIsNotInL1(c1, k2);
+      assertIsNotInL1(c3, k1);
+
+      assertOnAllCachesAndOwnership(k1, "new_value1");
+      assertOnAllCachesAndOwnership(k2, "new_value2");
+
+      assertIsInL1(c4, k1);
+      assertIsInL1(c4, k2);
+      assertIsInL1(c1, k2);
+      assertIsInL1(c3, k1);
+   }
+
+   public void testTransactionsSpanningKeysRollback() throws Exception {
+      // we need 2 keys that reside on different caches...
+      MagicKey k1 = new MagicKey(c1); // maps on to c1 and c2
+      MagicKey k2 = new MagicKey(c2); // maps on to c2 and c3
+
+      init(k1, k2);
+
+      // now test a transaction that spans both keys.
+      TransactionManager tm4 = getTransactionManager(c4);
+      tm4.begin();
+      c4.put(k1, "new_value1");
+      c4.put(k2, "new_value2");
+      tm4.rollback();
+
+      asyncWait();
+
+      assertIsInContainerImmortal(c1, k1);
+      assertIsInContainerImmortal(c2, k1);
+      assertIsInContainerImmortal(c2, k2);
+      assertIsInContainerImmortal(c3, k2);
+
+      assertIsNotInL1(c4, k1);
+      assertIsNotInL1(c4, k2);
+      assertIsNotInL1(c1, k2);
+      assertIsNotInL1(c3, k1);
+
+      assertOnAllCachesAndOwnership(k1, "value1");
+      assertOnAllCachesAndOwnership(k2, "value2");
+
+      assertIsInL1(c4, k1);
+      assertIsInL1(c4, k2);
+      assertIsInL1(c1, k2);
+      assertIsInL1(c3, k1);
+   }
+
+   public void testReturnValuesInTx() throws Exception {
+      // TODO
+   }
+}


Property changes on: trunk/core/src/test/java/org/infinispan/distribution/DistSyncTxFuncTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/core/src/test/java/org/infinispan/expiry/ReplicatedExpiryTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/expiry/ReplicatedExpiryTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/expiry/ReplicatedExpiryTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,11 +1,11 @@
 package org.infinispan.expiry;
 
 import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
 import org.infinispan.container.entries.InternalCacheEntry;
-import org.infinispan.container.entries.TransientMortalCacheEntry;
 import org.infinispan.container.entries.MortalCacheEntry;
 import org.infinispan.container.entries.TransientCacheEntry;
-import org.infinispan.config.Configuration;
+import org.infinispan.container.entries.TransientMortalCacheEntry;
 import org.infinispan.test.MultipleCacheManagersTest;
 import org.testng.annotations.Test;
 
@@ -19,7 +19,7 @@
 
    protected void createCacheManagers() throws Throwable {
       Configuration cfg = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC);
-      List<Cache> caches = createClusteredCaches(2, "cache", cfg);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "cache", cfg);
       c1 = caches.get(0);
       c2 = caches.get(1);
    }

Modified: trunk/core/src/test/java/org/infinispan/invalidation/BaseInvalidationTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/invalidation/BaseInvalidationTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/invalidation/BaseInvalidationTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -8,10 +8,10 @@
 import org.infinispan.commands.write.InvalidateCommand;
 import org.infinispan.config.Configuration;
 import org.infinispan.invocation.Flag;
+import org.infinispan.remoting.ResponseFilter;
+import org.infinispan.remoting.ResponseMode;
 import org.infinispan.remoting.RpcManager;
 import org.infinispan.remoting.RpcManagerImpl;
-import org.infinispan.remoting.ResponseFilter;
-import org.infinispan.remoting.ResponseMode;
 import org.infinispan.remoting.transport.Address;
 import org.infinispan.remoting.transport.Transport;
 import org.infinispan.test.MultipleCacheManagersTest;
@@ -35,7 +35,7 @@
       Configuration c = getDefaultClusteredConfig(isSync ? Configuration.CacheMode.INVALIDATION_SYNC : Configuration.CacheMode.INVALIDATION_ASYNC);
       c.setStateRetrievalTimeout(1000);
       c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
-      List<Cache> caches = createClusteredCaches(2, "invalidation", c);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "invalidation", c);
       cache1 = caches.get(0).getAdvancedCache();
       cache2 = caches.get(1).getAdvancedCache();
    }

Modified: trunk/core/src/test/java/org/infinispan/marshall/jboss/JBossMarshallerTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/marshall/jboss/JBossMarshallerTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/marshall/jboss/JBossMarshallerTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -21,18 +21,6 @@
  */
 package org.infinispan.marshall.jboss;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
 import org.infinispan.commands.ReplicableCommand;
 import org.infinispan.commands.control.StateTransferControlCommand;
 import org.infinispan.commands.read.GetKeyValueCommand;
@@ -53,10 +41,11 @@
 import org.infinispan.container.entries.TransientCacheEntry;
 import org.infinispan.container.entries.TransientMortalCacheEntry;
 import org.infinispan.marshall.MarshalledValue;
+import org.infinispan.remoting.responses.ExtendedResponse;
+import org.infinispan.remoting.responses.RequestIgnoredResponse;
+import org.infinispan.remoting.responses.SuccessfulResponse;
 import org.infinispan.remoting.transport.Address;
-import org.infinispan.remoting.transport.jgroups.ExtendedResponse;
 import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
-import org.infinispan.remoting.transport.jgroups.RequestIgnoredResponse;
 import org.infinispan.transaction.GlobalTransaction;
 import org.infinispan.transaction.TransactionLog;
 import org.infinispan.util.FastCopyHashMap;
@@ -66,11 +55,13 @@
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
+import java.util.*;
+
 /**
  * JBossMarshallingMarshallerTest.
- * 
+ * <p/>
  * Todo: AtomicHashMap missing.
- * 
+ *
  * @author Galder Zamarreño
  * @since 4.0
  */
@@ -78,27 +69,27 @@
 public class JBossMarshallerTest {
 
    private final JBossMarshaller marshaller = new JBossMarshaller();
-   
+
    @BeforeTest
    public void setUp() {
       marshaller.init(Thread.currentThread().getContextClassLoader(), null);
    }
-   
+
    @AfterTest
    public void tearDown() {
       marshaller.stop();
    }
-   
+
    public void testJGroupsAddressMarshalling() throws Exception {
       JGroupsAddress address = new JGroupsAddress(new IpAddress(12345));
       marshallAndAssertEquality(address);
    }
-   
+
    public void testGlobalTransactionMarshalling() throws Exception {
       GlobalTransaction gtx = GlobalTransaction.create(new JGroupsAddress(new IpAddress(12345)));
       marshallAndAssertEquality(gtx);
    }
-   
+
    public void testListMarshalling() throws Exception {
       List l1 = new ArrayList();
       List l2 = new LinkedList();
@@ -110,7 +101,7 @@
       marshallAndAssertEquality(l1);
       marshallAndAssertEquality(l2);
    }
-   
+
    public void testMapMarshalling() throws Exception {
       Map m1 = new HashMap();
       Map m2 = new TreeMap();
@@ -127,13 +118,13 @@
       marshallAndAssertEquality(m2);
       byte[] bytes = marshaller.objectToByteBuffer(m4);
       Map<Integer, GlobalTransaction> m4Read = (Map<Integer, GlobalTransaction>) marshaller.objectFromByteBuffer(bytes);
-      for (Map.Entry<Integer, GlobalTransaction> entry : m4.entrySet()) {      
-         assert m4Read.get(entry.getKey()).equals(entry.getValue()) : "Writen[" + entry.getValue() + "] and read[" +  m4Read.get(entry.getKey()) +"] objects should be the same";
+      for (Map.Entry<Integer, GlobalTransaction> entry : m4.entrySet()) {
+         assert m4Read.get(entry.getKey()).equals(entry.getValue()) : "Writen[" + entry.getValue() + "] and read[" + m4Read.get(entry.getKey()) + "] objects should be the same";
       }
-      
+
       marshallAndAssertEquality(m5);
    }
-   
+
    public void testSetMarshalling() throws Exception {
       Set s1 = new HashSet();
       Set s2 = new TreeSet();
@@ -145,7 +136,7 @@
       marshallAndAssertEquality(s1);
       marshallAndAssertEquality(s2);
    }
-   
+
    public void testMarshalledValueMarshalling() throws Exception {
       GlobalTransaction gtx = GlobalTransaction.create(new JGroupsAddress(new IpAddress(12345)));
       MarshalledValue mv = new MarshalledValue(gtx, true);
@@ -157,74 +148,74 @@
       List l = Collections.singletonList(gtx);
       marshallAndAssertEquality(l);
    }
-   
+
    public void testTransactionLogMarshalling() throws Exception {
       GlobalTransaction gtx = GlobalTransaction.create(new JGroupsAddress(new IpAddress(12345)));
       PutKeyValueCommand command = new PutKeyValueCommand("k", "v", false, null, 0, 0);
       TransactionLog.LogEntry entry = new TransactionLog.LogEntry(gtx, command);
       byte[] bytes = marshaller.objectToByteBuffer(entry);
       TransactionLog.LogEntry readObj = (TransactionLog.LogEntry) marshaller.objectFromByteBuffer(bytes);
-      assert Arrays.equals(readObj.getModifications(), entry.getModifications()) : 
-         "Writen[" + entry.getModifications() + "] and read[" +  readObj.getModifications() +"] objects should be the same";
-      assert readObj.getTransaction().equals(entry.getTransaction()) : 
-         "Writen[" + entry.getModifications() + "] and read[" +  readObj.getModifications() +"] objects should be the same";
+      assert Arrays.equals(readObj.getModifications(), entry.getModifications()) :
+            "Writen[" + entry.getModifications() + "] and read[" + readObj.getModifications() + "] objects should be the same";
+      assert readObj.getTransaction().equals(entry.getTransaction()) :
+            "Writen[" + entry.getModifications() + "] and read[" + readObj.getModifications() + "] objects should be the same";
    }
-   
+
    public void testRequestIgnoredResponseMarshalling() throws Exception {
       marshallAndAssertEquality(RequestIgnoredResponse.INSTANCE);
    }
-   
+
    public void testExtendedResponseMarshalling() throws Exception {
-      PutKeyValueCommand command = new PutKeyValueCommand("k", "v", false, null, 0, 0);
-      ExtendedResponse extended = new ExtendedResponse(command, false);
+      SuccessfulResponse sr = new SuccessfulResponse("Blah");
+      ExtendedResponse extended = new ExtendedResponse(sr, false);
       byte[] bytes = marshaller.objectToByteBuffer(extended);
       ExtendedResponse readObj = (ExtendedResponse) marshaller.objectFromByteBuffer(bytes);
       assert extended.getResponse().equals(readObj.getResponse()) :
-         "Writen[" + extended.getResponse() + "] and read[" +  readObj.getResponse() +"] objects should be the same";
+            "Writen[" + extended.getResponse() + "] and read[" + readObj.getResponse() + "] objects should be the same";
       assert extended.isReplayIgnoredRequests() == readObj.isReplayIgnoredRequests() :
-         "Writen[" + extended.isReplayIgnoredRequests() + "] and read[" +  readObj.isReplayIgnoredRequests() +"] objects should be the same";
+            "Writen[" + extended.isReplayIgnoredRequests() + "] and read[" + readObj.isReplayIgnoredRequests() + "] objects should be the same";
    }
-   
+
    public void testReplicableCommandsMarshalling() throws Exception {
       StateTransferControlCommand c1 = new StateTransferControlCommand(true);
       byte[] bytes = marshaller.objectToByteBuffer(c1);
-      StateTransferControlCommand rc1 = (StateTransferControlCommand)marshaller.objectFromByteBuffer(bytes);
-      assert rc1.getCommandId() == c1.getCommandId() : "Writen[" + c1.getCommandId() + "] and read[" +  rc1.getCommandId() +"] objects should be the same";
-      assert Arrays.equals(rc1.getParameters(), c1.getParameters()) : "Writen[" + c1.getParameters() + "] and read[" +  rc1.getParameters() +"] objects should be the same";
-      
+      StateTransferControlCommand rc1 = (StateTransferControlCommand) marshaller.objectFromByteBuffer(bytes);
+      assert rc1.getCommandId() == c1.getCommandId() : "Writen[" + c1.getCommandId() + "] and read[" + rc1.getCommandId() + "] objects should be the same";
+      assert Arrays.equals(rc1.getParameters(), c1.getParameters()) : "Writen[" + c1.getParameters() + "] and read[" + rc1.getParameters() + "] objects should be the same";
+
       ClusteredGetCommand c2 = new ClusteredGetCommand("key", "mycache");
       marshallAndAssertEquality(c2);
-      
+
       // SizeCommand does not have an empty constructor, so doesn't look to be one that is marshallable.      
-      
+
       GetKeyValueCommand c4 = new GetKeyValueCommand("key", null);
       bytes = marshaller.objectToByteBuffer(c4);
-      GetKeyValueCommand rc4 = (GetKeyValueCommand)marshaller.objectFromByteBuffer(bytes);
-      assert rc4.getCommandId() == c4.getCommandId() : "Writen[" + c4.getCommandId() + "] and read[" +  rc4.getCommandId() +"] objects should be the same";
-      assert Arrays.equals(rc4.getParameters(), c4.getParameters()) : "Writen[" + c4.getParameters() + "] and read[" +  rc4.getParameters() +"] objects should be the same";
-      
+      GetKeyValueCommand rc4 = (GetKeyValueCommand) marshaller.objectFromByteBuffer(bytes);
+      assert rc4.getCommandId() == c4.getCommandId() : "Writen[" + c4.getCommandId() + "] and read[" + rc4.getCommandId() + "] objects should be the same";
+      assert Arrays.equals(rc4.getParameters(), c4.getParameters()) : "Writen[" + c4.getParameters() + "] and read[" + rc4.getParameters() + "] objects should be the same";
+
       PutKeyValueCommand c5 = new PutKeyValueCommand("k", "v", false, null, 0, 0);
       marshallAndAssertEquality(c5);
-      
+
       RemoveCommand c6 = new RemoveCommand("key", null, null);
       marshallAndAssertEquality(c6);
-      
+
       // EvictCommand does not have an empty constructor, so doesn't look to be one that is marshallable.
-      
+
       InvalidateCommand c7 = new InvalidateCommand(null, "key1", "key2");
       bytes = marshaller.objectToByteBuffer(c7);
-      InvalidateCommand rc7 = (InvalidateCommand)marshaller.objectFromByteBuffer(bytes);
-      assert rc7.getCommandId() == c7.getCommandId() : "Writen[" + c7.getCommandId() + "] and read[" +  rc7.getCommandId() +"] objects should be the same";
-      assert Arrays.equals(rc7.getParameters(), c7.getParameters()) : "Writen[" + c7.getParameters() + "] and read[" +  rc7.getParameters() +"] objects should be the same";
-      
+      InvalidateCommand rc7 = (InvalidateCommand) marshaller.objectFromByteBuffer(bytes);
+      assert rc7.getCommandId() == c7.getCommandId() : "Writen[" + c7.getCommandId() + "] and read[" + rc7.getCommandId() + "] objects should be the same";
+      assert Arrays.equals(rc7.getParameters(), c7.getParameters()) : "Writen[" + c7.getParameters() + "] and read[" + rc7.getParameters() + "] objects should be the same";
+
       ReplaceCommand c8 = new ReplaceCommand("key", "oldvalue", "newvalue", 0, 0);
       marshallAndAssertEquality(c8);
-      
+
       ClearCommand c9 = new ClearCommand();
       bytes = marshaller.objectToByteBuffer(c9);
-      ClearCommand rc9 = (ClearCommand)marshaller.objectFromByteBuffer(bytes);
-      assert rc9.getCommandId() == c9.getCommandId() : "Writen[" + c9.getCommandId() + "] and read[" +  rc9.getCommandId() +"] objects should be the same";
-      assert Arrays.equals(rc9.getParameters(), c9.getParameters()) : "Writen[" + c9.getParameters() + "] and read[" +  rc9.getParameters() +"] objects should be the same";
+      ClearCommand rc9 = (ClearCommand) marshaller.objectFromByteBuffer(bytes);
+      assert rc9.getCommandId() == c9.getCommandId() : "Writen[" + c9.getCommandId() + "] and read[" + rc9.getCommandId() + "] objects should be the same";
+      assert Arrays.equals(rc9.getParameters(), c9.getParameters()) : "Writen[" + c9.getParameters() + "] and read[" + rc9.getParameters() + "] objects should be the same";
 
       Map m1 = new HashMap();
       for (int i = 0; i < 10; i++) {
@@ -233,40 +224,40 @@
       }
       PutMapCommand c10 = new PutMapCommand(m1, null, 0, 0);
       marshallAndAssertEquality(c10);
-      
+
       Address local = new JGroupsAddress(new IpAddress(12345));
       GlobalTransaction gtx = GlobalTransaction.create(local);
       PrepareCommand c11 = new PrepareCommand(gtx, local, true, c5, c6, c8, c10);
       marshallAndAssertEquality(c11);
-      
+
       CommitCommand c12 = new CommitCommand(gtx);
       marshallAndAssertEquality(c12);
-      
+
       RollbackCommand c13 = new RollbackCommand(gtx);
       marshallAndAssertEquality(c13);
-      
-      MultipleRpcCommand c99 = new MultipleRpcCommand(Arrays.asList(new ReplicableCommand[] {c2, c5, c6, c8, c10, c12, c13}), "mycache");
+
+      MultipleRpcCommand c99 = new MultipleRpcCommand(Arrays.asList(new ReplicableCommand[]{c2, c5, c6, c8, c10, c12, c13}), "mycache");
       marshallAndAssertEquality(c99);
    }
-   
+
    public void testInternalCacheEntryMarshalling() throws Exception {
       ImmortalCacheEntry entry1 = (ImmortalCacheEntry) InternalEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), -1);
       marshallAndAssertEquality(entry1);
-      
-      MortalCacheEntry entry2 =  (MortalCacheEntry) InternalEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), -1);
+
+      MortalCacheEntry entry2 = (MortalCacheEntry) InternalEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), -1);
       marshallAndAssertEquality(entry2);
-      
+
       TransientCacheEntry entry3 = (TransientCacheEntry) InternalEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, -1, System.currentTimeMillis(), 4000000);
       marshallAndAssertEquality(entry3);
-      
+
       TransientMortalCacheEntry entry4 = (TransientMortalCacheEntry) InternalEntryFactory.create("key", "value", System.currentTimeMillis() - 1000, 200000, System.currentTimeMillis(), 4000000);
-      marshallAndAssertEquality(entry4);      
+      marshallAndAssertEquality(entry4);
    }
-   
+
    protected void marshallAndAssertEquality(Object writeObj) throws Exception {
       byte[] bytes = marshaller.objectToByteBuffer(writeObj);
       Object readObj = marshaller.objectFromByteBuffer(bytes);
-      assert readObj.equals(writeObj) : "Writen[" + writeObj + "] and read[" +  readObj +"] objects should be the same";
+      assert readObj.equals(writeObj) : "Writen[" + writeObj + "] and read[" + readObj + "] objects should be the same";
    }
-   
+
 }

Modified: trunk/core/src/test/java/org/infinispan/replication/AsyncReplTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/AsyncReplTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/replication/AsyncReplTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -28,7 +28,7 @@
    protected void createCacheManagers() throws Throwable {
       Configuration asyncConfiguration = getDefaultClusteredConfig(Configuration.CacheMode.REPL_ASYNC);
       asyncConfiguration.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
-      List<Cache> caches = createClusteredCaches(2, "asyncRepl", asyncConfiguration);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "asyncRepl", asyncConfiguration);
       cache1 = caches.get(0);
       cache2 = caches.get(1);
    }

Modified: trunk/core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/replication/BaseReplicatedAPITest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -25,7 +25,7 @@
       Configuration c = getDefaultClusteredConfig(isSync ? Configuration.CacheMode.REPL_SYNC : Configuration.CacheMode.REPL_ASYNC);
       c.setStateRetrievalTimeout(1000);
       c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
-      List<Cache> caches = createClusteredCaches(2, "replication", c);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "replication", c);
       cache1 = caches.get(0).getAdvancedCache();
       cache2 = caches.get(1).getAdvancedCache();
    }

Modified: trunk/core/src/test/java/org/infinispan/replication/ReplicationExceptionTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/ReplicationExceptionTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/replication/ReplicationExceptionTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -41,7 +41,7 @@
       configuration.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
       configuration.setLockAcquisitionTimeout(5000);
 
-      List<Cache> caches = createClusteredCaches(2, "replicatinExceptionTest", configuration);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "replicatinExceptionTest", configuration);
 
       cache1 = caches.get(0).getAdvancedCache();
       cache2 = caches.get(1).getAdvancedCache();

Modified: trunk/core/src/test/java/org/infinispan/replication/SyncCacheListenerTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/SyncCacheListenerTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/replication/SyncCacheListenerTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -43,7 +43,7 @@
       conf.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
       conf.setLockAcquisitionTimeout(5000);
 
-      List<Cache> caches = createClusteredCaches(2, "cache", conf);
+      List<Cache<Object, Object>> caches = createClusteredCaches(2, "cache", conf);
 
       cache1 = caches.get(0);
       cache2 = caches.get(1);

Modified: trunk/core/src/test/java/org/infinispan/replication/SyncReplTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/replication/SyncReplTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/replication/SyncReplTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -10,10 +10,11 @@
 import org.infinispan.Cache;
 import org.infinispan.commands.remote.CacheRpcCommand;
 import org.infinispan.config.Configuration;
+import org.infinispan.remoting.ResponseFilter;
+import org.infinispan.remoting.ResponseMode;
 import org.infinispan.remoting.RpcManager;
 import org.infinispan.remoting.RpcManagerImpl;
-import org.infinispan.remoting.ResponseFilter;
-import org.infinispan.remoting.ResponseMode;
+import org.infinispan.remoting.responses.Response;
 import org.infinispan.remoting.transport.Address;
 import org.infinispan.remoting.transport.Transport;
 import org.infinispan.test.MultipleCacheManagersTest;
@@ -119,6 +120,7 @@
    public void testMixingSyncAndAsyncOnSameTransport() throws Exception {
       Transport originalTransport = null;
       RpcManagerImpl rpcManager = null;
+      List<Response> emptyResponses = Collections.emptyList();
       try {
          Configuration asyncCache = getDefaultClusteredConfig(Configuration.CacheMode.REPL_ASYNC);
          defineCacheOnAllManagers("asyncCache", asyncCache);
@@ -142,7 +144,7 @@
 
          expect(mockTransport.invokeRemotely((List<Address>) anyObject(), (CacheRpcCommand) anyObject(), eq(ResponseMode.SYNCHRONOUS),
                                              anyLong(), anyBoolean(), (ResponseFilter) anyObject(), anyBoolean()))
-               .andReturn(Collections.emptyList()).once();
+               .andReturn(emptyResponses).once();
 
          replay(mockTransport);
          // check that the replication call was sync
@@ -154,7 +156,7 @@
          expect(mockTransport.getMembers()).andReturn(addresses).anyTimes();
          expect(mockTransport.invokeRemotely((List<Address>) anyObject(), (CacheRpcCommand) anyObject(), eq(ResponseMode.ASYNCHRONOUS),
                                              anyLong(), anyBoolean(), (ResponseFilter) anyObject(), anyBoolean()))
-               .andReturn(Collections.emptyList()).once();
+               .andReturn(emptyResponses).once();
 
          replay(mockTransport);
          asyncCache1.put("k", "v");

Modified: trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java	2009-04-17 17:03:05 UTC (rev 143)
+++ trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java	2009-04-17 18:34:10 UTC (rev 144)
@@ -1,9 +1,9 @@
 package org.infinispan.test;
 
 import org.infinispan.Cache;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
 import org.infinispan.config.Configuration;
 import org.infinispan.manager.CacheManager;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
@@ -44,7 +44,7 @@
 public abstract class MultipleCacheManagersTest extends AbstractCacheTest {
 
    private List<CacheManager> cacheManagers = new ArrayList<CacheManager>();
-   private IdentityHashMap<Cache, ReplListener> listeners = new IdentityHashMap<Cache, ReplListener>();   
+   private IdentityHashMap<Cache, ReplListener> listeners = new IdentityHashMap<Cache, ReplListener>();
 
    @BeforeClass
    public void createBeforeClass() throws Throwable {
@@ -85,9 +85,6 @@
       }
    }
 
-   /**
-    * @see #getDefaultReplicatedConfig()
-    */
    private void assertSupportedConfig() {
       for (CacheManager cm : cacheManagers) {
          for (Cache cache : getRunningCaches(cm)) {
@@ -125,12 +122,13 @@
       }
    }
 
-   protected List<Cache> createClusteredCaches(int numMembersInCluster, String cacheName, Configuration c) {
-      List<Cache> caches = new ArrayList<Cache>(numMembersInCluster);
+   protected <K, V> List<Cache<K, V>> createClusteredCaches(int numMembersInCluster, String cacheName, Configuration c) {
+      List<Cache<K, V>> caches = new ArrayList<Cache<K, V>>(numMembersInCluster);
       for (int i = 0; i < numMembersInCluster; i++) {
          CacheManager cm = addClusterEnabledCacheManager();
          cm.defineCache(cacheName, c);
-         caches.add(cm.getCache(cacheName));
+         Cache<K, V> cache = cm.getCache(cacheName);
+         caches.add(cache);
       }
       TestingUtil.blockUntilViewsReceived(10000, caches);
       return caches;




More information about the infinispan-commits mailing list