[jboss-cvs] JBossAS SVN: r107280 - in projects/cluster/ha-server-cache-ispn/trunk/src: main/java/org/jboss/ha/framework/server/ispn and 12 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Aug 2 13:12:00 EDT 2010


Author: pferraro
Date: 2010-08-02 13:11:58 -0400 (Mon, 02 Aug 2010)
New Revision: 107280

Added:
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/DistributedState.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandler.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/InfinispanHAPartitionCacheHandler.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/ispn/DistributedTreeManager.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManager.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactory.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/CacheKey.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManager.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandlerTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManagerTest.java
Removed:
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/DistributedStateImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/InfinispanHAPartitionCacheHandler.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/IncomingDistributableSessionDataImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshaller.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactory.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/CacheKey.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImplTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerTest.java
Modified:
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntry.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorage.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorage.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorage.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactory.java
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryImpl.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntryTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorageTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorageTest.java
   projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryTest.java
Log:
Refactor spi impls into ispn subpackages.
Refactor BatchingManagerImpl and IncomingDistributableSessionDataImpl into ha-server-cache-spi.

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/DistributedStateImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/DistributedStateImpl.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/DistributedStateImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,525 +0,0 @@
-/*
-  * JBoss, Home of Professional Open Source
-  * Copyright 2010, 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.jboss.ha.framework.server;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.infinispan.Cache;
-import org.infinispan.atomic.AtomicMap;
-import org.infinispan.atomic.AtomicMapLookup;
-import org.infinispan.config.Configuration;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
-import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
-import org.infinispan.CacheException;
-import org.infinispan.notifications.Listener;
-import org.infinispan.util.SimpleImmutableEntry;
-import org.jboss.ha.framework.server.spi.ManagedDistributedState;
-
-/**
- * This class manages distributed state across the cluster.
- *
- * The Cache layout will have two formats.  The value collection will combine the category
- * + DS key for the composite key.  The DS value will be the value.  It will look like:
- * Cache<SimpleImmutableEntry<String Category, Serializable DS_Key>, Serializable DS_Value>
- *
- * The other Cache format will be the DS keys per category.  It will look like:
- * Cache<String, AtomicMap<Serializable, null>>
- *
- * If it ever becomes important to eliminate the "keys per category" (e.g. to save space),
- * we would have to implement the getAllCategories() + getAllKeys() sequentially.
- *
- * @author  <a href="mailto:sacha.labourey at cogito-info.ch">Sacha Labourey</a>.
- * @author  <a href="mailto:bill at burkecentral.com">Bill Burke</a>.
- * @author  Scott.Stark at jboss.org
- * @author  Scott Marlow
- * @version $Revision:77673 $
- */
- at Listener
-public class DistributedStateImpl 
-   implements ManagedDistributedState
-{
-   private final ConcurrentHashMap<String, List<DSListener>> keyListeners = new ConcurrentHashMap<String, List<DSListener>>();
-
-   private volatile Cache<Serializable, Serializable> cache;
-   private volatile boolean replAsync;
-   private volatile InfinispanHAPartitionCacheHandler<Serializable, Serializable> cacheHandler;
-
-   public InfinispanHAPartitionCacheHandler<Serializable, Serializable> getCacheHandler()
-   {
-      return cacheHandler;
-   }
-
-   public void setCacheHandler(InfinispanHAPartitionCacheHandler<Serializable, Serializable> cacheHandler)
-   {
-      this.cacheHandler = cacheHandler;
-   }
-
-   // Public --------------------------------------------------------
-
-   @Override
-   public void createService() throws Exception
-   {
-   }
-
-   @Override
-   public void startService() throws Exception
-   {
-      this.internalSetClusteredCache(cacheHandler.getCache());
-      this.cache.addListener(this);
-   }
-
-   @Override
-   public void stopService() throws Exception
-   {      
-      this.cache.removeListener(this);
-   }
-
-   @Override
-   public void destroyService() throws Exception
-   {
-   }
-
-/*
-TODO:  jmx support, delete or bring mbean interface back.
-   public String listContent() throws Exception
-   {
-      StringBuilder result = new StringBuilder();
-      Collection<String> cats = this.getAllCategories();
-      if (cats == null) return result.toString();
-
-      Iterator<String> catsIter = cats.iterator();
-      while (catsIter.hasNext())
-      {
-         String category = (String) catsIter.next();
-         Iterator<Serializable> keysIter = this.getAllKeys(category).iterator();
-
-         result.append("-----------------------------------------------\n");
-         result.append("Logger : ").append(category).append("\n\n");
-         result.append("KEY\t:\tVALUE\n");
-
-         while (keysIter.hasNext())
-         {
-            Serializable key = (Serializable) keysIter.next();
-            String value = this.get(category, key).toString();
-            result.append("'").append(key);
-            result.append("'\t:\t'");
-            result.append(value);
-            result.append("'\n");
-         }
-         result.append("\n");
-      }
-      return result.toString();
-   }
-
-   public String listXmlContent() throws Exception
-   {
-      StringBuilder result = new StringBuilder();
-      result.append("<DistributedState>\n");
-      Collection<String> cats = this.getAllCategories();
-      if (cats != null)
-      {
-         Iterator<String> catsIter = cats.iterator();
-         while (catsIter.hasNext())
-         {
-            String category = (String) catsIter.next();
-            Iterator<Serializable> keysIter = this.getAllKeys(category).iterator();
-
-            result.append("\t<Logger>\n");
-            result.append("\t\t<LoggerName>").append(category).append("</LoggerName>\n");
-
-            while (keysIter.hasNext())
-            {
-               Serializable key = (Serializable) keysIter.next();
-               String value = this.get(category, key).toString();
-               result.append("\t\t<Entry>\n");
-               result.append("\t\t\t<Key>").append(key).append("</Key>\n");
-               result.append("\t\t\t<Value>").append(value).append("</Value>\n");
-               result.append("\t\t</Entry>\n");
-            }
-            result.append("\t</Logger>\n");
-         }
-      }
-
-      result.append("</DistributedState>\n");
-
-      return result.toString();
-   }
-*/
-
-   // DistributedState implementation ----------------------------------------------
-   /*
-   * (non-Javadoc)
-   *
-   * @see org.jboss.ha.framework.interfaces.DistributedState#set(java.lang.String,
-   *      java.io.Serializable, java.io.Serializable)
-   */
-   @Override
-   public void set(String category, Serializable key, Serializable value) throws Exception
-   {
-      this.set(category, key, value, true);
-   }
-
-   /*
-    * (non-Javadoc)
-    *
-    * @see org.jboss.ha.framework.interfaces.DistributedState#set(java.lang.String,
-    *      java.io.Serializable, java.io.Serializable, boolean) @param
-    *      asynchronousCall is not supported yet. TreeCache cannot switch this
-    *      on the fly. Will take value from TreeCache-config instead.
-    */
-   @Override
-   public void set(String category, Serializable key, Serializable value, boolean asynchronousCall) throws Exception
-   {
-      //if (this.replAsync != asynchronousCall)
-      //{
-      //   if (asynchronousCall)
-      //   {
-      //      this.cache.put(this.buildFqn(category), key, value, Flag.FORCE_ASYNCHRONOUS);
-      //   }
-      //   else
-      //   {
-      //      this.cache.put(this.buildFqn(category), key, value, Flag.FORCE_SYNCHRONOUS);
-      //   }
-      //}
-      this.cache.startBatch();
-      boolean commit = false;
-      try
-      {
-         this.cache.put(buildValueCollectionKey(category, key), value);
-         AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
-         m.put(key, null);
-         commit = true;
-      }
-      finally 
-      {
-         this.cache.endBatch(commit);
-      }
-   }
-
-
-   /*
-     * (non-Javadoc)
-     *
-     * @see org.jboss.ha.framework.interfaces.DistributedState#remove(java.lang.String,
-     *      java.io.Serializable) @return - returns null in case of
-     *      CacheException
-     */
-   @Override
-   public Serializable remove(String category, Serializable key) throws Exception
-   {
-      return this.remove(category, key, true);
-   }
-
-   /*
-    * (non-Javadoc)
-    *
-    * @see org.jboss.ha.framework.interfaces.DistributedState#remove(java.lang.String,
-    *      java.io.Serializable, boolean)
-    */
-   @Override
-   public Serializable remove(String category, Serializable key, boolean asynchronousCall) throws Exception
-   {
-      Serializable retVal = this.get(category, key);
-      if (retVal != null)
-      {
-      //   if (this.replAsync != asynchronousCall)
-      //   {
-      //      if (asynchronousCall)
-      //      {
-      //         this.cache.getInvocationContext().getOptionOverrides().setForceAsynchronous(true);
-      //      }
-      //      else
-      //      {
-      //         this.cache.getInvocationContext().getOptionOverrides().setForceSynchronous(true);
-      //      }
-      //   }
-         cache.startBatch();
-         boolean commit = false;
-         try
-         {
-            cache.remove(buildValueCollectionKey(category, key));
-            AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
-            m.remove(key);
-            commit = true;
-         }
-         finally
-         {
-            cache.endBatch(commit);
-         }
-
-      }
-      return retVal;
-   }
-
-   /*
-     * (non-Javadoc)
-     *
-     * @see org.jboss.ha.framework.interfaces.DistributedState#get(java.lang.String,
-     *      java.io.Serializable)
-     */
-   @Override
-   public Serializable get(String category, Serializable key)
-   {
-      try
-      {
-         return this.cache.get(buildValueCollectionKey(category, key));
-      }
-      catch (CacheException ce)
-      {
-         return null;
-      }
-   }
-
-   @Override
-   public Collection<String> getAllCategories()
-   {
-      try
-      {
-         Set<Serializable> keys = this.cache.keySet();
-         if (keys.isEmpty()) return null;
-
-         List<String> categories = new LinkedList<String>();
-         for (Serializable key: keys)
-         {
-            if (key instanceof String)  // only the keys that are Strings, are categories
-            {
-               categories.add((String) key);
-            }
-         }
-         return categories;
-      }
-      catch (CacheException ce)
-      {
-         return null;
-      }
-   }
-
-   /*
-     * (non-Javadoc)
-     *
-     * @see org.jboss.ha.framework.interfaces.DistributedState#getAllKeys(java.lang.String)
-     *      @return - returns null in case of CacheException
-     */
-   @Override
-   public Collection<Serializable> getAllKeys(String category)
-   {
-      try
-      {
-         AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
-         return m.keySet();  // the keyset are the DS keys
-      }
-      catch (CacheException ce)
-      {
-         return null;
-      }
-   }
-
-   /*
-     * (non-Javadoc)
-     *
-     * @see org.jboss.ha.framework.interfaces.DistributedState#getAllValues(java.lang.String)
-     *      @return - returns null in case of CacheException
-     */
-   @Override
-   public Collection<Serializable> getAllValues(String category)
-   {
-      try
-      {
-         Collection<Serializable> keys = getAllKeys(category);
-         
-         if (keys == null) return null;
-
-         List<Serializable> values = new ArrayList<Serializable>();
-         for (Serializable key: keys)
-         {
-            values.add(cache.get(buildValueCollectionKey(category, key)));
-         }
-         return values;
-      }
-      catch (CacheException ce)
-      {
-         return null;
-      }
-   }
-
-   @Override
-   public void registerDSListenerEx(String category, @SuppressWarnings("deprecation") DSListenerEx subscriber)
-   {
-      this.registerDSListener(category, subscriber);
-   }
-
-   @Override
-   public void unregisterDSListenerEx(String category, @SuppressWarnings("deprecation") DSListenerEx subscriber)
-   {
-      this.unregisterDSListener(category, subscriber);
-   }
-
-   @Override
-   public void registerDSListener(String category, DSListener subscriber)
-   {
-      List<DSListener> listeners = this.keyListeners.get(category);
-      if (listeners == null)
-      {
-         listeners = new CopyOnWriteArrayList<DSListener>();
-         List<DSListener> existing = this.keyListeners.putIfAbsent(category, listeners);
-         if (existing != null )
-         {
-            listeners = existing;   // use the listeners added by other thread
-         }
-      }
-      listeners.add(subscriber);
-   }
-
-   @Override
-   public void unregisterDSListener(String category, DSListener subscriber)
-   {
-      List<DSListener> listeners = this.keyListeners.get(category);
-      if (listeners != null)
-      {
-         listeners.remove(subscriber);
-         this.keyListeners.remove(category, Collections.emptyList());
-      }
-   }
-
-   // ChannelSource -------------------------------------------------
-
-//   public Channel getChannel()
-//   {
-//      Channel result = null;
-//      if (cache != null)
-//      {
-//         result = cache.getConfiguration().getRuntimeConfig().getChannel();
-//      }
-//      return result;
-//   }
-   
-   // Package protected ---------------------------------------------
-
-   protected void notifyKeyListeners(String category, Serializable key, Serializable value, boolean locallyModified)
-   {
-      List<DSListener> listeners = this.keyListeners.get(category);
-      if (listeners == null) return;
-
-      for (DSListener listener: listeners)
-      {
-         listener.valueHasChanged(category, key, value, locallyModified);
-      }
-   }
-
-   protected void notifyKeyListenersOfRemove(String category, Serializable key, Serializable oldContent,
-         boolean locallyModified)
-   {
-      List<DSListener> listeners = this.keyListeners.get(category);
-      if (listeners == null) return;
-
-      for (DSListener listener: listeners)
-      {
-         listener.keyHasBeenRemoved(category, key, oldContent, locallyModified);
-      }
-   }
-
-   protected void cleanupKeyListeners()
-   {
-      // NOT IMPLEMENTED YET
-   }
-
-   /** ExtendedTreeCacheListener methods */
-
-   // Private -------------------------------------------------------
-
-   // @CacheListener  -------------------------------------------------
-
-   @CacheEntryModified
-   public void nodeModified(CacheEntryModifiedEvent event)
-   {
-      if (event.isPre()) return;
-
-      Object key = event.getKey();
-      
-      if (key instanceof SimpleImmutableEntry)
-      {
-         @SuppressWarnings("unchecked")
-         SimpleImmutableEntry<String, Serializable> entry = (SimpleImmutableEntry<String, Serializable>) key;
-         notifyKeyListeners(entry.getKey(), entry.getValue(), (Serializable) event.getValue(), event.isOriginLocal());
-      }
-   }
-
-   @CacheEntryRemoved
-   public void nodeRemoved(CacheEntryRemovedEvent event)
-   {
-      if (event.isPre()) return;
-
-      Object key = event.getKey();
-
-      if (key instanceof SimpleImmutableEntry)
-      {
-         @SuppressWarnings("unchecked")
-         SimpleImmutableEntry<String, Serializable> entry = (SimpleImmutableEntry<String, Serializable>) key;
-         notifyKeyListenersOfRemove(entry.getKey(), entry.getValue(), (Serializable) event.getValue(), event.isOriginLocal());
-      }
-   }
-
-   
-   // Private ------------------------------------------------------------
-   
-   private void internalSetClusteredCache(Cache<Serializable, Serializable> cache)
-   {
-      this.cache = cache;
-
-      if (this.cache != null)
-      {        
-        Configuration.CacheMode cm = cache.getConfiguration().getCacheMode();
-        if (Configuration.CacheMode.REPL_ASYNC == cm)
-        {
-           this.replAsync = true;
-        }
-        else if (Configuration.CacheMode.REPL_SYNC == cm)
-        {
-           this.replAsync = false;
-        }
-        else
-        {
-           throw new IllegalStateException("Cache must be configured for replication, not " + cm);
-        }
-      }
-   }
-
-   private SimpleImmutableEntry<String, Serializable> buildValueCollectionKey(String category, Serializable dskey)
-   {
-      return new SimpleImmutableEntry<String, Serializable>(category, dskey);
-   }
-
-   private AtomicMap<Serializable, Void> getKeysPerCategoryCollection(String category)
-   {
-      return AtomicMapLookup.getAtomicMap(this.cache, category, true);
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImpl.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,170 +0,0 @@
-package org.jboss.ha.framework.server;
-
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.infinispan.Cache;
-import org.infinispan.lifecycle.ComponentStatus;
-import org.infinispan.manager.CacheContainer;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.jboss.ha.ispn.CacheContainerRegistry;
-import org.jgroups.ChannelFactory;
-
- at SuppressWarnings("deprecation")
-public class HAPartitionCacheHandlerImpl<K, V> implements InfinispanHAPartitionCacheHandler<K, V>
-{
-   private final CacheContainerRegistry registry;
-   private final AtomicReference<Cache<K, V>> cacheReference = new AtomicReference<Cache<K, V>>();
-   private final AtomicInteger acquireCount = new AtomicInteger();
-   
-   private volatile String cacheContainerName;
-   private volatile String cacheName;
-   
-   public HAPartitionCacheHandlerImpl(CacheContainerRegistry registry)
-   {
-      this.registry = registry;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.InfinispanHAPartitionCacheHandler#getCache()
-    */
-   @Override
-   public Cache<K, V> getCache()
-   {
-      return this.cacheReference.get();
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#acquireCache()
-    */
-   @Override
-   public void acquireCache()
-   {
-      if (this.cacheReference.get() == null)
-      {
-         CacheContainer container = this.registry.getCacheContainer(this.cacheContainerName);
-         
-         String name = this.cacheName;
-         
-         this.cacheReference.compareAndSet(null, (name != null) ? container.<K, V>getCache(name) : container.<K, V>getCache());
-      }
-      
-      this.acquireCount.incrementAndGet();
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#startCache()
-    */
-   @Override
-   public void startCache()
-   {
-      Cache<K, V> cache = this.cacheReference.get();
-      
-      if (cache == null)
-      {
-         throw new IllegalStateException("You must first acquire a cache before starting it.");
-      }
-      
-      if (cache.getStatus() != ComponentStatus.RUNNING)
-      {
-         cache.start();
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#releaseCache()
-    */
-   @Override
-   public void releaseCache()
-   {
-      int count = this.acquireCount.decrementAndGet();
-      
-      if (count == 0)
-      {
-         Cache<K, V> cache = this.cacheReference.getAndSet(null);
-         
-         if ((cache != null) && (cache.getStatus() == ComponentStatus.RUNNING))
-         {
-            cache.stop();
-         }
-      }
-      else if (count < 0)
-      {
-         // Attempt to resolve
-         this.acquireCount.compareAndSet(count, count + 1);
-         
-         throw new IllegalStateException("Attempt to release cache that was not acquired.");
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getChannelStackName()
-    */
-   @Override
-   public String getChannelStackName()
-   {
-      return this.getTransportProperties().getProperty("stack");
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getCacheChannelFactory()
-    */
-   @Override
-   public ChannelFactory getCacheChannelFactory()
-   {
-      return (ChannelFactory) this.getTransportProperties().get("channelFactory");
-   }
-   
-   private Properties getTransportProperties()
-   {
-      Cache<K, V> cache = this.cacheReference.get();
-      
-      if (cache == null)
-      {
-         throw new IllegalStateException("Must acquire cache before getting channel stack name");
-      }
-      
-      CacheContainer container = cache.getCacheManager();
-      
-      if (!(container instanceof EmbeddedCacheManager))
-      {
-         throw new IllegalStateException(String.format("Cache container [%s] is not of the expected type: %s", container.getClass().getName(), EmbeddedCacheManager.class.getName()));
-      }
-      
-      EmbeddedCacheManager manager = (EmbeddedCacheManager) container;
-      
-      return manager.getGlobalConfiguration().getTransportProperties();
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getCacheConfigName()
-    */
-   @Override
-   public String getCacheConfigName()
-   {
-      return this.cacheName;
-   }
-   
-   public void setCacheConfigName(String cacheName)
-   {
-      this.cacheName = cacheName;
-   }
-   
-   public String getCacheContainerName()
-   {
-      return this.cacheContainerName;
-   }
-   
-   public void setCacheContainerName(String cacheContainerName)
-   {
-      this.cacheContainerName = cacheContainerName;
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/InfinispanHAPartitionCacheHandler.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/InfinispanHAPartitionCacheHandler.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/InfinispanHAPartitionCacheHandler.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.framework.server;
-
-import org.infinispan.Cache;
-import org.jboss.ha.framework.server.spi.HAPartitionCacheHandler;
-
-/**
- * Provides access to the underlying Infinispan cache instance of this cache handler.
- * @author Paul Ferraro
- */
-public interface InfinispanHAPartitionCacheHandler<K, V> extends HAPartitionCacheHandler
-{
-   /**
-    * Returns the cache instance associated with this cache handler.
-    * @return an Infinispan cache instance.
-    */
-   Cache<K, V> getCache();
-}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/DistributedState.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/DistributedStateImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/DistributedState.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/DistributedState.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,525 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2010, 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.jboss.ha.framework.server.ispn;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.infinispan.Cache;
+import org.infinispan.atomic.AtomicMap;
+import org.infinispan.atomic.AtomicMapLookup;
+import org.infinispan.config.Configuration;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+import org.infinispan.CacheException;
+import org.infinispan.notifications.Listener;
+import org.infinispan.util.SimpleImmutableEntry;
+import org.jboss.ha.framework.server.spi.ManagedDistributedState;
+
+/**
+ * This class manages distributed state across the cluster.
+ *
+ * The Cache layout will have two formats.  The value collection will combine the category
+ * + DS key for the composite key.  The DS value will be the value.  It will look like:
+ * Cache<SimpleImmutableEntry<String Category, Serializable DS_Key>, Serializable DS_Value>
+ *
+ * The other Cache format will be the DS keys per category.  It will look like:
+ * Cache<String, AtomicMap<Serializable, null>>
+ *
+ * If it ever becomes important to eliminate the "keys per category" (e.g. to save space),
+ * we would have to implement the getAllCategories() + getAllKeys() sequentially.
+ *
+ * @author  <a href="mailto:sacha.labourey at cogito-info.ch">Sacha Labourey</a>.
+ * @author  <a href="mailto:bill at burkecentral.com">Bill Burke</a>.
+ * @author  Scott.Stark at jboss.org
+ * @author  Scott Marlow
+ * @version $Revision:77673 $
+ */
+ at Listener
+public class DistributedState 
+   implements ManagedDistributedState
+{
+   private final ConcurrentHashMap<String, List<DSListener>> keyListeners = new ConcurrentHashMap<String, List<DSListener>>();
+
+   private volatile Cache<Serializable, Serializable> cache;
+   private volatile boolean replAsync;
+   private volatile InfinispanHAPartitionCacheHandler<Serializable, Serializable> cacheHandler;
+
+   public InfinispanHAPartitionCacheHandler<Serializable, Serializable> getCacheHandler()
+   {
+      return cacheHandler;
+   }
+
+   public void setCacheHandler(InfinispanHAPartitionCacheHandler<Serializable, Serializable> cacheHandler)
+   {
+      this.cacheHandler = cacheHandler;
+   }
+
+   // Public --------------------------------------------------------
+
+   @Override
+   public void createService() throws Exception
+   {
+   }
+
+   @Override
+   public void startService() throws Exception
+   {
+      this.internalSetClusteredCache(cacheHandler.getCache());
+      this.cache.addListener(this);
+   }
+
+   @Override
+   public void stopService() throws Exception
+   {      
+      this.cache.removeListener(this);
+   }
+
+   @Override
+   public void destroyService() throws Exception
+   {
+   }
+
+/*
+TODO:  jmx support, delete or bring mbean interface back.
+   public String listContent() throws Exception
+   {
+      StringBuilder result = new StringBuilder();
+      Collection<String> cats = this.getAllCategories();
+      if (cats == null) return result.toString();
+
+      Iterator<String> catsIter = cats.iterator();
+      while (catsIter.hasNext())
+      {
+         String category = (String) catsIter.next();
+         Iterator<Serializable> keysIter = this.getAllKeys(category).iterator();
+
+         result.append("-----------------------------------------------\n");
+         result.append("Logger : ").append(category).append("\n\n");
+         result.append("KEY\t:\tVALUE\n");
+
+         while (keysIter.hasNext())
+         {
+            Serializable key = (Serializable) keysIter.next();
+            String value = this.get(category, key).toString();
+            result.append("'").append(key);
+            result.append("'\t:\t'");
+            result.append(value);
+            result.append("'\n");
+         }
+         result.append("\n");
+      }
+      return result.toString();
+   }
+
+   public String listXmlContent() throws Exception
+   {
+      StringBuilder result = new StringBuilder();
+      result.append("<DistributedState>\n");
+      Collection<String> cats = this.getAllCategories();
+      if (cats != null)
+      {
+         Iterator<String> catsIter = cats.iterator();
+         while (catsIter.hasNext())
+         {
+            String category = (String) catsIter.next();
+            Iterator<Serializable> keysIter = this.getAllKeys(category).iterator();
+
+            result.append("\t<Logger>\n");
+            result.append("\t\t<LoggerName>").append(category).append("</LoggerName>\n");
+
+            while (keysIter.hasNext())
+            {
+               Serializable key = (Serializable) keysIter.next();
+               String value = this.get(category, key).toString();
+               result.append("\t\t<Entry>\n");
+               result.append("\t\t\t<Key>").append(key).append("</Key>\n");
+               result.append("\t\t\t<Value>").append(value).append("</Value>\n");
+               result.append("\t\t</Entry>\n");
+            }
+            result.append("\t</Logger>\n");
+         }
+      }
+
+      result.append("</DistributedState>\n");
+
+      return result.toString();
+   }
+*/
+
+   // DistributedState implementation ----------------------------------------------
+   /*
+   * (non-Javadoc)
+   *
+   * @see org.jboss.ha.framework.interfaces.DistributedState#set(java.lang.String,
+   *      java.io.Serializable, java.io.Serializable)
+   */
+   @Override
+   public void set(String category, Serializable key, Serializable value) throws Exception
+   {
+      this.set(category, key, value, true);
+   }
+
+   /*
+    * (non-Javadoc)
+    *
+    * @see org.jboss.ha.framework.interfaces.DistributedState#set(java.lang.String,
+    *      java.io.Serializable, java.io.Serializable, boolean) @param
+    *      asynchronousCall is not supported yet. TreeCache cannot switch this
+    *      on the fly. Will take value from TreeCache-config instead.
+    */
+   @Override
+   public void set(String category, Serializable key, Serializable value, boolean asynchronousCall) throws Exception
+   {
+      //if (this.replAsync != asynchronousCall)
+      //{
+      //   if (asynchronousCall)
+      //   {
+      //      this.cache.put(this.buildFqn(category), key, value, Flag.FORCE_ASYNCHRONOUS);
+      //   }
+      //   else
+      //   {
+      //      this.cache.put(this.buildFqn(category), key, value, Flag.FORCE_SYNCHRONOUS);
+      //   }
+      //}
+      this.cache.startBatch();
+      boolean commit = false;
+      try
+      {
+         this.cache.put(buildValueCollectionKey(category, key), value);
+         AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
+         m.put(key, null);
+         commit = true;
+      }
+      finally 
+      {
+         this.cache.endBatch(commit);
+      }
+   }
+
+
+   /*
+     * (non-Javadoc)
+     *
+     * @see org.jboss.ha.framework.interfaces.DistributedState#remove(java.lang.String,
+     *      java.io.Serializable) @return - returns null in case of
+     *      CacheException
+     */
+   @Override
+   public Serializable remove(String category, Serializable key) throws Exception
+   {
+      return this.remove(category, key, true);
+   }
+
+   /*
+    * (non-Javadoc)
+    *
+    * @see org.jboss.ha.framework.interfaces.DistributedState#remove(java.lang.String,
+    *      java.io.Serializable, boolean)
+    */
+   @Override
+   public Serializable remove(String category, Serializable key, boolean asynchronousCall) throws Exception
+   {
+      Serializable retVal = this.get(category, key);
+      if (retVal != null)
+      {
+      //   if (this.replAsync != asynchronousCall)
+      //   {
+      //      if (asynchronousCall)
+      //      {
+      //         this.cache.getInvocationContext().getOptionOverrides().setForceAsynchronous(true);
+      //      }
+      //      else
+      //      {
+      //         this.cache.getInvocationContext().getOptionOverrides().setForceSynchronous(true);
+      //      }
+      //   }
+         cache.startBatch();
+         boolean commit = false;
+         try
+         {
+            cache.remove(buildValueCollectionKey(category, key));
+            AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
+            m.remove(key);
+            commit = true;
+         }
+         finally
+         {
+            cache.endBatch(commit);
+         }
+
+      }
+      return retVal;
+   }
+
+   /*
+     * (non-Javadoc)
+     *
+     * @see org.jboss.ha.framework.interfaces.DistributedState#get(java.lang.String,
+     *      java.io.Serializable)
+     */
+   @Override
+   public Serializable get(String category, Serializable key)
+   {
+      try
+      {
+         return this.cache.get(buildValueCollectionKey(category, key));
+      }
+      catch (CacheException ce)
+      {
+         return null;
+      }
+   }
+
+   @Override
+   public Collection<String> getAllCategories()
+   {
+      try
+      {
+         Set<Serializable> keys = this.cache.keySet();
+         if (keys.isEmpty()) return null;
+
+         List<String> categories = new LinkedList<String>();
+         for (Serializable key: keys)
+         {
+            if (key instanceof String)  // only the keys that are Strings, are categories
+            {
+               categories.add((String) key);
+            }
+         }
+         return categories;
+      }
+      catch (CacheException ce)
+      {
+         return null;
+      }
+   }
+
+   /*
+     * (non-Javadoc)
+     *
+     * @see org.jboss.ha.framework.interfaces.DistributedState#getAllKeys(java.lang.String)
+     *      @return - returns null in case of CacheException
+     */
+   @Override
+   public Collection<Serializable> getAllKeys(String category)
+   {
+      try
+      {
+         AtomicMap<Serializable, Void> m = getKeysPerCategoryCollection(category);
+         return m.keySet();  // the keyset are the DS keys
+      }
+      catch (CacheException ce)
+      {
+         return null;
+      }
+   }
+
+   /*
+     * (non-Javadoc)
+     *
+     * @see org.jboss.ha.framework.interfaces.DistributedState#getAllValues(java.lang.String)
+     *      @return - returns null in case of CacheException
+     */
+   @Override
+   public Collection<Serializable> getAllValues(String category)
+   {
+      try
+      {
+         Collection<Serializable> keys = getAllKeys(category);
+         
+         if (keys == null) return null;
+
+         List<Serializable> values = new ArrayList<Serializable>();
+         for (Serializable key: keys)
+         {
+            values.add(cache.get(buildValueCollectionKey(category, key)));
+         }
+         return values;
+      }
+      catch (CacheException ce)
+      {
+         return null;
+      }
+   }
+
+   @Override
+   public void registerDSListenerEx(String category, @SuppressWarnings("deprecation") DSListenerEx subscriber)
+   {
+      this.registerDSListener(category, subscriber);
+   }
+
+   @Override
+   public void unregisterDSListenerEx(String category, @SuppressWarnings("deprecation") DSListenerEx subscriber)
+   {
+      this.unregisterDSListener(category, subscriber);
+   }
+
+   @Override
+   public void registerDSListener(String category, DSListener subscriber)
+   {
+      List<DSListener> listeners = this.keyListeners.get(category);
+      if (listeners == null)
+      {
+         listeners = new CopyOnWriteArrayList<DSListener>();
+         List<DSListener> existing = this.keyListeners.putIfAbsent(category, listeners);
+         if (existing != null )
+         {
+            listeners = existing;   // use the listeners added by other thread
+         }
+      }
+      listeners.add(subscriber);
+   }
+
+   @Override
+   public void unregisterDSListener(String category, DSListener subscriber)
+   {
+      List<DSListener> listeners = this.keyListeners.get(category);
+      if (listeners != null)
+      {
+         listeners.remove(subscriber);
+         this.keyListeners.remove(category, Collections.emptyList());
+      }
+   }
+
+   // ChannelSource -------------------------------------------------
+
+//   public Channel getChannel()
+//   {
+//      Channel result = null;
+//      if (cache != null)
+//      {
+//         result = cache.getConfiguration().getRuntimeConfig().getChannel();
+//      }
+//      return result;
+//   }
+   
+   // Package protected ---------------------------------------------
+
+   protected void notifyKeyListeners(String category, Serializable key, Serializable value, boolean locallyModified)
+   {
+      List<DSListener> listeners = this.keyListeners.get(category);
+      if (listeners == null) return;
+
+      for (DSListener listener: listeners)
+      {
+         listener.valueHasChanged(category, key, value, locallyModified);
+      }
+   }
+
+   protected void notifyKeyListenersOfRemove(String category, Serializable key, Serializable oldContent,
+         boolean locallyModified)
+   {
+      List<DSListener> listeners = this.keyListeners.get(category);
+      if (listeners == null) return;
+
+      for (DSListener listener: listeners)
+      {
+         listener.keyHasBeenRemoved(category, key, oldContent, locallyModified);
+      }
+   }
+
+   protected void cleanupKeyListeners()
+   {
+      // NOT IMPLEMENTED YET
+   }
+
+   /** ExtendedTreeCacheListener methods */
+
+   // Private -------------------------------------------------------
+
+   // @CacheListener  -------------------------------------------------
+
+   @CacheEntryModified
+   public void nodeModified(CacheEntryModifiedEvent event)
+   {
+      if (event.isPre()) return;
+
+      Object key = event.getKey();
+      
+      if (key instanceof SimpleImmutableEntry)
+      {
+         @SuppressWarnings("unchecked")
+         SimpleImmutableEntry<String, Serializable> entry = (SimpleImmutableEntry<String, Serializable>) key;
+         notifyKeyListeners(entry.getKey(), entry.getValue(), (Serializable) event.getValue(), event.isOriginLocal());
+      }
+   }
+
+   @CacheEntryRemoved
+   public void nodeRemoved(CacheEntryRemovedEvent event)
+   {
+      if (event.isPre()) return;
+
+      Object key = event.getKey();
+
+      if (key instanceof SimpleImmutableEntry)
+      {
+         @SuppressWarnings("unchecked")
+         SimpleImmutableEntry<String, Serializable> entry = (SimpleImmutableEntry<String, Serializable>) key;
+         notifyKeyListenersOfRemove(entry.getKey(), entry.getValue(), (Serializable) event.getValue(), event.isOriginLocal());
+      }
+   }
+
+   
+   // Private ------------------------------------------------------------
+   
+   private void internalSetClusteredCache(Cache<Serializable, Serializable> cache)
+   {
+      this.cache = cache;
+
+      if (this.cache != null)
+      {        
+        Configuration.CacheMode cm = cache.getConfiguration().getCacheMode();
+        if (Configuration.CacheMode.REPL_ASYNC == cm)
+        {
+           this.replAsync = true;
+        }
+        else if (Configuration.CacheMode.REPL_SYNC == cm)
+        {
+           this.replAsync = false;
+        }
+        else
+        {
+           throw new IllegalStateException("Cache must be configured for replication, not " + cm);
+        }
+      }
+   }
+
+   private SimpleImmutableEntry<String, Serializable> buildValueCollectionKey(String category, Serializable dskey)
+   {
+      return new SimpleImmutableEntry<String, Serializable>(category, dskey);
+   }
+
+   private AtomicMap<Serializable, Void> getKeysPerCategoryCollection(String category)
+   {
+      return AtomicMapLookup.getAtomicMap(this.cache, category, true);
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandler.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandler.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandler.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,170 @@
+package org.jboss.ha.framework.server.ispn;
+
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.infinispan.Cache;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.manager.CacheContainer;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.jboss.ha.ispn.CacheContainerRegistry;
+import org.jgroups.ChannelFactory;
+
+ at SuppressWarnings("deprecation")
+public class HAPartitionCacheHandler<K, V> implements InfinispanHAPartitionCacheHandler<K, V>
+{
+   private final CacheContainerRegistry registry;
+   private final AtomicReference<Cache<K, V>> cacheReference = new AtomicReference<Cache<K, V>>();
+   private final AtomicInteger acquireCount = new AtomicInteger();
+   
+   private volatile String cacheContainerName;
+   private volatile String cacheName;
+   
+   public HAPartitionCacheHandler(CacheContainerRegistry registry)
+   {
+      this.registry = registry;
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.ispn.InfinispanHAPartitionCacheHandler#getCache()
+    */
+   @Override
+   public Cache<K, V> getCache()
+   {
+      return this.cacheReference.get();
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#acquireCache()
+    */
+   @Override
+   public void acquireCache()
+   {
+      if (this.cacheReference.get() == null)
+      {
+         CacheContainer container = this.registry.getCacheContainer(this.cacheContainerName);
+         
+         String name = this.cacheName;
+         
+         this.cacheReference.compareAndSet(null, (name != null) ? container.<K, V>getCache(name) : container.<K, V>getCache());
+      }
+      
+      this.acquireCount.incrementAndGet();
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#startCache()
+    */
+   @Override
+   public void startCache()
+   {
+      Cache<K, V> cache = this.cacheReference.get();
+      
+      if (cache == null)
+      {
+         throw new IllegalStateException("You must first acquire a cache before starting it.");
+      }
+      
+      if (cache.getStatus() != ComponentStatus.RUNNING)
+      {
+         cache.start();
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#releaseCache()
+    */
+   @Override
+   public void releaseCache()
+   {
+      int count = this.acquireCount.decrementAndGet();
+      
+      if (count == 0)
+      {
+         Cache<K, V> cache = this.cacheReference.getAndSet(null);
+         
+         if ((cache != null) && (cache.getStatus() == ComponentStatus.RUNNING))
+         {
+            cache.stop();
+         }
+      }
+      else if (count < 0)
+      {
+         // Attempt to resolve
+         this.acquireCount.compareAndSet(count, count + 1);
+         
+         throw new IllegalStateException("Attempt to release cache that was not acquired.");
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getChannelStackName()
+    */
+   @Override
+   public String getChannelStackName()
+   {
+      return this.getTransportProperties().getProperty("stack");
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getCacheChannelFactory()
+    */
+   @Override
+   public ChannelFactory getCacheChannelFactory()
+   {
+      return (ChannelFactory) this.getTransportProperties().get("channelFactory");
+   }
+   
+   private Properties getTransportProperties()
+   {
+      Cache<K, V> cache = this.cacheReference.get();
+      
+      if (cache == null)
+      {
+         throw new IllegalStateException("Must acquire cache before getting channel stack name");
+      }
+      
+      CacheContainer container = cache.getCacheManager();
+      
+      if (!(container instanceof EmbeddedCacheManager))
+      {
+         throw new IllegalStateException(String.format("Cache container [%s] is not of the expected type: %s", container.getClass().getName(), EmbeddedCacheManager.class.getName()));
+      }
+      
+      EmbeddedCacheManager manager = (EmbeddedCacheManager) container;
+      
+      return manager.getGlobalConfiguration().getTransportProperties();
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ha.framework.server.spi.HAPartitionCacheHandler#getCacheConfigName()
+    */
+   @Override
+   public String getCacheConfigName()
+   {
+      return this.cacheName;
+   }
+   
+   public void setCacheConfigName(String cacheName)
+   {
+      this.cacheName = cacheName;
+   }
+   
+   public String getCacheContainerName()
+   {
+      return this.cacheContainerName;
+   }
+   
+   public void setCacheContainerName(String cacheContainerName)
+   {
+      this.cacheContainerName = cacheContainerName;
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/InfinispanHAPartitionCacheHandler.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/InfinispanHAPartitionCacheHandler.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/InfinispanHAPartitionCacheHandler.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/framework/server/ispn/InfinispanHAPartitionCacheHandler.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.jboss.ha.framework.server.ispn;
+
+import org.infinispan.Cache;
+import org.jboss.ha.framework.server.spi.HAPartitionCacheHandler;
+
+/**
+ * Provides access to the underlying Infinispan cache instance of this cache handler.
+ * @author Paul Ferraro
+ */
+public interface InfinispanHAPartitionCacheHandler<K, V> extends HAPartitionCacheHandler
+{
+   /**
+    * Returns the cache instance associated with this cache handler.
+    * @return an Infinispan cache instance.
+    */
+   Cache<K, V> getCache();
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/ispn/DistributedTreeManager.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/ispn/DistributedTreeManager.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/ispn/DistributedTreeManager.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,540 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2010, 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.jboss.ha.jndi.ispn;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+
+import org.infinispan.CacheException;
+import org.infinispan.tree.Fqn;
+import org.infinispan.tree.Node;
+import org.infinispan.tree.TreeCache;
+import org.jboss.ha.framework.server.ispn.InfinispanHAPartitionCacheHandler;
+import org.jboss.ha.ispn.tree.DefaultTreeCacheFactory;
+import org.jboss.ha.ispn.tree.TreeCacheFactory;
+import org.jboss.logging.Logger;
+import org.jnp.interfaces.Naming;
+import org.jnp.interfaces.NamingContext;
+import org.jnp.interfaces.NamingParser;
+
+/**
+ *  This class utilizes Infinispan to provide a HA-JNDI implementation.
+ *
+ *  @author Jerry Gauthier
+ *  @author Brian Stansberry
+ *  @author Scott Marlow
+ *  
+ *  @version $Revision$
+ */
+public class DistributedTreeManager
+   implements Naming, org.jboss.ha.jndi.spi.DistributedTreeManager
+{
+   private static final Logger LOG = Logger.getLogger(DistributedTreeManager.class);
+   private static final NamingParser PARSER = new NamingParser();
+   private static final String DEFAULT_ROOT = "__HA_JNDI__";
+   private static final Fqn FQN_ROOT = Fqn.fromString(DEFAULT_ROOT);
+
+   protected volatile TreeCache<String, Binding> m_cache;
+   private volatile InfinispanHAPartitionCacheHandler<String, Binding> cacheHandler;
+   private final Naming haStub;
+   private volatile TreeCacheFactory treeCacheFactory;
+
+
+   public DistributedTreeManager(Naming haStub)
+   {
+      this.haStub = haStub;
+      treeCacheFactory = new DefaultTreeCacheFactory();
+   }
+
+   public  DistributedTreeManager(Naming haStub, TreeCacheFactory factory)
+   {
+      this.haStub = haStub;
+      this.treeCacheFactory = factory;
+   }
+
+   public InfinispanHAPartitionCacheHandler<String, Binding> getCacheHandler()
+   {
+      return cacheHandler;
+   }
+
+   public void setCacheHandler(InfinispanHAPartitionCacheHandler<String, Binding> cacheHandler)
+   {
+      this.cacheHandler = cacheHandler;
+   }
+
+   @Override
+   public void init()
+   {
+      m_cache = treeCacheFactory.createTreeCache(cacheHandler.getCache());
+      LOG.debug("initializing HAJNDITreeCache root");
+   }
+
+
+   @Override
+   public void shutdown()
+   {
+      m_cache = null;
+   }
+
+
+   @Override
+   public Naming getHAStub()
+   {
+      return this.haStub;
+   }
+
+   @Override
+   public void setHAStub(Naming stub)
+   {
+      // TODO:  delete this method from the interface as its ignored (ctor accepts the stub)
+   }
+
+   // Naming implementation -----------------------------------------
+
+   @Override
+   public void bind(Name name, Object obj, String className) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("bind, name="+name);
+      }
+      
+      this.internalBind(name, obj, className, false);
+   }
+
+   @Override
+   public void rebind(Name name, Object obj, String className) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("rebind, name="+name);
+      }
+
+      this.internalBind(name, obj, className, true);
+   }
+
+   @Override   
+   public void unbind(Name name) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("unbind, name="+name);
+      }
+      if (name.isEmpty())
+      {
+         // Empty names are not allowed
+         throw new InvalidNameException("Name is empty");
+      }
+      
+      // is the name a context?
+      try
+      {
+         Fqn temp = Fqn.fromRelativeFqn(FQN_ROOT, Fqn.fromString(name.toString()));
+         // TODO why not jst call remove -- why hasChild first?
+         if (this.m_cache.getRoot().hasChild(temp))
+         {
+            this.m_cache.removeNode(temp);
+            return;
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since Infinispan may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+      
+      int size = name.size();
+      
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key is bound
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      }
+      else
+      {
+         ctx = FQN_ROOT;
+      }
+      
+      try
+      {
+         Object removed = this.m_cache.remove(ctx, key);
+         if (removed == null)
+         {
+            if (!this.m_cache.getRoot().hasChild(ctx))
+            {
+                throw new NotContextException(name.getPrefix(size - 1).toString() + " not a context");
+            }
+
+            throw new NameNotFoundException(key + " not bound");
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   @Override
+   public Object lookup(Name name) throws NamingException
+   {
+      boolean trace = LOG.isTraceEnabled();
+      if (trace)
+      {
+         LOG.trace("lookup, name="+name);
+      }
+   
+      if (name.isEmpty())
+      {
+         // Return this
+         return new NamingContext(null, PARSER.parse(""), this.getHAStub());
+      }
+
+      // is the name a context?
+      try
+      {
+         Node<String, Binding> n = this.m_cache.getRoot().getChild(Fqn.fromRelativeFqn(FQN_ROOT, Fqn.fromString(name.toString())));
+         if (n != null)
+         {
+            Name fullName = (Name) name.clone();
+            return new NamingContext(null, fullName, this.getHAStub());
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since Infinispan may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   
+      int size = name.size();
+   
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key is bound
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      }
+      else
+      {
+         ctx = FQN_ROOT;
+      }
+   
+      try
+      {
+         Binding b = this.m_cache.get(ctx, key);
+         
+         // if key not in cache, return null
+         return (b != null) ? b.getObject() : null;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   @Override
+   public Collection<NameClassPair> list(Name name) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("list, name="+name);
+      }
+   
+      // get the context
+      Fqn ctx;
+      String ctxName = "";
+      int size = name.size();
+      if (size >= 1)
+      {
+         ctxName = name.toString();
+         Fqn fqn = Fqn.fromString(ctxName);
+         ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      }
+      else
+      {
+         ctx = FQN_ROOT;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         try
+         {
+            return Collections.list(new InitialContext().list(name));
+         }
+         catch (NamingException e)
+         {
+            throw new NotContextException(ctxName+ " not a context");
+         }
+      }
+      
+      try
+      {
+         List<NameClassPair> list = new LinkedList<NameClassPair>();
+
+         Node<String, Binding> base = this.m_cache.getRoot().getChild(ctx);
+         if (base != null)
+         {
+            for (Binding b: base.getData().values())
+            {
+               list.add(new NameClassPair(b.getName(),b.getClassName(),true));
+            }
+            
+            // Why doesn't this return Set<String>?
+            Set<Object> children = base.getChildrenNames();
+            if (children != null && !children.isEmpty())
+            {
+               for (Object child: children)
+               {
+                  String node = (String) child;
+                  Name fullName = (Name) name.clone();
+                  fullName.add(node);
+                  list.add(new NameClassPair(node, NamingContext.class.getName(),true));
+               }
+            }
+         }
+         
+         return list;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   @Override
+   public Collection<Binding> listBindings(Name name) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("listBindings, name="+name);
+      }
+      
+      // get the context
+      Fqn ctx;
+      String ctxName = "";
+      int size = name.size();
+      if (size >= 1)
+      {
+         ctxName = name.toString();
+         Fqn fqn = Fqn.fromString(ctxName);
+         ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      }
+      else
+      {
+         ctx = FQN_ROOT;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         // not found in global jndi, look in local.
+         try
+         {
+            return Collections.list(new InitialContext().listBindings(name));
+         }
+         catch (NamingException e)
+         {
+            throw new NotContextException(ctxName+ " not a context");
+         }
+      }
+      
+      try
+      {
+         List<Binding> list = new LinkedList<Binding>();
+         
+         Node<String, Binding> node = this.m_cache.getRoot().getChild(ctx);
+         if (node != null)
+         {
+            Map<String, Binding> data = node.getData();
+            if (data != null && !data.isEmpty())
+            {
+               list.addAll(data.values());
+            }
+            
+            // Why doesn't this return Set<String>?
+            Set<Object> children = node.getChildrenNames();
+            if (children != null && !children.isEmpty())
+            {
+               for (Object obj: children)
+               {
+                  String child = (String) obj;
+                  Name fullName = (Name) name.clone();
+                  fullName.add(child);
+                  NamingContext subCtx = new NamingContext(null, fullName, this.getHAStub());
+                  list.add(new Binding(child, NamingContext.class.getName(), subCtx, true));
+               }
+            }
+         }
+         
+         return list;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since Infinispan may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   @Override
+   public Context createSubcontext(Name name) throws NamingException
+   {
+      if (LOG.isTraceEnabled())
+      {
+         LOG.trace("createSubcontext, name="+name);
+      }
+      
+      int size = name.size();
+      
+      if (size == 0)
+      {
+         throw new InvalidNameException("Name is empty");
+      }
+
+      // does the new context already exist?
+      String str = name.toString();
+      Fqn fqn = Fqn.fromString(str);
+      Fqn ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      if (this.m_cache.getRoot().hasChild(ctx))
+      {
+         throw new NameAlreadyBoundException(str);
+      }
+      
+      // does the prefix context already exist?
+      Fqn pctx;
+      String newctx = name.get(size - 1);
+      if (size > 1) // find subcontext to which the context will be added
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn2 = Fqn.fromString(prefix);
+         pctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn2);
+      }
+      else
+      {
+         pctx = FQN_ROOT;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(pctx);
+      if (!exists)
+      {
+         throw new NotContextException(name.getPrefix(size - 1).toString());
+      }
+
+      Fqn newf = Fqn.fromRelativeFqn(pctx, Fqn.fromString(newctx));
+      try
+      {
+         this.m_cache.put(newf, new HashMap<String, Binding>());
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   
+      Name fullName = PARSER.parse("");
+      fullName.addAll(name);
+      
+      return new NamingContext(null, fullName, this.getHAStub());
+   }
+
+   private void internalBind(Name name, Object obj, String className, boolean rebind) throws NamingException
+   {
+      if (name.isEmpty())
+      {  // Empty names are not allowed
+         throw new InvalidNameException("Name is empty");
+      }
+
+      int size = name.size();
+      
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key will be added
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(FQN_ROOT, fqn);
+      }
+      else
+      {
+         ctx = FQN_ROOT;
+      }
+   
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         throw new NotContextException(name.getPrefix(size - 1).toString() + " not a context");
+         // note - NamingServer throws a CannotProceedException if the client attempts to bind
+         //        to a Reference object having an "nns" address.  This implementation simply
+         //        throws the NotContextException that's used when "nns" isn't present.
+      }
+      if (!rebind)
+      {
+         Node<String, Binding> node = this.m_cache.getRoot().getChild(ctx);
+         if ((node != null) && (node.get(key) != null))
+         {
+            throw new NameAlreadyBoundException(key);
+         }
+      }
+      
+      this.m_cache.put(ctx, key, new Binding(key, className, obj, true));
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl)

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntry.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/AtomicMapEntry.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntry.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,7 +19,7 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.infinispan.atomic.AtomicMap;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/BatchingManagerImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,109 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.TransactionManager;
-
-import org.jboss.logging.Logger;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
-
-/**
- * @author Paul Ferraro
- */
-public class BatchingManagerImpl implements BatchingManager
-{
-   private static final Logger log = Logger.getLogger(BatchingManagerImpl.class);
-   
-   private final TransactionManager tm;
-   
-   public BatchingManagerImpl(TransactionManager tm)
-   {
-      this.tm = tm;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager#isBatchInProgress()
-    */
-   @Override
-   public boolean isBatchInProgress() throws Exception
-   {
-      return this.tm.getTransaction() != null;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager#startBatch()
-    */
-   @Override
-   public void startBatch() throws Exception
-   {
-      this.tm.begin();
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager#setBatchRollbackOnly()
-    */
-   @Override
-   public void setBatchRollbackOnly() throws Exception
-   {
-      this.tm.setRollbackOnly();
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager#endBatch()
-    */
-   @Override
-   public void endBatch()
-   {
-      try
-      {
-         if (this.tm.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK)
-         {
-            this.tm.commit();
-         }
-         else
-         {
-            log.debug("endBatch(): rolling back batch");
-            
-            this.tm.rollback();
-         }
-      }
-      catch (RollbackException e)
-      {
-         // Do nothing here since cache may rollback automatically.
-         log.warn("endBatch(): rolling back transaction with exception", e);
-      }
-      catch (RuntimeException e)
-      {
-         throw e;
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException("endTransaction(): Caught Exception ending batch: ", e);
-      }
-   }
-}

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorage.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/CoarseSessionAttributeStorage.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorage.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,13 +19,14 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.Map;
 
 import org.infinispan.atomic.AtomicMap;
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingSessionGranularitySessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 
 /**
  * Handles session attribute load/store operations for {@link ReplicationGranularity#SESSION} distributed session managers.
@@ -42,7 +43,7 @@
    
    /**
     * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeStorage#store(org.infinispan.atomic.AtomicMap, org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
+    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage#store(org.infinispan.atomic.AtomicMap, org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
     */
    @Override
    public void store(AtomicMap<Object, Object> data, OutgoingSessionGranularitySessionData sessionData)
@@ -57,7 +58,7 @@
 
    /**
     * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeStorage#load(org.infinispan.atomic.AtomicMap)
+    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage#load(org.infinispan.atomic.AtomicMap)
     */
    @SuppressWarnings("unchecked")
    @Override

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManager.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManager.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManager.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,491 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.TransactionManager;
+
+import org.infinispan.Cache;
+import org.infinispan.atomic.AtomicMap;
+import org.infinispan.config.CacheLoaderManagerConfig;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.Flag;
+import org.infinispan.distribution.DistributionManager;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.manager.CacheContainer;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryActivatedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+import org.jboss.ha.ispn.CacheContainerRegistry;
+import org.jboss.ha.ispn.atomic.AtomicMapFactory;
+import org.jboss.ha.ispn.invoker.CacheInvoker;
+import org.jboss.logging.Logger;
+import org.jboss.web.tomcat.service.session.distributedcache.impl.BatchingManagerImpl;
+import org.jboss.web.tomcat.service.session.distributedcache.impl.IncomingDistributableSessionDataImpl;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionOwnershipSupport;
+
+/**
+ * Distributed cache manager implementation using Infinispan.
+ * @author Paul Ferraro
+ */
+ at Listener
+public class DistributedCacheManager<T extends OutgoingDistributableSessionData> implements org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager<T>
+{
+   static String mask(String sessionId)
+   {
+      if (sessionId == null) return null;
+      
+      int length = sessionId.length();
+      
+      if (length <= 8) return sessionId;
+
+      return sessionId.substring(0, 2) + "****" + sessionId.substring(length - 6, length);
+   }
+
+   static RuntimeException getRuntimeException(String message, Exception e)
+   {   
+      if (e instanceof RuntimeException) return (RuntimeException) e;
+      
+      return new RuntimeException(message != null ? message : e.toString(), e);
+   }
+   
+   private static final Logger log = Logger.getLogger(DistributedCacheManager.class);
+   
+   private final LocalDistributableSessionManager manager;
+   private final SessionAttributeStorage<T> attributeStorage;
+   private final CacheInvoker invoker;
+   private final CacheContainerRegistry registry;
+   final AtomicMapFactory atomicMapFactory;
+   
+   private Cache<String, AtomicMap<Object, Object>> cache;
+   private BatchingManagerImpl batchingManager;
+   private boolean passivationEnabled = false;
+   
+   public DistributedCacheManager(LocalDistributableSessionManager manager, CacheContainerRegistry registry, SessionAttributeStorage<T> attributeStorage, CacheInvoker invoker, AtomicMapFactory atomicMapFactory)
+   {
+      this.manager = manager;
+      this.registry = registry;
+      this.attributeStorage = attributeStorage;
+      this.invoker = invoker;
+      this.atomicMapFactory = atomicMapFactory;
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#start()
+    */
+   @Override
+   public void start()
+   {
+      String templateCacheName = this.manager.getReplicationConfig().getCacheName();
+      
+      String containerName = null;
+      
+      if (templateCacheName != null)
+      {
+         String[] parts = templateCacheName.split(":");
+         
+         if (parts.length == 2)
+         {
+            containerName = parts[0];
+            templateCacheName = parts[1];
+         }
+      }
+      
+      CacheContainer container = this.registry.getCacheContainer(containerName);
+      
+      String hostName = this.manager.getHostName();
+      String host = (hostName == null) || hostName.isEmpty() ? "localhost" : hostName;
+      
+      String context = this.manager.getContextName();
+      String path = context.isEmpty() || context.equals("/") ? "ROOT" : context.startsWith("/") ? context.substring(1) : context;
+
+      String cacheName = host + "/" + path;
+      
+      EmbeddedCacheManager manager = (EmbeddedCacheManager) container.getCache().getCacheManager();
+      manager.defineConfiguration(cacheName, templateCacheName, new Configuration());
+      
+      this.cache = manager.getCache(cacheName);
+      
+      if (this.cache.getStatus() != ComponentStatus.RUNNING)
+      {
+         this.cache.start();
+      }
+      
+      TransactionManager tm = this.cache.getAdvancedCache().getTransactionManager();
+      
+      if (!(tm instanceof BatchModeTransactionManager))
+      {
+         throw new IllegalStateException("Unexpected transaction manager type: " + ((tm != null) ? tm.getClass().getName() : "null"));
+      }
+      
+      this.batchingManager = new BatchingManagerImpl(tm);
+      
+      this.cache.addListener(this);
+      
+      CacheLoaderManagerConfig loaderManagerConfig = this.cache.getConfiguration().getCacheLoaderManagerConfig();
+      
+      this.passivationEnabled = (loaderManagerConfig != null) ? loaderManagerConfig.isPassivation().booleanValue() && !loaderManagerConfig.isShared().booleanValue() : false;
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#stop()
+    */
+   @Override
+   public void stop()
+   {
+      this.cache.removeListener(this);
+      
+      this.cache.stop();
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getBatchingManager()
+    */
+   @Override
+   public BatchingManager getBatchingManager()
+   {
+      return this.batchingManager;
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#sessionCreated(java.lang.String)
+    */
+   @Override
+   public void sessionCreated(String sessionId)
+   {
+      // Do nothing
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#storeSessionData(org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
+    */
+   @Override
+   public void storeSessionData(T sessionData)
+   {
+      final String sessionId = sessionData.getRealId();
+      
+      if (log.isTraceEnabled())
+      {
+         log.trace("putSession(): putting session " + mask(sessionId));
+      }     
+      
+      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
+      {
+         @Override
+         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
+         {
+            return DistributedCacheManager.this.atomicMapFactory.getAtomicMap(cache, sessionId, true);
+         }
+      };
+      
+      AtomicMap<Object, Object> data = this.invoker.invoke(this.cache, operation);
+      
+      AtomicMapEntry.VERSION.put(data, Integer.valueOf(sessionData.getVersion()));
+      AtomicMapEntry.METADATA.put(data, sessionData.getMetadata());
+      AtomicMapEntry.TIMESTAMP.put(data, sessionData.getTimestamp());
+      
+      this.attributeStorage.store(data, sessionData);
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionData(java.lang.String, boolean)
+    */
+   @Override
+   public IncomingDistributableSessionData getSessionData(String sessionId, boolean initialLoad)
+   {
+      return this.getData(sessionId, true);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionData(java.lang.String, java.lang.String, boolean)
+    */
+   @Override
+   public IncomingDistributableSessionData getSessionData(final String sessionId, String dataOwner, boolean includeAttributes)
+   {
+      return (dataOwner == null) ? this.getData(sessionId, includeAttributes) : null;
+   }
+   
+   private IncomingDistributableSessionData getData(final String sessionId, boolean includeAttributes)
+   {
+      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
+      {
+         @Override
+         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
+         {
+            return DistributedCacheManager.this.atomicMapFactory.getAtomicMap(cache, sessionId, false);
+         }
+      };
+      
+      AtomicMap<Object, Object> data = this.invoker.invoke(this.cache, operation);
+      
+      // If requested session is no longer in the cache; return null
+      if (data == null) return null;
+      
+      try
+      {
+         Integer version = AtomicMapEntry.VERSION.get(data);
+         Long timestamp = AtomicMapEntry.TIMESTAMP.get(data);
+         DistributableSessionMetadata metadata = AtomicMapEntry.METADATA.get(data);
+         IncomingDistributableSessionDataImpl result = new IncomingDistributableSessionDataImpl(version, timestamp, metadata);
+         
+         if (includeAttributes)
+         {
+            try
+            {
+               result.setSessionAttributes(this.attributeStorage.load(data));
+            }
+            catch (Exception e)
+            {
+               throw getRuntimeException("Failed to load session attributes for session: " + mask(sessionId), e);
+            }
+         }
+
+         return result;
+      }
+      catch (Exception e)
+      {
+         String message = String.format("Problem accessing session [%s]: %s", mask(sessionId), e.toString());
+         log.warn(message);
+         log.debug(message, e);
+         
+         // Clean up
+         this.removeSessionLocal(sessionId);
+         
+         return null;
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSession(java.lang.String)
+    */
+   @Override
+   public void removeSession(final String sessionId)
+   {
+      this.removeSession(sessionId, false);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSessionLocal(java.lang.String)
+    */
+   @Override
+   public void removeSessionLocal(final String sessionId)
+   {
+      this.removeSession(sessionId, true);
+   }
+
+   private void removeSession(final String sessionId, final boolean local)
+   {
+      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
+      {
+         @Override
+         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
+         {
+            if (local)
+            {
+               cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL);
+            }
+            
+            return cache.remove(sessionId);
+         }
+      };
+      
+      this.invoker.invoke(this.cache, operation);
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSessionLocal(java.lang.String, java.lang.String)
+    */
+   @Override
+   public void removeSessionLocal(String sessionId, String dataOwner)
+   {
+      if (dataOwner == null)
+      {
+         this.removeSession(sessionId, true);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#evictSession(java.lang.String)
+    */
+   @Override
+   public void evictSession(final String sessionId)
+   {
+      Operation<Void> operation = new Operation<Void>()
+      {
+         @Override
+         public Void invoke(Cache<String, AtomicMap<Object, Object>> cache)
+         {
+            cache.evict(sessionId);
+            return null;
+         }
+      };
+      
+      this.invoker.invoke(this.cache, operation);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#evictSession(java.lang.String, java.lang.String)
+    */
+   @Override
+   public void evictSession(String sessionId, String dataOwner)
+   {
+      if (dataOwner == null)
+      {
+         this.evictSession(sessionId);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionIds()
+    */
+   @Override
+   public Map<String, String> getSessionIds()
+   {
+      Map<String, String> result = new HashMap<String, String>();
+
+      for (String sessionId: this.cache.keySet())
+      {
+         result.put(sessionId, null);
+      }
+      
+      return result;
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#isPassivationEnabled()
+    */
+   @Override
+   public boolean isPassivationEnabled()
+   {
+      return this.passivationEnabled;
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#setForceSynchronous(boolean)
+    */
+   @Override
+   public void setForceSynchronous(boolean forceSynchronous)
+   {
+      this.invoker.setForceSynchronous(forceSynchronous);
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionOwnershipSupport()
+    */
+   @Override
+   public SessionOwnershipSupport getSessionOwnershipSupport()
+   {
+      return null;
+   }
+   
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#isLocal(java.lang.String)
+    */
+   @Override
+   public boolean isLocal(String realId)
+   {
+      DistributionManager manager = this.cache.getAdvancedCache().getDistributionManager();
+      
+      return (manager != null) ? manager.isLocal(realId) : true;
+   }
+
+   @CacheEntryRemoved
+   public void removed(CacheEntryRemovedEvent event)
+   {
+      if (event.isPre() || event.isOriginLocal()) return;
+      
+      this.manager.notifyRemoteInvalidation((String) event.getKey());
+   }
+   
+   @CacheEntryModified
+   public void modified(CacheEntryModifiedEvent event)
+   {
+      if (event.isPre() || event.isOriginLocal()) return;
+      
+      String sessionId = (String) event.getKey();
+      @SuppressWarnings("unchecked")
+      AtomicMap<Object, Object> data = (AtomicMap<Object, Object>) event.getValue();
+      
+      Integer version = AtomicMapEntry.VERSION.get(data);
+      Long timestamp = AtomicMapEntry.TIMESTAMP.get(data);
+      DistributableSessionMetadata metadata = AtomicMapEntry.METADATA.get(data);
+      
+      if (timestamp == null)
+      {
+         log.warn(String.format("No timestamp attribute found in node modification event for session %s", mask(sessionId)));
+         return;
+      }
+      
+      boolean updated = this.manager.sessionChangedInDistributedCache(sessionId, null, version.intValue(), timestamp.longValue(), metadata);
+      
+      if (!updated)
+      {
+         log.warn(String.format("Possible concurrency problem: Replicated version id %d is less than or equal to in-memory version for session %s", version, mask(sessionId))); 
+      }
+   }
+   
+   @CacheEntryActivated
+   public void activated(CacheEntryActivatedEvent event)
+   {
+      if (event.isPre()) return;
+      
+      if (this.manager.isPassivationEnabled())
+      {
+         this.manager.sessionActivated();
+      }
+   }
+   
+   // Simplified CacheInvoker.Operation using assigned key/value types
+   static interface Operation<R> extends CacheInvoker.Operation<String, AtomicMap<Object, Object>, R>
+   {      
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactory.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerFactoryImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactory.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactory.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
+
+import org.jboss.ha.ispn.CacheContainerRegistry;
+import org.jboss.ha.ispn.DefaultCacheContainerRegistry;
+import org.jboss.ha.ispn.atomic.AtomicMapFactory;
+import org.jboss.ha.ispn.atomic.DefaultAtomicMapFactory;
+import org.jboss.ha.ispn.invoker.CacheInvoker;
+import org.jboss.ha.ispn.invoker.RetryingCacheInvoker;
+import org.jboss.web.tomcat.service.session.distributedcache.impl.SessionAttributeMarshallerFactoryImpl;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshallerFactory;
+
+/**
+ * Factory for creating an Infinispan-backed distributed cache manager.
+ * @author Paul Ferraro
+ */
+public class DistributedCacheManagerFactory implements org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManagerFactory
+{
+   private CacheContainerRegistry registry = DefaultCacheContainerRegistry.getInstance();
+   private SessionAttributeStorageFactory storageFactory = new SessionAttributeStorageFactoryImpl();
+   private SessionAttributeMarshallerFactory marshallerFactory = new SessionAttributeMarshallerFactoryImpl();
+   private CacheInvoker invoker = new RetryingCacheInvoker(10, 100);
+   private AtomicMapFactory atomicMapFactory = new DefaultAtomicMapFactory();
+   
+   @Override
+   public <T extends OutgoingDistributableSessionData> org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager<T> getDistributedCacheManager(LocalDistributableSessionManager manager)
+   {
+      SessionAttributeMarshaller marshaller = this.marshallerFactory.createMarshaller(manager);
+      SessionAttributeStorage<T> storage = this.storageFactory.createStorage(manager.getReplicationConfig().getReplicationGranularity(), marshaller);
+      
+      return new DistributedCacheManager<T>(manager, this.registry, storage, this.invoker, this.atomicMapFactory);
+   }
+   
+   public void setCacheContainerRegistry(CacheContainerRegistry registry)
+   {
+      this.registry = registry;
+   }
+   
+   public void setSessionAttributeStorageFactory(SessionAttributeStorageFactory storageFactory)
+   {
+      this.storageFactory = storageFactory;
+   }
+   
+   public void setSessionAttributeMarshallerFactory(SessionAttributeMarshallerFactory marshallerFactory)
+   {
+      this.marshallerFactory = marshallerFactory;
+   }
+   
+   public void setCacheInvoker(CacheInvoker invoker)
+   {
+      this.invoker = invoker;
+   }
+   
+   public void setAtomicMapFactory(AtomicMapFactory atomicMapFactory)
+   {
+      this.atomicMapFactory = atomicMapFactory;
+   }
+}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerFactoryImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,80 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import org.jboss.ha.ispn.CacheContainerRegistry;
-import org.jboss.ha.ispn.DefaultCacheContainerRegistry;
-import org.jboss.ha.ispn.atomic.AtomicMapFactory;
-import org.jboss.ha.ispn.atomic.DefaultAtomicMapFactory;
-import org.jboss.ha.ispn.invoker.CacheInvoker;
-import org.jboss.ha.ispn.invoker.RetryingCacheInvoker;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManagerFactory;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
-
-/**
- * Factory for creating an Infinispan-backed distributed cache manager.
- * @author Paul Ferraro
- */
-public class DistributedCacheManagerFactoryImpl implements DistributedCacheManagerFactory
-{
-   private CacheContainerRegistry registry = DefaultCacheContainerRegistry.getInstance();
-   private SessionAttributeStorageFactory storageFactory = new SessionAttributeStorageFactoryImpl();
-   private SessionAttributeMarshallerFactory marshallerFactory = new SessionAttributeMarshallerFactoryImpl();
-   private CacheInvoker invoker = new RetryingCacheInvoker(10, 100);
-   private AtomicMapFactory atomicMapFactory = new DefaultAtomicMapFactory();
-   
-   @Override
-   public <T extends OutgoingDistributableSessionData> DistributedCacheManager<T> getDistributedCacheManager(LocalDistributableSessionManager manager)
-   {
-      SessionAttributeMarshaller marshaller = this.marshallerFactory.createMarshaller(manager);
-      SessionAttributeStorage<T> storage = this.storageFactory.createStorage(manager.getReplicationConfig().getReplicationGranularity(), marshaller);
-      
-      return new DistributedCacheManagerImpl<T>(manager, this.registry, storage, this.invoker, this.atomicMapFactory);
-   }
-   
-   public void setCacheContainerRegistry(CacheContainerRegistry registry)
-   {
-      this.registry = registry;
-   }
-   
-   public void setSessionAttributeStorageFactory(SessionAttributeStorageFactory storageFactory)
-   {
-      this.storageFactory = storageFactory;
-   }
-   
-   public void setSessionAttributeMarshallerFactory(SessionAttributeMarshallerFactory marshallerFactory)
-   {
-      this.marshallerFactory = marshallerFactory;
-   }
-   
-   public void setCacheInvoker(CacheInvoker invoker)
-   {
-      this.invoker = invoker;
-   }
-   
-   public void setAtomicMapFactory(AtomicMapFactory atomicMapFactory)
-   {
-      this.atomicMapFactory = atomicMapFactory;
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,490 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.transaction.TransactionManager;
-
-import org.infinispan.Cache;
-import org.infinispan.atomic.AtomicMap;
-import org.infinispan.config.CacheLoaderManagerConfig;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.Flag;
-import org.infinispan.distribution.DistributionManager;
-import org.infinispan.lifecycle.ComponentStatus;
-import org.infinispan.manager.CacheContainer;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.notifications.Listener;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryActivated;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
-import org.infinispan.notifications.cachelistener.event.CacheEntryActivatedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
-import org.infinispan.transaction.tm.BatchModeTransactionManager;
-import org.jboss.ha.ispn.CacheContainerRegistry;
-import org.jboss.ha.ispn.atomic.AtomicMapFactory;
-import org.jboss.ha.ispn.invoker.CacheInvoker;
-import org.jboss.logging.Logger;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionOwnershipSupport;
-
-/**
- * Distributed cache manager implementation using Infinispan.
- * @author Paul Ferraro
- */
- at Listener
-public class DistributedCacheManagerImpl<T extends OutgoingDistributableSessionData> implements DistributedCacheManager<T>
-{
-   static String mask(String sessionId)
-   {
-      if (sessionId == null) return null;
-      
-      int length = sessionId.length();
-      
-      if (length <= 8) return sessionId;
-
-      return sessionId.substring(0, 2) + "****" + sessionId.substring(length - 6, length);
-   }
-
-   static RuntimeException getRuntimeException(String message, Exception e)
-   {   
-      if (e instanceof RuntimeException) return (RuntimeException) e;
-      
-      return new RuntimeException(message != null ? message : e.toString(), e);
-   }
-   
-   private static final Logger log = Logger.getLogger(DistributedCacheManagerImpl.class);
-   
-   private final LocalDistributableSessionManager manager;
-   private final SessionAttributeStorage<T> attributeStorage;
-   private final CacheInvoker invoker;
-   private final CacheContainerRegistry registry;
-   final AtomicMapFactory atomicMapFactory;
-   
-   private Cache<String, AtomicMap<Object, Object>> cache;
-   private BatchingManager batchingManager;
-   private boolean passivationEnabled = false;
-   
-   public DistributedCacheManagerImpl(LocalDistributableSessionManager manager, CacheContainerRegistry registry, SessionAttributeStorage<T> attributeStorage, CacheInvoker invoker, AtomicMapFactory atomicMapFactory)
-   {
-      this.manager = manager;
-      this.registry = registry;
-      this.attributeStorage = attributeStorage;
-      this.invoker = invoker;
-      this.atomicMapFactory = atomicMapFactory;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#start()
-    */
-   @Override
-   public void start()
-   {
-      String templateCacheName = this.manager.getReplicationConfig().getCacheName();
-      
-      String containerName = null;
-      
-      if (templateCacheName != null)
-      {
-         String[] parts = templateCacheName.split(":");
-         
-         if (parts.length == 2)
-         {
-            containerName = parts[0];
-            templateCacheName = parts[1];
-         }
-      }
-      
-      CacheContainer container = this.registry.getCacheContainer(containerName);
-      
-      String hostName = this.manager.getHostName();
-      String host = (hostName == null) || hostName.isEmpty() ? "localhost" : hostName;
-      
-      String context = this.manager.getContextName();
-      String path = context.isEmpty() || context.equals("/") ? "ROOT" : context.startsWith("/") ? context.substring(1) : context;
-
-      String cacheName = host + "/" + path;
-      
-      EmbeddedCacheManager manager = (EmbeddedCacheManager) container.getCache().getCacheManager();
-      manager.defineConfiguration(cacheName, templateCacheName, new Configuration());
-      
-      this.cache = manager.getCache(cacheName);
-      
-      if (this.cache.getStatus() != ComponentStatus.RUNNING)
-      {
-         this.cache.start();
-      }
-      
-      TransactionManager tm = this.cache.getAdvancedCache().getTransactionManager();
-      
-      if (!(tm instanceof BatchModeTransactionManager))
-      {
-         throw new IllegalStateException("Unexpected transaction manager type: " + ((tm != null) ? tm.getClass().getName() : "null"));
-      }
-      
-      this.batchingManager = new BatchingManagerImpl(tm);
-      
-      this.cache.addListener(this);
-      
-      CacheLoaderManagerConfig loaderManagerConfig = this.cache.getConfiguration().getCacheLoaderManagerConfig();
-      
-      this.passivationEnabled = (loaderManagerConfig != null) ? loaderManagerConfig.isPassivation().booleanValue() && !loaderManagerConfig.isShared().booleanValue() : false;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#stop()
-    */
-   @Override
-   public void stop()
-   {
-      this.cache.removeListener(this);
-      
-      this.cache.stop();
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getBatchingManager()
-    */
-   @Override
-   public BatchingManager getBatchingManager()
-   {
-      return this.batchingManager;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#sessionCreated(java.lang.String)
-    */
-   @Override
-   public void sessionCreated(String sessionId)
-   {
-      // Do nothing
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#storeSessionData(org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
-    */
-   @Override
-   public void storeSessionData(T sessionData)
-   {
-      final String sessionId = sessionData.getRealId();
-      
-      if (log.isTraceEnabled())
-      {
-         log.trace("putSession(): putting session " + mask(sessionId));
-      }     
-      
-      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
-      {
-         @Override
-         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
-         {
-            return DistributedCacheManagerImpl.this.atomicMapFactory.getAtomicMap(cache, sessionId, true);
-         }
-      };
-      
-      AtomicMap<Object, Object> data = this.invoker.invoke(this.cache, operation);
-      
-      AtomicMapEntry.VERSION.put(data, Integer.valueOf(sessionData.getVersion()));
-      AtomicMapEntry.METADATA.put(data, sessionData.getMetadata());
-      AtomicMapEntry.TIMESTAMP.put(data, sessionData.getTimestamp());
-      
-      this.attributeStorage.store(data, sessionData);
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionData(java.lang.String, boolean)
-    */
-   @Override
-   public IncomingDistributableSessionData getSessionData(String sessionId, boolean initialLoad)
-   {
-      return this.getData(sessionId, true);
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionData(java.lang.String, java.lang.String, boolean)
-    */
-   @Override
-   public IncomingDistributableSessionData getSessionData(final String sessionId, String dataOwner, boolean includeAttributes)
-   {
-      return (dataOwner == null) ? this.getData(sessionId, includeAttributes) : null;
-   }
-   
-   private IncomingDistributableSessionData getData(final String sessionId, boolean includeAttributes)
-   {
-      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
-      {
-         @Override
-         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
-         {
-            return DistributedCacheManagerImpl.this.atomicMapFactory.getAtomicMap(cache, sessionId, false);
-         }
-      };
-      
-      AtomicMap<Object, Object> data = this.invoker.invoke(this.cache, operation);
-      
-      // If requested session is no longer in the cache; return null
-      if (data == null) return null;
-      
-      try
-      {
-         Integer version = AtomicMapEntry.VERSION.get(data);
-         Long timestamp = AtomicMapEntry.TIMESTAMP.get(data);
-         DistributableSessionMetadata metadata = AtomicMapEntry.METADATA.get(data);
-         IncomingDistributableSessionDataImpl result = new IncomingDistributableSessionDataImpl(version, timestamp, metadata);
-         
-         if (includeAttributes)
-         {
-            try
-            {
-               result.setSessionAttributes(this.attributeStorage.load(data));
-            }
-            catch (Exception e)
-            {
-               throw getRuntimeException("Failed to load session attributes for session: " + mask(sessionId), e);
-            }
-         }
-
-         return result;
-      }
-      catch (Exception e)
-      {
-         String message = String.format("Problem accessing session [%s]: %s", mask(sessionId), e.toString());
-         log.warn(message);
-         log.debug(message, e);
-         
-         // Clean up
-         this.removeSessionLocal(sessionId);
-         
-         return null;
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSession(java.lang.String)
-    */
-   @Override
-   public void removeSession(final String sessionId)
-   {
-      this.removeSession(sessionId, false);
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSessionLocal(java.lang.String)
-    */
-   @Override
-   public void removeSessionLocal(final String sessionId)
-   {
-      this.removeSession(sessionId, true);
-   }
-
-   private void removeSession(final String sessionId, final boolean local)
-   {
-      Operation<AtomicMap<Object, Object>> operation = new Operation<AtomicMap<Object, Object>>()
-      {
-         @Override
-         public AtomicMap<Object, Object> invoke(Cache<String, AtomicMap<Object, Object>> cache)
-         {
-            if (local)
-            {
-               cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL);
-            }
-            
-            return cache.remove(sessionId);
-         }
-      };
-      
-      this.invoker.invoke(this.cache, operation);
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#removeSessionLocal(java.lang.String, java.lang.String)
-    */
-   @Override
-   public void removeSessionLocal(String sessionId, String dataOwner)
-   {
-      if (dataOwner == null)
-      {
-         this.removeSession(sessionId, true);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#evictSession(java.lang.String)
-    */
-   @Override
-   public void evictSession(final String sessionId)
-   {
-      Operation<Void> operation = new Operation<Void>()
-      {
-         @Override
-         public Void invoke(Cache<String, AtomicMap<Object, Object>> cache)
-         {
-            cache.evict(sessionId);
-            return null;
-         }
-      };
-      
-      this.invoker.invoke(this.cache, operation);
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#evictSession(java.lang.String, java.lang.String)
-    */
-   @Override
-   public void evictSession(String sessionId, String dataOwner)
-   {
-      if (dataOwner == null)
-      {
-         this.evictSession(sessionId);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionIds()
-    */
-   @Override
-   public Map<String, String> getSessionIds()
-   {
-      Map<String, String> result = new HashMap<String, String>();
-
-      for (String sessionId: this.cache.keySet())
-      {
-         result.put(sessionId, null);
-      }
-      
-      return result;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#isPassivationEnabled()
-    */
-   @Override
-   public boolean isPassivationEnabled()
-   {
-      return this.passivationEnabled;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#setForceSynchronous(boolean)
-    */
-   @Override
-   public void setForceSynchronous(boolean forceSynchronous)
-   {
-      this.invoker.setForceSynchronous(forceSynchronous);
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#getSessionOwnershipSupport()
-    */
-   @Override
-   public SessionOwnershipSupport getSessionOwnershipSupport()
-   {
-      return null;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager#isLocal(java.lang.String)
-    */
-   @Override
-   public boolean isLocal(String realId)
-   {
-      DistributionManager manager = this.cache.getAdvancedCache().getDistributionManager();
-      
-      return (manager != null) ? manager.isLocal(realId) : true;
-   }
-
-   @CacheEntryRemoved
-   public void removed(CacheEntryRemovedEvent event)
-   {
-      if (event.isPre() || event.isOriginLocal()) return;
-      
-      this.manager.notifyRemoteInvalidation((String) event.getKey());
-   }
-   
-   @CacheEntryModified
-   public void modified(CacheEntryModifiedEvent event)
-   {
-      if (event.isPre() || event.isOriginLocal()) return;
-      
-      String sessionId = (String) event.getKey();
-      @SuppressWarnings("unchecked")
-      AtomicMap<Object, Object> data = (AtomicMap<Object, Object>) event.getValue();
-      
-      Integer version = AtomicMapEntry.VERSION.get(data);
-      Long timestamp = AtomicMapEntry.TIMESTAMP.get(data);
-      DistributableSessionMetadata metadata = AtomicMapEntry.METADATA.get(data);
-      
-      if (timestamp == null)
-      {
-         log.warn(String.format("No timestamp attribute found in node modification event for session %s", mask(sessionId)));
-         return;
-      }
-      
-      boolean updated = this.manager.sessionChangedInDistributedCache(sessionId, null, version.intValue(), timestamp.longValue(), metadata);
-      
-      if (!updated)
-      {
-         log.warn(String.format("Possible concurrency problem: Replicated version id %d is less than or equal to in-memory version for session %s", version, mask(sessionId))); 
-      }
-   }
-   
-   @CacheEntryActivated
-   public void activated(CacheEntryActivatedEvent event)
-   {
-      if (event.isPre()) return;
-      
-      if (this.manager.isPassivationEnabled())
-      {
-         this.manager.sessionActivated();
-      }
-   }
-   
-   // Simplified CacheInvoker.Operation using assigned key/value types
-   static interface Operation<R> extends CacheInvoker.Operation<String, AtomicMap<Object, Object>, R>
-   {      
-   }
-}

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorage.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/FineSessionAttributeStorage.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorage.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,7 +19,7 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -28,6 +28,7 @@
 import org.infinispan.atomic.AtomicMap;
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingAttributeGranularitySessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 
 /**
  * Handles session attribute load/store operations for {@link ReplicationGranularity#ATTRIBUTE} distributed session managers.
@@ -44,7 +45,7 @@
    
    /**
     * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeStorage#store(org.infinispan.atomic.AtomicMap, org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
+    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage#store(org.infinispan.atomic.AtomicMap, org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData)
     */
    @Override
    public void store(AtomicMap<Object, Object> data, OutgoingAttributeGranularitySessionData sessionData)
@@ -72,7 +73,7 @@
 
    /**
     * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeStorage#load(org.infinispan.atomic.AtomicMap)
+    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage#load(org.infinispan.atomic.AtomicMap)
     */
    @Override
    public Map<String, Object> load(AtomicMap<Object, Object> data) throws Exception

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/IncomingDistributableSessionDataImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/IncomingDistributableSessionDataImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/IncomingDistributableSessionDataImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,116 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import java.util.Map;
-
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
-
-/**
- * Base implementation of {@link DistributableSessionData}.
- * 
- * @author Brian Stansberry
- */
-public class IncomingDistributableSessionDataImpl implements IncomingDistributableSessionData
-{
-   private final int version;
-   private final long timestamp;
-   private final DistributableSessionMetadata metadata;
-   private volatile Map<String, Object> attributes;
-   
-   public IncomingDistributableSessionDataImpl(Integer version, Long timestamp, DistributableSessionMetadata metadata)
-   {
-      assert version != null : "version is null";
-      assert timestamp != null : "timestamp is null";
-      assert metadata != null : "metadata is null";
-      
-      this.version = version.intValue();
-      this.timestamp = timestamp.longValue();
-      this.metadata = metadata;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData#providesSessionAttributes()
-    */
-   @Override
-   public boolean providesSessionAttributes()
-   {
-      return this.attributes != null;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData#getSessionAttributes()
-    */
-   @Override
-   public Map<String, Object> getSessionAttributes()
-   {
-      if (this.attributes == null)
-      {
-         throw new IllegalStateException("Not configured to provide session attributes");
-      }
-      
-      return attributes;
-   }   
-
-   /**
-    * Sets the session attributes.
-    * @param attributes a map of session attributes
-    */
-   public void setSessionAttributes(Map<String, Object> attributes)
-   {
-      this.attributes = attributes;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData#getMetadata()
-    */
-   @Override
-   public DistributableSessionMetadata getMetadata()
-   {
-      return metadata;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData#getTimestamp()
-    */
-   @Override
-   public long getTimestamp()
-   {
-      return timestamp;
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData#getVersion()
-    */
-   @Override
-   public int getVersion()
-   {
-      return version;
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshaller.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshaller.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshaller.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,35 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import java.io.IOException;
-
-/**
- * @author Paul Ferraro
- *
- */
-public interface SessionAttributeMarshaller
-{
-   Object marshal(Object object);
-   
-   Object unmarshal(Object object) throws IOException, ClassNotFoundException;
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactory.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshallerFactory.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactory.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-
-/**
- * Factory for creating session attribute marshallers.
- * @author Paul Ferraro
- */
-public interface SessionAttributeMarshallerFactory
-{
-   /**
-    * Create a session attribute marshaller using the specified distributable session manager.
-    * @param manager a distributable session manager
-    * @return a session attribute marshaller
-    */
-   SessionAttributeMarshaller createMarshaller(LocalDistributableSessionManager manager);
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshallerFactoryImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,55 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import org.jboss.ha.framework.interfaces.ObjectStreamSource;
-import org.jboss.ha.framework.server.MarshalledValueObjectStreamSource;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-
-/**
- * Default factory for creating session attribute marshallers.
- * @author Paul Ferraro
- */
-public class SessionAttributeMarshallerFactoryImpl implements SessionAttributeMarshallerFactory
-{
-   private final ObjectStreamSource source;
-   
-   public SessionAttributeMarshallerFactoryImpl()
-   {
-      this(new MarshalledValueObjectStreamSource());
-   }
-   
-   public SessionAttributeMarshallerFactoryImpl(ObjectStreamSource source)
-   {
-      this.source = source;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeMarshallerFactory#createMarshaller(org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager)
-    */
-   @Override
-   public SessionAttributeMarshaller createMarshaller(LocalDistributableSessionManager manager)
-   {
-      return new SessionAttributeMarshallerImpl(manager, this.source);
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshallerImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,95 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.security.AccessController;
-
-import org.jboss.ha.framework.interfaces.ObjectStreamSource;
-import org.jboss.ha.framework.server.MarshalledValueHelper;
-import org.jboss.ha.framework.server.SimpleCachableMarshalledValue;
-import org.jboss.util.loading.ContextClassLoaderSwitcher;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-
-/**
- * Session attribute marshaller that marshals attribute values using a {@link SimpleCachableMarshalledValue}.
- * @author Paul Ferraro
- */
-public class SessionAttributeMarshallerImpl implements SessionAttributeMarshaller
-{
-   @SuppressWarnings("unchecked")
-   // Need to cast since ContextClassLoaderSwitcher.NewInstance does not generically implement PrivilegedAction<ContextClassLoaderSwitcher>
-   private final ContextClassLoaderSwitcher switcher = (ContextClassLoaderSwitcher) AccessController.doPrivileged(ContextClassLoaderSwitcher.INSTANTIATOR);
-   
-   private final LocalDistributableSessionManager manager;
-   private final ObjectStreamSource source;
-   
-   public SessionAttributeMarshallerImpl(LocalDistributableSessionManager manager, ObjectStreamSource source)
-   {
-      this.manager = manager;
-      this.source = source;
-   }
-   
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeMarshaller#marshal(java.lang.Object)
-    */
-   @Override
-   public Object marshal(Object value)
-   {
-      if ((value == null) || MarshalledValueHelper.isTypeExcluded(value.getClass())) return value;
-
-      if (!(value instanceof Serializable))
-      {
-         throw new IllegalArgumentException(String.format("%s does not implement %s", value, Serializable.class.getName()));
-      }
-      
-      return new SimpleCachableMarshalledValue((Serializable) value, this.source, true);
-   }
-
-   /**
-    * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeMarshaller#unmarshal(java.lang.Object)
-    */
-   @Override
-   public Object unmarshal(Object object) throws IOException, ClassNotFoundException
-   {
-      if ((object == null) || !(object instanceof SimpleCachableMarshalledValue)) return object;
-
-      SimpleCachableMarshalledValue value = (SimpleCachableMarshalledValue) object;
-      
-      // Swap in/out the class loader for this web app. Needed only for unmarshalling.
-      ContextClassLoaderSwitcher.SwitchContext switchContext = this.switcher.getSwitchContext(this.manager.getApplicationClassLoader());
-      
-      try
-      {
-         value.setObjectStreamSource(this.source);
-         
-         return value.get();
-      }
-      finally
-      {
-         switchContext.reset();
-      }
-   }
-}

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorage.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeStorage.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorage.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,7 +19,7 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.Map;
 

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactory.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeStorageFactory.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactory.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,10 +19,11 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 
 /**
  * Factory for creating strategies for storing session attributes.

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeStorageFactoryImpl.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,10 +19,11 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 
 /**
  * Default factory for creating strategies for storing session attributes.
@@ -32,7 +33,7 @@
 {
    /**
     * {@inheritDoc}
-    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeStorageFactory#createStorage(org.jboss.metadata.web.jboss.ReplicationGranularity, org.jboss.ha.web.tomcat.service.session.distributedcache.impl.SessionAttributeMarshaller)
+    * @see org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorageFactory#createStorage(org.jboss.metadata.web.jboss.ReplicationGranularity, org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller)
     */
    @SuppressWarnings("unchecked")
    @Override

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/CacheKey.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/CacheKey.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/CacheKey.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,73 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2010, 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.jboss.ha.web.tomcat.service.session.sso;
-
-/**
- * Used to represent the different types of entries in the cache store.
- *
- * Note that we purposely do not implement equals, which allows many different
- * entries with the same key to be added.
- *
- */
-public class CacheKey
-{
-   public static enum Type { SESSION, CREDENTIAL }
-
-   private final String ssoId;
-   private final Type type;
-
-   public CacheKey(String ssoId, Type type)
-   {
-      this.ssoId = ssoId;
-      this.type = type;
-   }
-
-   public String getSSOID()
-   {
-      return this.ssoId;
-   }
-
-   public Type getType()
-   {
-      return this.type;
-   }
-
-   @Override
-   public int hashCode()
-   {
-      int result = 17;
-      result = 37*result + this.ssoId.hashCode();
-      result = 37*result + this.type.ordinal();
-      return result;
-   }
-   
-   @Override
-   public boolean equals(Object object)
-   {
-      if ((object == null) || !(object instanceof CacheKey)) return false;
-      
-      CacheKey key = (CacheKey) object;
-      
-      return (this.type == key.type) && this.ssoId.equals(key.ssoId);
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerImpl.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerImpl.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,1152 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2010, 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.jboss.ha.web.tomcat.service.session.sso;
-
-import org.infinispan.atomic.AtomicMap;
-import org.infinispan.atomic.AtomicMapLookup;
-import org.infinispan.config.Configuration;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
-import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
-import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
-import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged;
-import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent;
-import org.infinispan.Cache;
-import org.infinispan.remoting.transport.Address;
-import org.jboss.ha.framework.server.InfinispanHAPartitionCacheHandler;
-import org.jboss.logging.Logger;
-import org.jboss.util.threadpool.ThreadPool;
-import org.jboss.web.tomcat.service.sso.spi.FullyQualifiedSessionId;
-import org.jboss.web.tomcat.service.sso.spi.SSOClusterManager;
-import org.jboss.web.tomcat.service.sso.spi.SSOCredentials;
-import org.jboss.web.tomcat.service.sso.spi.SSOLocalManager;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.transaction.Status;
-import javax.transaction.TransactionManager;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * An implementation of SSOClusterManager that uses a Infinispan cache
- * to share SSO information between cluster nodes.
- *
- * @author Brian E. Stansberry
- * @author Scott Marlow
- * @version $Revision$ $Date: 2007-01-12 03:39:24 +0100 (ven., 12 janv. 2007) $
- */
-// @Listener
-public final class SSOClusterManagerImpl
-   implements SSOClusterManager
-{
-   // -------------------------------------------------------------  Constants
-
-
-   /**
-    * Default global value for the threadPoolName property
-    */
-   public static final String DEFAULT_THREAD_POOL_NAME =
-      "jboss.system:service=ThreadPool";
-
-   // -------------------------------------------------------  Instance Fields
-
-   /**
-    * SSO id which the thread is currently storing to the cache
-    */
-   private volatile ThreadLocal<String> beingLocallyAdded = new ThreadLocal<String>();
-
-   /**
-    * SSO id which a thread is currently removing from the cache
-    */
-   private volatile ThreadLocal<String> beingLocallyRemoved = new ThreadLocal<String>();
-
-   /**
-    * SSO id which the thread is deregistering due to removal on another node
-    */
-   private volatile ThreadLocal<String> beingRemotelyRemoved = new ThreadLocal<String>();
-
-   /**
-    * The clustered cache that holds the SSO credentials and the sessions.
-    * The CacheKey will indicate which type it is (CacheKey.CREDENTIAL or CacheKey.SESSION);
-    */
-   private volatile Cache<CacheKey, Object> cache = null;
-
-   /**
-    * Transaction Manager
-    */
-   private volatile TransactionManager tm = null;
-
-   private volatile String threadPoolName = DEFAULT_THREAD_POOL_NAME;
-
-   private volatile ThreadPool threadPool;
-
-   /**
-    * The Log-object for this class
-    */
-   private static final Logger log = Logger.getLogger(SSOClusterManagerImpl.class);;
-
-   /**
-    * Whether we are registered as a CacheListener anywhere
-    */
-   private volatile boolean registeredAsListener = false;
-
-   /**
-    * The MBean server we use to access external components (TODO: convert to injection)
-    */
-   private volatile MBeanServer server = null;
-
-   /**
-    * The SingleSignOn for which we are providing cluster support
-    */
-   private volatile SSOLocalManager ssoValve = null;
-
-   /**
-    * Whether we have been started
-    */
-   private volatile boolean started = false;
-
-   /**
-    * Whether we have logged an error due to not having a valid cache
-    */
-   private volatile boolean missingCacheErrorLogged = false;
-
-   /**
-    * Our node's address in the cluster.
-    */
-   private volatile Object localAddress = null;
-
-   /**
-    * The new members of the last view passed to viewChange()
-    */
-   private final Set<Object> currentView = new HashSet<Object>();;
-
-   /** Mutex lock to ensure only one view change at a time is being processed */
-   private final Object cleanupMutex = new Object();
-
-   private volatile InfinispanHAPartitionCacheHandler<CacheKey, Object> cacheHandler;
-
-   // ------------------------------------------------------------  Properties
-
-   public InfinispanHAPartitionCacheHandler getCacheHandler()
-   {
-      return cacheHandler;
-   }
-
-   public void setCacheHandler(InfinispanHAPartitionCacheHandler cacheHandler)
-   {
-      this.cacheHandler = cacheHandler;
-   }
-
-   public String getThreadPoolName()
-   {
-      return threadPoolName;
-   }
-
-   public boolean isUsingThreadPool()
-   {
-      return threadPool != null;
-   }
-
-   // -----------------------------------------------------  SSOClusterManager
-
-   /**
-    * Notify the cluster of the addition of a Session to an SSO session.
-    *
-    * @param ssoId   the id of the SSO session
-    * @param sessionId id of the Session that has been added
-    */
-   public void addSession(String ssoId, FullyQualifiedSessionId sessionId)
-   {
-      if (ssoId == null || sessionId == null)
-      {
-         return;
-      }
-
-      if (!isCacheAvailable())
-      {
-         return;
-      }
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("addSession(): adding Session " + sessionId.getSessionId() +
-            " to cached session set for SSO " + ssoId);
-      }
-
-      boolean doTx = false;
-      try
-      {
-         // Confirm we have a transaction manager; if not get it from Cache
-         // failure to find will throw an IllegalStateException
-         if (tm == null)
-            configureFromCache();
-
-         // Don't do anything if there is already a transaction
-         // context associated with this thread.
-         if(tm.getTransaction() == null)
-            doTx = true;
-
-         if(doTx)
-            tm.begin();
-
-         putSessionInCache(ssoId, sessionId);
-      }
-      catch (Exception e)
-      {
-         try
-         {
-            if(doTx)
-               tm.setRollbackOnly();
-         }
-         catch (Exception ignored)
-         {
-         }
-         log.error("caught exception adding session " + sessionId.getSessionId() +
-            " to SSO id " + ssoId, e);
-      }
-      finally
-      {
-         if (doTx)
-            endTransaction();
-      }
-   }
-
-
-   /**
-    * Gets the SingleSignOn valve for which this object is handling
-    * cluster communications.
-    *
-    * @return the <code>SingleSignOn</code> valve.
-    */
-   public SSOLocalManager getSSOLocalManager()
-   {
-      return ssoValve;
-   }
-
-
-   /**
-    * Sets the SingleSignOn valve for which this object is handling
-    * cluster communications.
-    * <p><b>NOTE:</b> This method must be called before calls can be
-    * made to the other methods of this interface.
-    *
-    * @param localManager a <code>SingleSignOn</code> valve.
-    */
-   public void setSSOLocalManager(SSOLocalManager localManager)
-   {
-      ssoValve = localManager;
-      if (ssoValve != null)
-      {
-         if (server == null)
-         {
-            server = ssoValve.getMBeanServer();
-         }
-         String poolName = ssoValve.getThreadPoolName();
-         if (poolName != null)
-         {
-            threadPoolName = poolName;
-         }
-      }
-   }
-
-
-   /**
-    * Notifies the cluster that a single sign on session has been terminated
-    * due to a user logout.
-    *
-    * @param ssoId
-    */
-   public void logout(String ssoId)
-   {
-      if (!isCacheAvailable())
-      {
-         return;
-      }
-
-      // Check whether we are already handling this removal
-      if (ssoId.equals(beingLocallyRemoved.get()))
-      {
-         return;
-      }
-
-      // Add this SSO to our list of in-process local removals so
-      // this.nodeRemoved() will ignore the removal
-      beingLocallyRemoved.set(ssoId);
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("Registering logout of SSO " + ssoId +
-            " in clustered cache");
-      }
-
-      try
-      {
-         removeSSOFromCache(ssoId);
-      }
-      catch (Exception e)
-      {
-         log.error("Exception attempting to logout " +
-            ssoId, e);
-      }
-      finally
-      {
-         beingLocallyRemoved.set(null);
-      }
-   }
-
-
-   public SSOCredentials lookup(String ssoId)
-   {
-      if (!isCacheAvailable())
-      {
-         return null;
-      }
-
-      SSOCredentials credentials = null;
-      // Find the latest credential info from the cluster
-      try
-      {
-         credentials = getCredentialsFromCache(ssoId);
-      }
-      catch (Exception e)
-      {
-         log.error("caught exception looking up SSOCredentials for SSO id " +
-            ssoId, e);
-      }
-      return credentials;
-   }
-
-
-   /**
-    * Notifies the cluster of the creation of a new SSO entry.
-    *
-    * @param ssoId    the id of the SSO session
-    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
-    *                 or FORM) used to authenticate the SSO.
-    * @param username the username (if any) used for the authentication
-    * @param password the password (if any) used for the authentication
-    */
-   public void register(String ssoId, String authType,
-      String username, String password)
-   {
-      if (!isCacheAvailable())
-      {
-         return;
-      }
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("Registering SSO " + ssoId + " in clustered cache");
-      }
-
-      storeCredentials(ssoId, authType, username, password);
-   }
-
-
-   /**
-    * Notify the cluster of the removal of a Session from an SSO session.
-    *
-    * @param ssoId   the id of the SSO session
-    * @param sessionId id of the Session that has been removed
-    */
-   public void removeSession(String ssoId, FullyQualifiedSessionId sessionId)
-   {
-      if (ssoId == null || sessionId == null)
-      {
-         return;
-      }
-
-      if (!isCacheAvailable())
-      {
-         return;
-      }
-
-      // Check that this session removal is not due to our own deregistration
-      // of an SSO following receipt of a nodeRemoved() call
-      if (ssoId.equals(beingRemotelyRemoved.get()))
-      {
-         return;
-      }
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("removeSession(): removing Session " + sessionId.getSessionId() +
-            " from cached session set for SSO " + ssoId);
-      }
-
-      boolean doTx = false;
-      boolean removing = false;
-      try
-      {
-         // Confirm we have a transaction manager; if not get it from Cache
-         // failure to find will throw an IllegalStateException
-         if (tm == null)
-            configureFromCache();
-
-         // Don't do anything if there is already a transaction
-         // context associated with this thread.
-         if(tm.getTransaction() == null)
-            doTx = true;
-
-         if(doTx)
-            tm.begin();
-
-         // remove session
-         removeSessionFromCache(ssoId, sessionId);
-      }
-      catch (Exception e)
-      {
-         try
-         {
-            if(doTx)
-               tm.setRollbackOnly();
-         }
-         catch (Exception x)
-         {
-         }
-
-         log.error("caught exception removing session " + sessionId.getSessionId() +
-            " from SSO id " + ssoId, e);
-      }
-      finally
-      {
-         try
-         {
-            if (removing)
-            {
-               beingLocallyRemoved.set(null);
-            }
-         }
-         finally
-         {
-            if (doTx)
-               endTransaction();
-         }
-      }
-   }
-
-
-   /**
-    * Notifies the cluster of an update of the security credentials
-    * associated with an SSO session.
-    *
-    * @param ssoId    the id of the SSO session
-    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
-    *                 or FORM) used to authenticate the SSO.
-    * @param username the username (if any) used for the authentication
-    * @param password the password (if any) used for the authentication
-    */
-   public void updateCredentials(String ssoId, String authType,
-      String username, String password)
-   {
-      if (!isCacheAvailable())
-      {
-         return;
-      }
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("Updating credentials for SSO " + ssoId +
-            " in clustered cache");
-      }
-
-      storeCredentials(ssoId, authType, username, password);
-   }
-
-
-   // ------------------------------------------------------  CacheListener
-
-   /**
-    * Extracts an SSO session id and uses it in an invocation of
-    * {@link ClusteredSingleSignOn#deregister(String) ClusteredSingleSignOn.deregister(String)}.
-    * <p/>
-    * Ignores invocations resulting from Cache changes originated by
-    * this object.
-    *
-    * @param event
-    */
-   @CacheEntryRemoved
-   public void cacheEntryRemoved(CacheEntryRemovedEvent event)
-   {
-      if (event.isPre())
-         return;
-
-      CacheKey key = (CacheKey)event.getKey();
-      String ssoId = key.getSSOID();
-
-      if (ssoId == null ||
-         key.getType() != CacheKey.Type.SESSION)
-      {
-         return;
-      }
-
-      // Entire SSO is being removed; i.e. an invalidation
-      // Ignore messages generated by our own logout activity
-      // TODO:  can we check event.isOriginLocal instead of beingLocallyRemoved? 
-      if (!ssoId.equals(beingLocallyRemoved.get()))
-      {
-         deregisterSSO(ssoId);
-      }
-      // signal the case that we have zero sessions for this ssoId
-      notifySSOEmpty(ssoId);
-   }
-
-   /**
-    * If any nodes have been removed from the view, asynchronously scans
-    * all SSOs looking for and removing sessions owned by the removed node.
-    * Notifies the SSO valve if as a result any SSOs no longer have active
-    * sessions.  If the removed node is the one associated with this object,
-    * does nothing.
-    */
-   @ViewChanged
-   public void viewChange(ViewChangedEvent event)
-   {
-      log.debug("Received ViewChangedEvent " + event);
-      boolean masterNode = false;  // true if we are the first node in the cluster group.
-      Set<Object> oldMembers = new HashSet<Object>(event.getOldMembers());
-      synchronized (currentView)
-      {
-         currentView.clear();
-         currentView.addAll(event.getNewMembers());
-
-         // If we're not in the view, just exit
-         if (localAddress == null || !currentView.contains(localAddress))
-            return;
-
-         // treat the first node in the view as the master node
-         if (currentView.iterator().next().equals(localAddress))
-         {
-            masterNode = true;
-         }
-
-         // Remove all the current members from the old set; any left
-         // are the dead members
-         oldMembers.removeAll(currentView);
-      }
-
-      /**
-       * if we are the master node, clean up any dead sessions left behind from a node that left the cluster group
-       */
-      if (oldMembers.size() > 0 && masterNode)
-      {
-         log.debug("Members have been removed; will launch cleanup task. Dead members: " + oldMembers);
-
-         launchSSOCleaner(false);
-      }
-
-   }
-
-
-   /**
-    * Instantiates a DeadMemberCleaner and assigns a thread
-    * to execute the cleanup task.
-    * @param notifyIfEmpty TODO
-    */
-   private void launchSSOCleaner(boolean notifyIfEmpty)
-   {
-
-      SSOCleanerTask cleaner = new SSOCleanerTask(notifyIfEmpty);
-      if (threadPool != null)
-      {
-         threadPool.run(cleaner);
-      }
-      else
-      {
-         Thread t = new Thread(cleaner, "ClusteredSSOCleaner");
-         t.setDaemon(true);
-         t.start();
-      }
-   }
-
-
-   /**
-    * Handles the notification that an entire SSO has been removed remotely
-    *
-    * @param ssoId id of the removed SSO
-    */
-   private void deregisterSSO(String ssoId)
-   {
-      beingRemotelyRemoved.set(ssoId);
-
-      try
-      {
-         if (log.isTraceEnabled())
-         {
-            log.trace("received a node removed message for SSO " + ssoId);
-         }
-
-         ssoValve.deregister(ssoId);
-      }
-      finally
-      {
-         beingRemotelyRemoved.set(null);
-      }
-   }
-
-   /**
-    * Checks whether any peers remain for the given SSO; if not
-    * notifies the valve that the SSO is empty.
-    *
-    * @param ssoId
-    */
-   private void notifySSOEmpty(String ssoId)
-   {
-      try
-      {
-         if (getSSOSessions(ssoId).size() == 0)
-         {
-            ssoValve.notifySSOEmpty(ssoId);
-         }
-      }
-      catch (Exception e)
-      {
-         log.error("Caught exception checking if " +  ssoId + " is empty", e);
-      }
-   }
-
-   /**
-    * Extracts an SSO session id and uses it in an invocation of
-    * {@link ClusteredSingleSignOn#update ClusteredSingleSignOn.update()}.
-    * <p/>
-    * Ignores invocations resulting from Cache changes originated by
-    * this object.
-    * <p/>
-    * Ignores invocations for SSO session id's that are not registered
-    * with the local SingleSignOn valve.
-    *
-    * @param event
-    */
-   @CacheEntryModified
-   public void cacheEntryModified(CacheEntryModifiedEvent event)
-   {
-      if (event.isPre() || event.isOriginLocal())
-         return;
-
-      CacheKey key = (CacheKey)event.getKey();
-      if (key.getType() == CacheKey.Type.CREDENTIAL)
-      {
-         handleCredentialModifiedEvent(key.getSSOID(), (SSOCredentials)event.getValue());
-      }
-      else if (key.getType() == CacheKey.Type.SESSION)
-      {
-         handleSessionModifiedEvent(key.getSSOID());
-      }
-   }
-
-   /**
-    * @param ssoId the id of the sso
-    * @param credentials 
-    */
-   private void handleCredentialModifiedEvent(String ssoId,SSOCredentials credentials)
-   {
-      // Ignore invocations that come as a result of our additions
-      // TODO: can this local check be removed since we already ignore local events in caller
-      if (ssoId.equals(beingLocallyAdded.get()))
-      {
-         return;
-      }
-
-      if (log.isTraceEnabled())
-      {
-         log.trace("received a credentials modified message for SSO " + ssoId);
-      }
-
-      try
-      {
-         if (credentials != null)
-         {
-            ssoValve.remoteUpdate(ssoId, credentials);
-         }
-      }
-      catch (Exception e)
-      {
-         log.error("failed to update credentials for SSO " + ssoId, e);
-      }
-   }
-
-   /**
-    *
-    * @param ssoId single sign-on session id
-    */
-   private void handleSessionModifiedEvent(String ssoId)
-   {
-      // Peers remove their entire node when it's empty, so any
-      // other modification means it's not empty
-      ssoValve.notifySSONotEmpty(ssoId);
-   }
-
-   /**
-    * Prepare for the beginning of active use of the public methods of this
-    * component.  This method should be called before any of the public
-    * methods of this component are utilized.  It should also send a
-    * LifecycleEvent of type START_EVENT to any registered listeners.
-    *
-    * @throws Exception if this component detects a fatal error
-    *                            that prevents this component from being used
-    */
-   public void start() throws Exception
-   {
-      // Validate and update our current component state
-      if (started)
-      {
-         throw new IllegalStateException("SSOClusterManagerImpl already Started");
-      }
-      this.cache = cacheHandler.getCache();
-      initThreadPool();
-      registerAsCacheListener();
-
-      this.tm = this.cache.getAdvancedCache().getTransactionManager();
-
-      started = true;
-   }
-
-
-   /**
-    * Gracefully terminate the active use of the public methods of this
-    * component.  This method should be the last one called on a given
-    * instance of this component.  It should also send a LifecycleEvent
-    * of type STOP_EVENT to any registered listeners.
-    *
-    * @throws Exception if this component detects a fatal error
-    *                            that needs to be reported
-    */
-   public void stop() throws Exception
-   {
-      // Validate and update our current component state
-      if (!started)
-      {
-         throw new IllegalStateException("SSOClusterManagerImpl not Started");
-      }
-
-      removeAsCacheListener();
-
-      started = false;
-   }
-
-
-   // -------------------------------------------------------  Public Methods
-
-   /**
-    * Gets the number of sessions associated with the given SSO. The same
-    * session active on more than one node will count more than once.
-    */
-   public int getSessionCount(String ssoId) throws Exception
-   {
-      return getSSOSessions(ssoId).size();
-   }
-
-   // -------------------------------------------------------  Private Methods
-
-   private Set<String> getSSOIds() throws Exception
-   {
-      Set keys = cache.keySet();
-      Set result = new HashSet<String>();
-      for (Object key: keys)
-      {
-         CacheKey ck = (CacheKey)key;
-         if (ck.getType() == CacheKey.Type.SESSION)
-         {
-            result.add(ck.getSSOID());
-         }
-      }
-
-      return result;
-   }
-
-   /**
-    *
-    * @param ssoId
-    * @return set of FullyQualifiedSessionId
-    * @throws Exception
-    */
-   private Set<FullyQualifiedSessionId> getSSOSessions(String ssoId) throws Exception
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
-      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, true);
-      return m!=null ? m.keySet() : Collections.EMPTY_SET;
-   }
-
-   /**
-    * Obtains needed configuration information from the cache.
-    * Invokes "getTransactionManager" on the cache, caching the
-    * result or throwing an IllegalStateException if one is not found.
-    * Also gets our cluster-wide unique local address from the cache.
-    *
-    * @throws Exception
-    */
-   private void configureFromCache() throws Exception
-   {
-      if(tm == null)
-      {
-         tm = cache.getAdvancedCache().getTransactionManager();
-      }
-
-      if (tm == null)
-      {
-         throw new IllegalStateException("Cache does not have a " +
-                                         "transaction manager; please " +
-                                         "configure a valid " +
-                                         "TransactionManagerLookupClass");
-      }
-
-      // We no longer rule out buddy replication, as it can be valid if
-      // all activity for the SSO is meant to pinned to one server (i.e.
-      // only one session, or all sessions share the same session id cookie)
-      /*
-      if (cache.getConfiguration().getBuddyReplicationConfig() != null
-            && cache.getConfiguration().getBuddyReplicationConfig().isEnabled())
-      {
-         throw new IllegalStateException("Underlying cache is configured for " +
-                                         "buddy replication; use of buddy " +
-                                         "replication with ClusteredSingleSignOn " +
-                                         "is not supported");
-      }
-      */
-      // Find out our address
-      Address address = cache.getAdvancedCache().getRpcManager().getAddress();
-      if (address != null)
-         localAddress = address;
-      else if (Configuration.CacheMode.LOCAL == cache.getConfiguration().getCacheMode())
-         localAddress = "LOCAL";
-      else
-         throw new IllegalStateException("Cannot get local address from cache");
-
-
-      log.debug("Local address is " + localAddress);
-
-   }
-
-   private void endTransaction()
-   {
-      try
-      {
-         if(tm.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK)
-         {
-            tm.commit();
-         }
-         else
-         {
-            tm.rollback();
-         }
-      }
-      catch (Exception e)
-      {
-         log.error(e);
-         throw new RuntimeException("SSOClusterManagerImpl.endTransaction(): ", e);
-      }
-   }
-
-   private MBeanServer getMBeanServer()
-   {
-      if (server == null && ssoValve != null)
-      {
-         server = ssoValve.getMBeanServer();
-      }
-      return server;
-   }
-
-   private boolean isCacheAvailable()
-   {
-      //boolean avail = isCacheAvailable(false);
-      boolean avail = this.cache != null;
-      if (!avail)
-         logMissingCacheError();
-      return avail;
-   }
-
-   /**
-    * Put a new session in the cache
-    * @param ssoId session id
-    * @param fullyQualifiedSessionId  fully qualified session id
-    * @throws Exception
-    */
-   private void putSessionInCache(String ssoId, FullyQualifiedSessionId fullyQualifiedSessionId) throws Exception
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
-      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, true);
-      m.put(fullyQualifiedSessionId, null);
-   }
-
-   /**
-    * Put or update user credentials in the cache
-    * @param ssoId session id
-    * @param credentials
-    * @throws Exception
-    */
-   private void putCredentialsInCache(String ssoId, SSOCredentials credentials) throws Exception
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
-      cache.put(key, credentials);
-   }
-
-   private SSOCredentials getCredentialsFromCache(String ssoId)
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
-      return (SSOCredentials)cache.get(key);
-   }
-
-   /**
-    * register as a cache listener.
-    *
-    * @throws Exception
-    */
-   private void registerAsCacheListener() throws Exception
-   {
-      cache.addListener(this);
-      registeredAsListener = true;
-   }
-
-
-   /**
-    * stop listening on the cache.
-    *
-    * @throws Exception
-    */
-   private void removeAsCacheListener() throws Exception
-   {
-      if (registeredAsListener && cache != null)
-      {
-         cache.removeListener(this);
-         registeredAsListener = false;
-      }
-   }
-
-   /**
-    * Remove the specified session from the cache (used for session.logout)
-    *
-    * @param ssoId the session id representing the shared single session
-    * @throws Exception
-    */
-   private void removeSSOFromCache(String ssoId) throws Exception
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
-      cache.remove(key);
-      key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
-      cache.remove(key);  // remove user credentials too
-   }
-
-   /**
-    * Remove one of the sessions associated with the users shared single session
-    * @param ssoId ssoId the session id representing the shared single session
-    * @param fullyQualifiedSessionId representing the session to remove
-    * @throws Exception
-    */
-   private void removeSessionFromCache(String ssoId, FullyQualifiedSessionId fullyQualifiedSessionId) throws Exception
-   {
-      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
-      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, false);
-      if (m != null)
-      {
-         m.remove(fullyQualifiedSessionId);
-      }
-   }
-
-   /**
-    * Stores the given data to the clustered cache.
-    *
-    * @param ssoId    the id of the SSO session
-    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
-    *                 or FORM) used to authenticate the SSO.
-    * @param username the username (if any) used for the authentication
-    * @param password the password (if any) used for the authentication
-    */
-   private void storeCredentials(String ssoId, String authType, String username,
-      String password)
-   {
-      SSOCredentials credentials = new SSOCredentials(authType, username, password);
-
-      // Add this SSO to our list of in-process local adds so
-      // this.nodeModified() will ignore the addition
-      beingLocallyAdded.set(ssoId);
-
-      try
-      {
-         putCredentialsInCache(ssoId, credentials);
-      }
-      catch (Exception e)
-      {
-         log.error("Exception attempting to add Cache nodes for SSO " +
-            ssoId, e);
-      }
-      finally
-      {
-         beingLocallyAdded.set(null);
-      }
-   }
-
-   private void initThreadPool()
-   {
-      if (threadPoolName != null && getMBeanServer() != null)
-      {
-         try
-         {
-            ObjectName on = new ObjectName(threadPoolName);
-            threadPool = (ThreadPool) server.getAttribute(on, "Instance");
-            log.debug("Using ThreadPool at " + threadPoolName + " to clean dead members");
-         }
-         catch (Exception e)
-         {
-            log.info("Unable to access ThreadPool at " + threadPoolName +
-                     " -- will use individual threads for cleanup work");
-            log.debug("Failure to access ThreadPool due to: " + e);
-         }
-      }
-      else
-      {
-         log.debug("No ThreadPool configured -- will use individual threads for cleanup work");
-      }
-   }
-
-   private boolean isMissingCacheErrorLogged()
-   {
-      return missingCacheErrorLogged;
-   }
-
-   private void setMissingCacheErrorLogged(boolean missingCacheErrorLogged)
-   {
-      this.missingCacheErrorLogged = missingCacheErrorLogged;
-   }
-
-   private void logMissingCacheError()
-   {
-      StringBuffer msg = new StringBuffer("Cache is not set");
-      msg.append(" -- Cache must be started before SSOClusterManagerImpl ");
-      msg.append("can handle requests");
-
-      if (isMissingCacheErrorLogged())
-      {
-         // Just log it as a warning
-         log.warn(msg);
-      }
-      else
-      {
-         log.error(msg);
-         // Set a flag so we don't relog this error over and over
-         setMissingCacheErrorLogged(true);
-      }
-   }
-
-   // ---------------------------------------------------------  Outer Classes
-
-   /**
-    * Runnable that's run when the removal of a node from the cluster has been detected.
-    * Removes any SessionAddress objects associated with dead members from the
-    * session set of each SSO.  Operates locally only so each node can independently clean
-    * its SSOs without concern about replication lock conflicts.
-    */
-   private class SSOCleanerTask implements Runnable
-   {
-      private final boolean checkForEmpty;
-
-      private SSOCleanerTask(boolean checkForEmpty)
-      {
-         this.checkForEmpty = checkForEmpty;
-      }
-
-      public void run()
-      {
-         synchronized (cleanupMutex)
-         {
-            try
-            {
-               log.debug("check if we have to clean up SSO for any members that left the cluster.");
-               // Ensure we have a TransactionManager
-               if (tm == null)
-                  configureFromCache();
-
-               Set<String> ids = getSSOIds();
-               for (String sso : ids)
-               {
-                  cleanSSO(sso);
-               }
-            }
-            catch (Exception e)
-            {
-               log.error("Caught exception cleaning sessions from dead cluster members from SSOs ", e);
-            }
-         }
-      }
-
-      private void cleanSSO(String ssoId)
-      {
-         boolean doTx = false;
-         try
-         {
-            // Don't start tx if there is already one associated with this thread.
-            if(tm.getTransaction() == null)
-               doTx = true;
-
-            if(doTx)
-               tm.begin();
-
-            Set<FullyQualifiedSessionId> fullyQualifiedSessionIds = getSSOSessions(ssoId);
-            if (fullyQualifiedSessionIds.size() > 0)
-            {
-               for (FullyQualifiedSessionId fullyQualifiedSessionId : fullyQualifiedSessionIds)
-               {
-                  boolean alive;
-                  synchronized (currentView)
-                  {
-                     alive = currentView.contains(fullyQualifiedSessionId.getHostName());
-                  }
-                  if (!alive)
-                  {
-                     if (log.isTraceEnabled())
-                     {
-                        log.trace("Removing peer " + fullyQualifiedSessionId + " from SSO " + ssoId);
-                     }
-
-                     // Remove the peer node
-                     removeSessionFromCache(ssoId, fullyQualifiedSessionId);
-                  }
-               }
-            }
-            else if (checkForEmpty)
-            {
-               // SSO has no peers; notify our valve so we can expire it
-               ssoValve.notifySSOEmpty(ssoId);
-            }
-         }
-         catch (Exception e)
-         {
-            try
-            {
-               if(doTx)
-                  tm.setRollbackOnly();
-            }
-            catch (Exception ignored)
-            {
-            }
-            log.error("caught exception cleaning dead members from SSO " + ssoId, e);
-         }
-         finally
-         {
-            if (doTx)
-               endTransaction();
-         }
-      }
-   }
-
-}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/CacheKey.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/CacheKey.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/CacheKey.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/CacheKey.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,73 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, 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.jboss.ha.web.tomcat.service.session.sso.ispn;
+
+/**
+ * Used to represent the different types of entries in the cache store.
+ *
+ * Note that we purposely do not implement equals, which allows many different
+ * entries with the same key to be added.
+ *
+ */
+public class CacheKey
+{
+   public static enum Type { SESSION, CREDENTIAL }
+
+   private final String ssoId;
+   private final Type type;
+
+   public CacheKey(String ssoId, Type type)
+   {
+      this.ssoId = ssoId;
+      this.type = type;
+   }
+
+   public String getSSOID()
+   {
+      return this.ssoId;
+   }
+
+   public Type getType()
+   {
+      return this.type;
+   }
+
+   @Override
+   public int hashCode()
+   {
+      int result = 17;
+      result = 37*result + this.ssoId.hashCode();
+      result = 37*result + this.type.ordinal();
+      return result;
+   }
+   
+   @Override
+   public boolean equals(Object object)
+   {
+      if ((object == null) || !(object instanceof CacheKey)) return false;
+      
+      CacheKey key = (CacheKey) object;
+      
+      return (this.type == key.type) && this.ssoId.equals(key.ssoId);
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManager.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerImpl.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManager.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManager.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,1150 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2010, 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.jboss.ha.web.tomcat.service.session.sso.ispn;
+
+import org.infinispan.atomic.AtomicMap;
+import org.infinispan.atomic.AtomicMapLookup;
+import org.infinispan.config.Configuration;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+import org.infinispan.notifications.cachemanagerlistener.annotation.ViewChanged;
+import org.infinispan.notifications.cachemanagerlistener.event.ViewChangedEvent;
+import org.infinispan.Cache;
+import org.infinispan.remoting.transport.Address;
+import org.jboss.ha.framework.server.ispn.InfinispanHAPartitionCacheHandler;
+import org.jboss.logging.Logger;
+import org.jboss.util.threadpool.ThreadPool;
+import org.jboss.web.tomcat.service.sso.spi.FullyQualifiedSessionId;
+import org.jboss.web.tomcat.service.sso.spi.SSOCredentials;
+import org.jboss.web.tomcat.service.sso.spi.SSOLocalManager;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An implementation of SSOClusterManager that uses a Infinispan cache
+ * to share SSO information between cluster nodes.
+ *
+ * @author Brian E. Stansberry
+ * @author Scott Marlow
+ * @version $Revision$ $Date: 2007-01-12 03:39:24 +0100 (ven., 12 janv. 2007) $
+ */
+// @Listener
+public final class SSOClusterManager implements org.jboss.web.tomcat.service.sso.spi.SSOClusterManager
+{
+   // -------------------------------------------------------------  Constants
+
+
+   /**
+    * Default global value for the threadPoolName property
+    */
+   public static final String DEFAULT_THREAD_POOL_NAME =
+      "jboss.system:service=ThreadPool";
+
+   // -------------------------------------------------------  Instance Fields
+
+   /**
+    * SSO id which the thread is currently storing to the cache
+    */
+   private volatile ThreadLocal<String> beingLocallyAdded = new ThreadLocal<String>();
+
+   /**
+    * SSO id which a thread is currently removing from the cache
+    */
+   private volatile ThreadLocal<String> beingLocallyRemoved = new ThreadLocal<String>();
+
+   /**
+    * SSO id which the thread is deregistering due to removal on another node
+    */
+   private volatile ThreadLocal<String> beingRemotelyRemoved = new ThreadLocal<String>();
+
+   /**
+    * The clustered cache that holds the SSO credentials and the sessions.
+    * The CacheKey will indicate which type it is (CacheKey.CREDENTIAL or CacheKey.SESSION);
+    */
+   private volatile Cache<CacheKey, Object> cache = null;
+
+   /**
+    * Transaction Manager
+    */
+   private volatile TransactionManager tm = null;
+
+   private volatile String threadPoolName = DEFAULT_THREAD_POOL_NAME;
+
+   private volatile ThreadPool threadPool;
+
+   /**
+    * The Log-object for this class
+    */
+   private static final Logger log = Logger.getLogger(SSOClusterManager.class);;
+
+   /**
+    * Whether we are registered as a CacheListener anywhere
+    */
+   private volatile boolean registeredAsListener = false;
+
+   /**
+    * The MBean server we use to access external components (TODO: convert to injection)
+    */
+   private volatile MBeanServer server = null;
+
+   /**
+    * The SingleSignOn for which we are providing cluster support
+    */
+   private volatile SSOLocalManager ssoValve = null;
+
+   /**
+    * Whether we have been started
+    */
+   private volatile boolean started = false;
+
+   /**
+    * Whether we have logged an error due to not having a valid cache
+    */
+   private volatile boolean missingCacheErrorLogged = false;
+
+   /**
+    * Our node's address in the cluster.
+    */
+   private volatile Object localAddress = null;
+
+   /**
+    * The new members of the last view passed to viewChange()
+    */
+   private final Set<Object> currentView = new HashSet<Object>();;
+
+   /** Mutex lock to ensure only one view change at a time is being processed */
+   private final Object cleanupMutex = new Object();
+
+   private volatile InfinispanHAPartitionCacheHandler<CacheKey, Object> cacheHandler;
+
+   // ------------------------------------------------------------  Properties
+
+   public InfinispanHAPartitionCacheHandler getCacheHandler()
+   {
+      return cacheHandler;
+   }
+
+   public void setCacheHandler(InfinispanHAPartitionCacheHandler cacheHandler)
+   {
+      this.cacheHandler = cacheHandler;
+   }
+
+   public String getThreadPoolName()
+   {
+      return threadPoolName;
+   }
+
+   public boolean isUsingThreadPool()
+   {
+      return threadPool != null;
+   }
+
+   // -----------------------------------------------------  SSOClusterManager
+
+   /**
+    * Notify the cluster of the addition of a Session to an SSO session.
+    *
+    * @param ssoId   the id of the SSO session
+    * @param sessionId id of the Session that has been added
+    */
+   public void addSession(String ssoId, FullyQualifiedSessionId sessionId)
+   {
+      if (ssoId == null || sessionId == null)
+      {
+         return;
+      }
+
+      if (!isCacheAvailable())
+      {
+         return;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("addSession(): adding Session " + sessionId.getSessionId() +
+            " to cached session set for SSO " + ssoId);
+      }
+
+      boolean doTx = false;
+      try
+      {
+         // Confirm we have a transaction manager; if not get it from Cache
+         // failure to find will throw an IllegalStateException
+         if (tm == null)
+            configureFromCache();
+
+         // Don't do anything if there is already a transaction
+         // context associated with this thread.
+         if(tm.getTransaction() == null)
+            doTx = true;
+
+         if(doTx)
+            tm.begin();
+
+         putSessionInCache(ssoId, sessionId);
+      }
+      catch (Exception e)
+      {
+         try
+         {
+            if(doTx)
+               tm.setRollbackOnly();
+         }
+         catch (Exception ignored)
+         {
+         }
+         log.error("caught exception adding session " + sessionId.getSessionId() +
+            " to SSO id " + ssoId, e);
+      }
+      finally
+      {
+         if (doTx)
+            endTransaction();
+      }
+   }
+
+
+   /**
+    * Gets the SingleSignOn valve for which this object is handling
+    * cluster communications.
+    *
+    * @return the <code>SingleSignOn</code> valve.
+    */
+   public SSOLocalManager getSSOLocalManager()
+   {
+      return ssoValve;
+   }
+
+
+   /**
+    * Sets the SingleSignOn valve for which this object is handling
+    * cluster communications.
+    * <p><b>NOTE:</b> This method must be called before calls can be
+    * made to the other methods of this interface.
+    *
+    * @param localManager a <code>SingleSignOn</code> valve.
+    */
+   public void setSSOLocalManager(SSOLocalManager localManager)
+   {
+      ssoValve = localManager;
+      if (ssoValve != null)
+      {
+         if (server == null)
+         {
+            server = ssoValve.getMBeanServer();
+         }
+         String poolName = ssoValve.getThreadPoolName();
+         if (poolName != null)
+         {
+            threadPoolName = poolName;
+         }
+      }
+   }
+
+
+   /**
+    * Notifies the cluster that a single sign on session has been terminated
+    * due to a user logout.
+    *
+    * @param ssoId
+    */
+   public void logout(String ssoId)
+   {
+      if (!isCacheAvailable())
+      {
+         return;
+      }
+
+      // Check whether we are already handling this removal
+      if (ssoId.equals(beingLocallyRemoved.get()))
+      {
+         return;
+      }
+
+      // Add this SSO to our list of in-process local removals so
+      // this.nodeRemoved() will ignore the removal
+      beingLocallyRemoved.set(ssoId);
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("Registering logout of SSO " + ssoId +
+            " in clustered cache");
+      }
+
+      try
+      {
+         removeSSOFromCache(ssoId);
+      }
+      catch (Exception e)
+      {
+         log.error("Exception attempting to logout " +
+            ssoId, e);
+      }
+      finally
+      {
+         beingLocallyRemoved.set(null);
+      }
+   }
+
+
+   public SSOCredentials lookup(String ssoId)
+   {
+      if (!isCacheAvailable())
+      {
+         return null;
+      }
+
+      SSOCredentials credentials = null;
+      // Find the latest credential info from the cluster
+      try
+      {
+         credentials = getCredentialsFromCache(ssoId);
+      }
+      catch (Exception e)
+      {
+         log.error("caught exception looking up SSOCredentials for SSO id " +
+            ssoId, e);
+      }
+      return credentials;
+   }
+
+
+   /**
+    * Notifies the cluster of the creation of a new SSO entry.
+    *
+    * @param ssoId    the id of the SSO session
+    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
+    *                 or FORM) used to authenticate the SSO.
+    * @param username the username (if any) used for the authentication
+    * @param password the password (if any) used for the authentication
+    */
+   public void register(String ssoId, String authType,
+      String username, String password)
+   {
+      if (!isCacheAvailable())
+      {
+         return;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("Registering SSO " + ssoId + " in clustered cache");
+      }
+
+      storeCredentials(ssoId, authType, username, password);
+   }
+
+
+   /**
+    * Notify the cluster of the removal of a Session from an SSO session.
+    *
+    * @param ssoId   the id of the SSO session
+    * @param sessionId id of the Session that has been removed
+    */
+   public void removeSession(String ssoId, FullyQualifiedSessionId sessionId)
+   {
+      if (ssoId == null || sessionId == null)
+      {
+         return;
+      }
+
+      if (!isCacheAvailable())
+      {
+         return;
+      }
+
+      // Check that this session removal is not due to our own deregistration
+      // of an SSO following receipt of a nodeRemoved() call
+      if (ssoId.equals(beingRemotelyRemoved.get()))
+      {
+         return;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("removeSession(): removing Session " + sessionId.getSessionId() +
+            " from cached session set for SSO " + ssoId);
+      }
+
+      boolean doTx = false;
+      boolean removing = false;
+      try
+      {
+         // Confirm we have a transaction manager; if not get it from Cache
+         // failure to find will throw an IllegalStateException
+         if (tm == null)
+            configureFromCache();
+
+         // Don't do anything if there is already a transaction
+         // context associated with this thread.
+         if(tm.getTransaction() == null)
+            doTx = true;
+
+         if(doTx)
+            tm.begin();
+
+         // remove session
+         removeSessionFromCache(ssoId, sessionId);
+      }
+      catch (Exception e)
+      {
+         try
+         {
+            if(doTx)
+               tm.setRollbackOnly();
+         }
+         catch (Exception x)
+         {
+         }
+
+         log.error("caught exception removing session " + sessionId.getSessionId() +
+            " from SSO id " + ssoId, e);
+      }
+      finally
+      {
+         try
+         {
+            if (removing)
+            {
+               beingLocallyRemoved.set(null);
+            }
+         }
+         finally
+         {
+            if (doTx)
+               endTransaction();
+         }
+      }
+   }
+
+
+   /**
+    * Notifies the cluster of an update of the security credentials
+    * associated with an SSO session.
+    *
+    * @param ssoId    the id of the SSO session
+    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
+    *                 or FORM) used to authenticate the SSO.
+    * @param username the username (if any) used for the authentication
+    * @param password the password (if any) used for the authentication
+    */
+   public void updateCredentials(String ssoId, String authType,
+      String username, String password)
+   {
+      if (!isCacheAvailable())
+      {
+         return;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("Updating credentials for SSO " + ssoId +
+            " in clustered cache");
+      }
+
+      storeCredentials(ssoId, authType, username, password);
+   }
+
+
+   // ------------------------------------------------------  CacheListener
+
+   /**
+    * Extracts an SSO session id and uses it in an invocation of
+    * {@link ClusteredSingleSignOn#deregister(String) ClusteredSingleSignOn.deregister(String)}.
+    * <p/>
+    * Ignores invocations resulting from Cache changes originated by
+    * this object.
+    *
+    * @param event
+    */
+   @CacheEntryRemoved
+   public void cacheEntryRemoved(CacheEntryRemovedEvent event)
+   {
+      if (event.isPre())
+         return;
+
+      CacheKey key = (CacheKey)event.getKey();
+      String ssoId = key.getSSOID();
+
+      if (ssoId == null ||
+         key.getType() != CacheKey.Type.SESSION)
+      {
+         return;
+      }
+
+      // Entire SSO is being removed; i.e. an invalidation
+      // Ignore messages generated by our own logout activity
+      // TODO:  can we check event.isOriginLocal instead of beingLocallyRemoved? 
+      if (!ssoId.equals(beingLocallyRemoved.get()))
+      {
+         deregisterSSO(ssoId);
+      }
+      // signal the case that we have zero sessions for this ssoId
+      notifySSOEmpty(ssoId);
+   }
+
+   /**
+    * If any nodes have been removed from the view, asynchronously scans
+    * all SSOs looking for and removing sessions owned by the removed node.
+    * Notifies the SSO valve if as a result any SSOs no longer have active
+    * sessions.  If the removed node is the one associated with this object,
+    * does nothing.
+    */
+   @ViewChanged
+   public void viewChange(ViewChangedEvent event)
+   {
+      log.debug("Received ViewChangedEvent " + event);
+      boolean masterNode = false;  // true if we are the first node in the cluster group.
+      Set<Object> oldMembers = new HashSet<Object>(event.getOldMembers());
+      synchronized (currentView)
+      {
+         currentView.clear();
+         currentView.addAll(event.getNewMembers());
+
+         // If we're not in the view, just exit
+         if (localAddress == null || !currentView.contains(localAddress))
+            return;
+
+         // treat the first node in the view as the master node
+         if (currentView.iterator().next().equals(localAddress))
+         {
+            masterNode = true;
+         }
+
+         // Remove all the current members from the old set; any left
+         // are the dead members
+         oldMembers.removeAll(currentView);
+      }
+
+      /**
+       * if we are the master node, clean up any dead sessions left behind from a node that left the cluster group
+       */
+      if (oldMembers.size() > 0 && masterNode)
+      {
+         log.debug("Members have been removed; will launch cleanup task. Dead members: " + oldMembers);
+
+         launchSSOCleaner(false);
+      }
+
+   }
+
+
+   /**
+    * Instantiates a DeadMemberCleaner and assigns a thread
+    * to execute the cleanup task.
+    * @param notifyIfEmpty TODO
+    */
+   private void launchSSOCleaner(boolean notifyIfEmpty)
+   {
+
+      SSOCleanerTask cleaner = new SSOCleanerTask(notifyIfEmpty);
+      if (threadPool != null)
+      {
+         threadPool.run(cleaner);
+      }
+      else
+      {
+         Thread t = new Thread(cleaner, "ClusteredSSOCleaner");
+         t.setDaemon(true);
+         t.start();
+      }
+   }
+
+
+   /**
+    * Handles the notification that an entire SSO has been removed remotely
+    *
+    * @param ssoId id of the removed SSO
+    */
+   private void deregisterSSO(String ssoId)
+   {
+      beingRemotelyRemoved.set(ssoId);
+
+      try
+      {
+         if (log.isTraceEnabled())
+         {
+            log.trace("received a node removed message for SSO " + ssoId);
+         }
+
+         ssoValve.deregister(ssoId);
+      }
+      finally
+      {
+         beingRemotelyRemoved.set(null);
+      }
+   }
+
+   /**
+    * Checks whether any peers remain for the given SSO; if not
+    * notifies the valve that the SSO is empty.
+    *
+    * @param ssoId
+    */
+   private void notifySSOEmpty(String ssoId)
+   {
+      try
+      {
+         if (getSSOSessions(ssoId).size() == 0)
+         {
+            ssoValve.notifySSOEmpty(ssoId);
+         }
+      }
+      catch (Exception e)
+      {
+         log.error("Caught exception checking if " +  ssoId + " is empty", e);
+      }
+   }
+
+   /**
+    * Extracts an SSO session id and uses it in an invocation of
+    * {@link ClusteredSingleSignOn#update ClusteredSingleSignOn.update()}.
+    * <p/>
+    * Ignores invocations resulting from Cache changes originated by
+    * this object.
+    * <p/>
+    * Ignores invocations for SSO session id's that are not registered
+    * with the local SingleSignOn valve.
+    *
+    * @param event
+    */
+   @CacheEntryModified
+   public void cacheEntryModified(CacheEntryModifiedEvent event)
+   {
+      if (event.isPre() || event.isOriginLocal())
+         return;
+
+      CacheKey key = (CacheKey)event.getKey();
+      if (key.getType() == CacheKey.Type.CREDENTIAL)
+      {
+         handleCredentialModifiedEvent(key.getSSOID(), (SSOCredentials)event.getValue());
+      }
+      else if (key.getType() == CacheKey.Type.SESSION)
+      {
+         handleSessionModifiedEvent(key.getSSOID());
+      }
+   }
+
+   /**
+    * @param ssoId the id of the sso
+    * @param credentials 
+    */
+   private void handleCredentialModifiedEvent(String ssoId,SSOCredentials credentials)
+   {
+      // Ignore invocations that come as a result of our additions
+      // TODO: can this local check be removed since we already ignore local events in caller
+      if (ssoId.equals(beingLocallyAdded.get()))
+      {
+         return;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("received a credentials modified message for SSO " + ssoId);
+      }
+
+      try
+      {
+         if (credentials != null)
+         {
+            ssoValve.remoteUpdate(ssoId, credentials);
+         }
+      }
+      catch (Exception e)
+      {
+         log.error("failed to update credentials for SSO " + ssoId, e);
+      }
+   }
+
+   /**
+    *
+    * @param ssoId single sign-on session id
+    */
+   private void handleSessionModifiedEvent(String ssoId)
+   {
+      // Peers remove their entire node when it's empty, so any
+      // other modification means it's not empty
+      ssoValve.notifySSONotEmpty(ssoId);
+   }
+
+   /**
+    * Prepare for the beginning of active use of the public methods of this
+    * component.  This method should be called before any of the public
+    * methods of this component are utilized.  It should also send a
+    * LifecycleEvent of type START_EVENT to any registered listeners.
+    *
+    * @throws Exception if this component detects a fatal error
+    *                            that prevents this component from being used
+    */
+   public void start() throws Exception
+   {
+      // Validate and update our current component state
+      if (started)
+      {
+         throw new IllegalStateException("SSOClusterManagerImpl already Started");
+      }
+      this.cache = cacheHandler.getCache();
+      initThreadPool();
+      registerAsCacheListener();
+
+      this.tm = this.cache.getAdvancedCache().getTransactionManager();
+
+      started = true;
+   }
+
+
+   /**
+    * Gracefully terminate the active use of the public methods of this
+    * component.  This method should be the last one called on a given
+    * instance of this component.  It should also send a LifecycleEvent
+    * of type STOP_EVENT to any registered listeners.
+    *
+    * @throws Exception if this component detects a fatal error
+    *                            that needs to be reported
+    */
+   public void stop() throws Exception
+   {
+      // Validate and update our current component state
+      if (!started)
+      {
+         throw new IllegalStateException("SSOClusterManagerImpl not Started");
+      }
+
+      removeAsCacheListener();
+
+      started = false;
+   }
+
+
+   // -------------------------------------------------------  Public Methods
+
+   /**
+    * Gets the number of sessions associated with the given SSO. The same
+    * session active on more than one node will count more than once.
+    */
+   public int getSessionCount(String ssoId) throws Exception
+   {
+      return getSSOSessions(ssoId).size();
+   }
+
+   // -------------------------------------------------------  Private Methods
+
+   private Set<String> getSSOIds() throws Exception
+   {
+      Set keys = cache.keySet();
+      Set result = new HashSet<String>();
+      for (Object key: keys)
+      {
+         CacheKey ck = (CacheKey)key;
+         if (ck.getType() == CacheKey.Type.SESSION)
+         {
+            result.add(ck.getSSOID());
+         }
+      }
+
+      return result;
+   }
+
+   /**
+    *
+    * @param ssoId
+    * @return set of FullyQualifiedSessionId
+    * @throws Exception
+    */
+   private Set<FullyQualifiedSessionId> getSSOSessions(String ssoId) throws Exception
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
+      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, true);
+      return m!=null ? m.keySet() : Collections.EMPTY_SET;
+   }
+
+   /**
+    * Obtains needed configuration information from the cache.
+    * Invokes "getTransactionManager" on the cache, caching the
+    * result or throwing an IllegalStateException if one is not found.
+    * Also gets our cluster-wide unique local address from the cache.
+    *
+    * @throws Exception
+    */
+   private void configureFromCache() throws Exception
+   {
+      if(tm == null)
+      {
+         tm = cache.getAdvancedCache().getTransactionManager();
+      }
+
+      if (tm == null)
+      {
+         throw new IllegalStateException("Cache does not have a " +
+                                         "transaction manager; please " +
+                                         "configure a valid " +
+                                         "TransactionManagerLookupClass");
+      }
+
+      // We no longer rule out buddy replication, as it can be valid if
+      // all activity for the SSO is meant to pinned to one server (i.e.
+      // only one session, or all sessions share the same session id cookie)
+      /*
+      if (cache.getConfiguration().getBuddyReplicationConfig() != null
+            && cache.getConfiguration().getBuddyReplicationConfig().isEnabled())
+      {
+         throw new IllegalStateException("Underlying cache is configured for " +
+                                         "buddy replication; use of buddy " +
+                                         "replication with ClusteredSingleSignOn " +
+                                         "is not supported");
+      }
+      */
+      // Find out our address
+      Address address = cache.getAdvancedCache().getRpcManager().getAddress();
+      if (address != null)
+         localAddress = address;
+      else if (Configuration.CacheMode.LOCAL == cache.getConfiguration().getCacheMode())
+         localAddress = "LOCAL";
+      else
+         throw new IllegalStateException("Cannot get local address from cache");
+
+
+      log.debug("Local address is " + localAddress);
+
+   }
+
+   private void endTransaction()
+   {
+      try
+      {
+         if(tm.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK)
+         {
+            tm.commit();
+         }
+         else
+         {
+            tm.rollback();
+         }
+      }
+      catch (Exception e)
+      {
+         log.error(e);
+         throw new RuntimeException("SSOClusterManagerImpl.endTransaction(): ", e);
+      }
+   }
+
+   private MBeanServer getMBeanServer()
+   {
+      if (server == null && ssoValve != null)
+      {
+         server = ssoValve.getMBeanServer();
+      }
+      return server;
+   }
+
+   private boolean isCacheAvailable()
+   {
+      //boolean avail = isCacheAvailable(false);
+      boolean avail = this.cache != null;
+      if (!avail)
+         logMissingCacheError();
+      return avail;
+   }
+
+   /**
+    * Put a new session in the cache
+    * @param ssoId session id
+    * @param fullyQualifiedSessionId  fully qualified session id
+    * @throws Exception
+    */
+   private void putSessionInCache(String ssoId, FullyQualifiedSessionId fullyQualifiedSessionId) throws Exception
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
+      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, true);
+      m.put(fullyQualifiedSessionId, null);
+   }
+
+   /**
+    * Put or update user credentials in the cache
+    * @param ssoId session id
+    * @param credentials
+    * @throws Exception
+    */
+   private void putCredentialsInCache(String ssoId, SSOCredentials credentials) throws Exception
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
+      cache.put(key, credentials);
+   }
+
+   private SSOCredentials getCredentialsFromCache(String ssoId)
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
+      return (SSOCredentials)cache.get(key);
+   }
+
+   /**
+    * register as a cache listener.
+    *
+    * @throws Exception
+    */
+   private void registerAsCacheListener() throws Exception
+   {
+      cache.addListener(this);
+      registeredAsListener = true;
+   }
+
+
+   /**
+    * stop listening on the cache.
+    *
+    * @throws Exception
+    */
+   private void removeAsCacheListener() throws Exception
+   {
+      if (registeredAsListener && cache != null)
+      {
+         cache.removeListener(this);
+         registeredAsListener = false;
+      }
+   }
+
+   /**
+    * Remove the specified session from the cache (used for session.logout)
+    *
+    * @param ssoId the session id representing the shared single session
+    * @throws Exception
+    */
+   private void removeSSOFromCache(String ssoId) throws Exception
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
+      cache.remove(key);
+      key = new CacheKey(ssoId,CacheKey.Type.CREDENTIAL);
+      cache.remove(key);  // remove user credentials too
+   }
+
+   /**
+    * Remove one of the sessions associated with the users shared single session
+    * @param ssoId ssoId the session id representing the shared single session
+    * @param fullyQualifiedSessionId representing the session to remove
+    * @throws Exception
+    */
+   private void removeSessionFromCache(String ssoId, FullyQualifiedSessionId fullyQualifiedSessionId) throws Exception
+   {
+      CacheKey key = new CacheKey(ssoId,CacheKey.Type.SESSION);
+      AtomicMap m = AtomicMapLookup.getAtomicMap(cache, key, false);
+      if (m != null)
+      {
+         m.remove(fullyQualifiedSessionId);
+      }
+   }
+
+   /**
+    * Stores the given data to the clustered cache.
+    *
+    * @param ssoId    the id of the SSO session
+    * @param authType the type of authenticator (BASIC, CLIENT-CERT, DIGEST
+    *                 or FORM) used to authenticate the SSO.
+    * @param username the username (if any) used for the authentication
+    * @param password the password (if any) used for the authentication
+    */
+   private void storeCredentials(String ssoId, String authType, String username,
+      String password)
+   {
+      SSOCredentials credentials = new SSOCredentials(authType, username, password);
+
+      // Add this SSO to our list of in-process local adds so
+      // this.nodeModified() will ignore the addition
+      beingLocallyAdded.set(ssoId);
+
+      try
+      {
+         putCredentialsInCache(ssoId, credentials);
+      }
+      catch (Exception e)
+      {
+         log.error("Exception attempting to add Cache nodes for SSO " +
+            ssoId, e);
+      }
+      finally
+      {
+         beingLocallyAdded.set(null);
+      }
+   }
+
+   private void initThreadPool()
+   {
+      if (threadPoolName != null && getMBeanServer() != null)
+      {
+         try
+         {
+            ObjectName on = new ObjectName(threadPoolName);
+            threadPool = (ThreadPool) server.getAttribute(on, "Instance");
+            log.debug("Using ThreadPool at " + threadPoolName + " to clean dead members");
+         }
+         catch (Exception e)
+         {
+            log.info("Unable to access ThreadPool at " + threadPoolName +
+                     " -- will use individual threads for cleanup work");
+            log.debug("Failure to access ThreadPool due to: " + e);
+         }
+      }
+      else
+      {
+         log.debug("No ThreadPool configured -- will use individual threads for cleanup work");
+      }
+   }
+
+   private boolean isMissingCacheErrorLogged()
+   {
+      return missingCacheErrorLogged;
+   }
+
+   private void setMissingCacheErrorLogged(boolean missingCacheErrorLogged)
+   {
+      this.missingCacheErrorLogged = missingCacheErrorLogged;
+   }
+
+   private void logMissingCacheError()
+   {
+      StringBuffer msg = new StringBuffer("Cache is not set");
+      msg.append(" -- Cache must be started before SSOClusterManagerImpl ");
+      msg.append("can handle requests");
+
+      if (isMissingCacheErrorLogged())
+      {
+         // Just log it as a warning
+         log.warn(msg);
+      }
+      else
+      {
+         log.error(msg);
+         // Set a flag so we don't relog this error over and over
+         setMissingCacheErrorLogged(true);
+      }
+   }
+
+   // ---------------------------------------------------------  Outer Classes
+
+   /**
+    * Runnable that's run when the removal of a node from the cluster has been detected.
+    * Removes any SessionAddress objects associated with dead members from the
+    * session set of each SSO.  Operates locally only so each node can independently clean
+    * its SSOs without concern about replication lock conflicts.
+    */
+   private class SSOCleanerTask implements Runnable
+   {
+      private final boolean checkForEmpty;
+
+      private SSOCleanerTask(boolean checkForEmpty)
+      {
+         this.checkForEmpty = checkForEmpty;
+      }
+
+      public void run()
+      {
+         synchronized (cleanupMutex)
+         {
+            try
+            {
+               log.debug("check if we have to clean up SSO for any members that left the cluster.");
+               // Ensure we have a TransactionManager
+               if (tm == null)
+                  configureFromCache();
+
+               Set<String> ids = getSSOIds();
+               for (String sso : ids)
+               {
+                  cleanSSO(sso);
+               }
+            }
+            catch (Exception e)
+            {
+               log.error("Caught exception cleaning sessions from dead cluster members from SSOs ", e);
+            }
+         }
+      }
+
+      private void cleanSSO(String ssoId)
+      {
+         boolean doTx = false;
+         try
+         {
+            // Don't start tx if there is already one associated with this thread.
+            if(tm.getTransaction() == null)
+               doTx = true;
+
+            if(doTx)
+               tm.begin();
+
+            Set<FullyQualifiedSessionId> fullyQualifiedSessionIds = getSSOSessions(ssoId);
+            if (fullyQualifiedSessionIds.size() > 0)
+            {
+               for (FullyQualifiedSessionId fullyQualifiedSessionId : fullyQualifiedSessionIds)
+               {
+                  boolean alive;
+                  synchronized (currentView)
+                  {
+                     alive = currentView.contains(fullyQualifiedSessionId.getHostName());
+                  }
+                  if (!alive)
+                  {
+                     if (log.isTraceEnabled())
+                     {
+                        log.trace("Removing peer " + fullyQualifiedSessionId + " from SSO " + ssoId);
+                     }
+
+                     // Remove the peer node
+                     removeSessionFromCache(ssoId, fullyQualifiedSessionId);
+                  }
+               }
+            }
+            else if (checkForEmpty)
+            {
+               // SSO has no peers; notify our valve so we can expire it
+               ssoValve.notifySSOEmpty(ssoId);
+            }
+         }
+         catch (Exception e)
+         {
+            try
+            {
+               if(doTx)
+                  tm.setRollbackOnly();
+            }
+            catch (Exception ignored)
+            {
+            }
+            log.error("caught exception cleaning dead members from SSO " + ssoId, e);
+         }
+         finally
+         {
+            if (doTx)
+               endTransaction();
+         }
+      }
+   }
+
+}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImplTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImplTest.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImplTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,495 +0,0 @@
-package org.jboss.ha.framework.server;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.easymock.EasyMock;
-import org.infinispan.Cache;
-import org.infinispan.config.GlobalConfiguration;
-import org.infinispan.lifecycle.ComponentStatus;
-import org.infinispan.manager.CacheContainer;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.jboss.ha.framework.server.spi.HAPartitionCacheHandler;
-import org.jboss.ha.ispn.CacheContainerRegistry;
-import org.jgroups.ChannelFactory;
-import org.junit.Assert;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class HAPartitionCacheHandlerImplTest
-{
-   @Test
-   public void defaults() throws Exception
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
-      @SuppressWarnings("unchecked")
-      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
-      
-      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
-      EasyMock.expect(container.getCache()).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      // Release w/out start
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.releaseCache();
-
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-      
-      // Re-acquire
-      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
-      EasyMock.expect(container.getCache()).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-      
-      // start cache
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
-      cache.start();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.startCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      // Already started
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.startCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      // Release
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
-      cache.stop();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.releaseCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-   }
-
-   @Test
-   public void custom() throws Exception
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
-      @SuppressWarnings("unchecked")
-      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
-      
-      HAPartitionCacheHandlerImpl<Object, Object> handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      handler.setCacheContainerName("container");
-      handler.setCacheConfigName("cache");
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.expect(registry.getCacheContainer("container")).andReturn(container);
-      EasyMock.expect(container.getCache("cache")).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      // Release w/out start
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.releaseCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-      
-      // Re-acquire
-      EasyMock.expect(registry.getCacheContainer("container")).andReturn(container);
-      EasyMock.expect(container.getCache("cache")).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-      
-      // start cache
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
-      cache.start();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.startCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-      
-      // Already started
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.startCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      // Release
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
-      cache.stop();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.releaseCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-   }
-   
-   @Test
-   public void concurrent() throws Exception
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
-      @SuppressWarnings("unchecked")
-      final Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
-      
-      final InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      // Acquire and start cache
-      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
-      EasyMock.expect(container.getCache()).andReturn(cache);
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
-      cache.start();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-      handler.startCache();
-
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertSame(cache, handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-
-      EasyMock.makeThreadSafe(cache, true);
-      
-      Callable<Void> task = new Callable<Void>()
-      {
-         @Override
-         public Void call() throws Exception
-         {
-            handler.acquireCache();
-            
-            try
-            {
-               handler.startCache();
-            }
-            finally
-            {
-               handler.releaseCache();
-            }
-            
-            return null;
-         }
-      };
-      
-      int tasks = 100;
-      
-      ExecutorService executor = Executors.newFixedThreadPool(tasks);
-      List<Future<Void>> futures = new ArrayList<Future<Void>>(tasks);
-      
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING).times(tasks);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      List<Throwable> exceptions = new LinkedList<Throwable>();
-      
-      try
-      {
-         for (int i = 0; i < tasks; ++i)
-         {
-            futures.add(executor.submit(task));
-         }
-         
-         for (Future<Void> future: futures)
-         {
-            try
-            {
-               future.get();
-            }
-            catch (InterruptedException e)
-            {
-               Thread.currentThread().interrupt();
-            }
-            catch (ExecutionException e)
-            {
-               exceptions.add(e.getCause());
-            }
-         }
-      }
-      finally
-      {
-         executor.shutdown();
-      }
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertTrue(exceptions.toString(), exceptions.isEmpty());
-      Assert.assertSame(cache, handler.getCache());
-
-      EasyMock.reset(registry, container, cache);
-      
-      // Release
-      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
-      cache.stop();
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.releaseCache();
-      
-      EasyMock.verify(registry, container, cache);
-      
-      Assert.assertNull(handler.getCache());
-      
-      EasyMock.reset(registry, container, cache);
-   }
-   
-   @Test
-   public void startBeforeAcquire()
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      
-      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      EasyMock.replay(registry);
-      
-      Exception exception = null;
-      
-      try
-      {
-         handler.startCache();
-      }
-      catch (Exception e)
-      {
-         exception = e;
-      }
-      
-      EasyMock.verify(registry);
-      
-      Assert.assertNotNull(exception);
-      Assert.assertTrue(exception.toString(), exception instanceof IllegalStateException);
-      Assert.assertNull(handler.getCache());
-   }
-
-   @Test
-   public void releaseBeforeAcquire()
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      
-      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      EasyMock.replay(registry);
-      
-      Exception exception = null;
-      
-      try
-      {
-         handler.releaseCache();
-      }
-      catch (Exception e)
-      {
-         exception = e;
-      }
-      
-      EasyMock.verify(registry);
-      
-      Assert.assertNotNull(exception);
-      Assert.assertTrue(exception.toString(), exception instanceof IllegalStateException);
-      Assert.assertNull(handler.getCache());
-   }
-   
-   @Test
-   public void getCacheChannelFactoryBeforeAcquire()
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      
-      HAPartitionCacheHandler handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      try
-      {
-         handler.getCacheChannelFactory();
-         
-         Assert.fail("Cache was not yet acquired");
-      }
-      catch (Exception e)
-      {
-         Assert.assertEquals(IllegalStateException.class.getName(), e.getClass().getName());
-      }
-   }
-
-   @Test
-   public void getChannelStackNameBeforeAcquire()
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      
-      HAPartitionCacheHandler handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      try
-      {
-         handler.getChannelStackName();
-         
-         Assert.fail("Cache was not yet acquired");
-      }
-      catch (Exception e)
-      {
-         Assert.assertEquals(IllegalStateException.class.getName(), e.getClass().getName());
-      }
-   }
-   
-   @Test
-   public void getCacheChannelFactory() throws Exception
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
-      @SuppressWarnings("unchecked")
-      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
-      
-      HAPartitionCacheHandler handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
-      EasyMock.expect(container.getCache()).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-
-      EasyMock.verify(registry, container, cache);
-      EasyMock.reset(registry, container, cache);
-
-      EmbeddedCacheManager manager = EasyMock.createStrictMock(EmbeddedCacheManager.class);
-      ChannelFactory factory = EasyMock.createStrictMock(ChannelFactory.class);
-      GlobalConfiguration configuration = new GlobalConfiguration();
-      configuration.getTransportProperties().put("channelFactory", factory);
-      
-      EasyMock.expect(cache.getCacheManager()).andReturn(manager);
-      EasyMock.expect(manager.getGlobalConfiguration()).andReturn(configuration);
-      
-      EasyMock.replay(registry, container, cache, manager, factory);
-      
-      ChannelFactory result = handler.getCacheChannelFactory();
-
-      EasyMock.verify(registry, container, cache, manager, factory);
-      
-      Assert.assertSame(factory, result);
-      
-      EasyMock.reset(registry, container, cache, manager, factory);
-   }
-   
-   @Test
-   public void getChannelStackName() throws Exception
-   {
-      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
-      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
-      @SuppressWarnings("unchecked")
-      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
-      
-      HAPartitionCacheHandler handler = new HAPartitionCacheHandlerImpl<Object, Object>(registry);
-      
-      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
-      EasyMock.expect(container.getCache()).andReturn(cache);
-      
-      EasyMock.replay(registry, container, cache);
-      
-      handler.acquireCache();
-
-      EasyMock.verify(registry, container, cache);
-      EasyMock.reset(registry, container, cache);
-
-      EmbeddedCacheManager manager = EasyMock.createStrictMock(EmbeddedCacheManager.class);
-      GlobalConfiguration configuration = new GlobalConfiguration();
-      configuration.getTransportProperties().setProperty("stack", "udp");
-      
-      EasyMock.expect(cache.getCacheManager()).andReturn(manager);
-      EasyMock.expect(manager.getGlobalConfiguration()).andReturn(configuration);
-      
-      EasyMock.replay(registry, container, cache, manager);
-      
-      String result = handler.getChannelStackName();
-
-      EasyMock.verify(registry, container, cache, manager);
-      
-      Assert.assertEquals("udp", result);
-      
-      EasyMock.reset(registry, container, cache, manager);
-   }
-}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandlerTest.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/HAPartitionCacheHandlerImplTest.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandlerTest.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/framework/server/ispn/HAPartitionCacheHandlerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,496 @@
+package org.jboss.ha.framework.server.ispn;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.easymock.EasyMock;
+import org.infinispan.Cache;
+import org.infinispan.config.GlobalConfiguration;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.manager.CacheContainer;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.jboss.ha.framework.server.ispn.HAPartitionCacheHandler;
+import org.jboss.ha.framework.server.ispn.InfinispanHAPartitionCacheHandler;
+import org.jboss.ha.ispn.CacheContainerRegistry;
+import org.jgroups.ChannelFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+ at SuppressWarnings("deprecation")
+public class HAPartitionCacheHandlerTest
+{
+   @Test
+   public void defaults() throws Exception
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
+      @SuppressWarnings("unchecked")
+      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
+      
+      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
+      EasyMock.expect(container.getCache()).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      // Release w/out start
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.releaseCache();
+
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+      
+      // Re-acquire
+      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
+      EasyMock.expect(container.getCache()).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+      
+      // start cache
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
+      cache.start();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.startCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      // Already started
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.startCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      // Release
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
+      cache.stop();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.releaseCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+   }
+
+   @Test
+   public void custom() throws Exception
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
+      @SuppressWarnings("unchecked")
+      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
+      
+      HAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      handler.setCacheContainerName("container");
+      handler.setCacheConfigName("cache");
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.expect(registry.getCacheContainer("container")).andReturn(container);
+      EasyMock.expect(container.getCache("cache")).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      // Release w/out start
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.releaseCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+      
+      // Re-acquire
+      EasyMock.expect(registry.getCacheContainer("container")).andReturn(container);
+      EasyMock.expect(container.getCache("cache")).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+      
+      // start cache
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
+      cache.start();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.startCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+      
+      // Already started
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.startCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      // Release
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
+      cache.stop();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.releaseCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+   }
+   
+   @Test
+   public void concurrent() throws Exception
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
+      @SuppressWarnings("unchecked")
+      final Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
+      
+      final InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      // Acquire and start cache
+      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
+      EasyMock.expect(container.getCache()).andReturn(cache);
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.INSTANTIATED);
+      cache.start();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+      handler.startCache();
+
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertSame(cache, handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+
+      EasyMock.makeThreadSafe(cache, true);
+      
+      Callable<Void> task = new Callable<Void>()
+      {
+         @Override
+         public Void call() throws Exception
+         {
+            handler.acquireCache();
+            
+            try
+            {
+               handler.startCache();
+            }
+            finally
+            {
+               handler.releaseCache();
+            }
+            
+            return null;
+         }
+      };
+      
+      int tasks = 100;
+      
+      ExecutorService executor = Executors.newFixedThreadPool(tasks);
+      List<Future<Void>> futures = new ArrayList<Future<Void>>(tasks);
+      
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING).times(tasks);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      List<Throwable> exceptions = new LinkedList<Throwable>();
+      
+      try
+      {
+         for (int i = 0; i < tasks; ++i)
+         {
+            futures.add(executor.submit(task));
+         }
+         
+         for (Future<Void> future: futures)
+         {
+            try
+            {
+               future.get();
+            }
+            catch (InterruptedException e)
+            {
+               Thread.currentThread().interrupt();
+            }
+            catch (ExecutionException e)
+            {
+               exceptions.add(e.getCause());
+            }
+         }
+      }
+      finally
+      {
+         executor.shutdown();
+      }
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertTrue(exceptions.toString(), exceptions.isEmpty());
+      Assert.assertSame(cache, handler.getCache());
+
+      EasyMock.reset(registry, container, cache);
+      
+      // Release
+      EasyMock.expect(cache.getStatus()).andReturn(ComponentStatus.RUNNING);
+      cache.stop();
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.releaseCache();
+      
+      EasyMock.verify(registry, container, cache);
+      
+      Assert.assertNull(handler.getCache());
+      
+      EasyMock.reset(registry, container, cache);
+   }
+   
+   @Test
+   public void startBeforeAcquire()
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      
+      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      EasyMock.replay(registry);
+      
+      Exception exception = null;
+      
+      try
+      {
+         handler.startCache();
+      }
+      catch (Exception e)
+      {
+         exception = e;
+      }
+      
+      EasyMock.verify(registry);
+      
+      Assert.assertNotNull(exception);
+      Assert.assertTrue(exception.toString(), exception instanceof IllegalStateException);
+      Assert.assertNull(handler.getCache());
+   }
+
+   @Test
+   public void releaseBeforeAcquire()
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      
+      InfinispanHAPartitionCacheHandler<Object, Object> handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      EasyMock.replay(registry);
+      
+      Exception exception = null;
+      
+      try
+      {
+         handler.releaseCache();
+      }
+      catch (Exception e)
+      {
+         exception = e;
+      }
+      
+      EasyMock.verify(registry);
+      
+      Assert.assertNotNull(exception);
+      Assert.assertTrue(exception.toString(), exception instanceof IllegalStateException);
+      Assert.assertNull(handler.getCache());
+   }
+   
+   @Test
+   public void getCacheChannelFactoryBeforeAcquire()
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      
+      org.jboss.ha.framework.server.spi.HAPartitionCacheHandler handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      try
+      {
+         handler.getCacheChannelFactory();
+         
+         Assert.fail("Cache was not yet acquired");
+      }
+      catch (Exception e)
+      {
+         Assert.assertEquals(IllegalStateException.class.getName(), e.getClass().getName());
+      }
+   }
+
+   @Test
+   public void getChannelStackNameBeforeAcquire()
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      
+      org.jboss.ha.framework.server.spi.HAPartitionCacheHandler handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      try
+      {
+         handler.getChannelStackName();
+         
+         Assert.fail("Cache was not yet acquired");
+      }
+      catch (Exception e)
+      {
+         Assert.assertEquals(IllegalStateException.class.getName(), e.getClass().getName());
+      }
+   }
+   
+   @Test
+   public void getCacheChannelFactory() throws Exception
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
+      @SuppressWarnings("unchecked")
+      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
+      
+      org.jboss.ha.framework.server.spi.HAPartitionCacheHandler handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
+      EasyMock.expect(container.getCache()).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+
+      EasyMock.verify(registry, container, cache);
+      EasyMock.reset(registry, container, cache);
+
+      EmbeddedCacheManager manager = EasyMock.createStrictMock(EmbeddedCacheManager.class);
+      ChannelFactory factory = EasyMock.createStrictMock(ChannelFactory.class);
+      GlobalConfiguration configuration = new GlobalConfiguration();
+      configuration.getTransportProperties().put("channelFactory", factory);
+      
+      EasyMock.expect(cache.getCacheManager()).andReturn(manager);
+      EasyMock.expect(manager.getGlobalConfiguration()).andReturn(configuration);
+      
+      EasyMock.replay(registry, container, cache, manager, factory);
+      
+      ChannelFactory result = handler.getCacheChannelFactory();
+
+      EasyMock.verify(registry, container, cache, manager, factory);
+      
+      Assert.assertSame(factory, result);
+      
+      EasyMock.reset(registry, container, cache, manager, factory);
+   }
+   
+   @Test
+   public void getChannelStackName() throws Exception
+   {
+      CacheContainerRegistry registry = EasyMock.createStrictMock(CacheContainerRegistry.class);
+      CacheContainer container = EasyMock.createStrictMock(CacheContainer.class);
+      @SuppressWarnings("unchecked")
+      Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
+      
+      org.jboss.ha.framework.server.spi.HAPartitionCacheHandler handler = new HAPartitionCacheHandler<Object, Object>(registry);
+      
+      EasyMock.expect(registry.getCacheContainer(null)).andReturn(container);
+      EasyMock.expect(container.getCache()).andReturn(cache);
+      
+      EasyMock.replay(registry, container, cache);
+      
+      handler.acquireCache();
+
+      EasyMock.verify(registry, container, cache);
+      EasyMock.reset(registry, container, cache);
+
+      EmbeddedCacheManager manager = EasyMock.createStrictMock(EmbeddedCacheManager.class);
+      GlobalConfiguration configuration = new GlobalConfiguration();
+      configuration.getTransportProperties().setProperty("stack", "udp");
+      
+      EasyMock.expect(cache.getCacheManager()).andReturn(manager);
+      EasyMock.expect(manager.getGlobalConfiguration()).andReturn(configuration);
+      
+      EasyMock.replay(registry, container, cache, manager);
+      
+      String result = handler.getChannelStackName();
+
+      EasyMock.verify(registry, container, cache, manager);
+      
+      Assert.assertEquals("udp", result);
+      
+      EasyMock.reset(registry, container, cache, manager);
+   }
+}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl)

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntryTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/AtomicMapEntryTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/AtomicMapEntryTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,10 +19,11 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.easymock.EasyMock;
 import org.infinispan.atomic.AtomicMap;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.AtomicMapEntry;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
 import org.junit.Assert;
 import org.junit.Test;

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/BatchingManagerTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/BatchingManagerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,149 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import javax.transaction.Status;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import org.easymock.EasyMock;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.BatchingManager;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * @author Paul Ferraro
- *
- */
-public class BatchingManagerTest
-{
-   private final TransactionManager tm = EasyMock.createStrictMock(TransactionManager.class);
-   private final BatchingManager bm = new BatchingManagerImpl(this.tm);
-   
-   @Test
-   public void isBatchInProgress() throws Exception
-   {
-      EasyMock.expect(this.tm.getTransaction()).andReturn(null);
-      
-      EasyMock.replay(this.tm);
-      
-      boolean result = this.bm.isBatchInProgress();
-      
-      EasyMock.verify(this.tm);
-      
-      Assert.assertFalse(result);
-      
-      EasyMock.reset(this.tm);
-      
-      
-      Transaction transaction = EasyMock.createStrictMock(Transaction.class);
-      
-      EasyMock.expect(this.tm.getTransaction()).andReturn(transaction);
-      
-      EasyMock.replay(this.tm);
-      
-      result = this.bm.isBatchInProgress();
-      
-      EasyMock.verify(this.tm);
-      
-      Assert.assertTrue(result);
-      
-      EasyMock.reset(this.tm);
-   }
-   
-   @Test
-   public void setRollbackOnly() throws Exception
-   {
-      this.tm.setRollbackOnly();
-      
-      EasyMock.replay(this.tm);
-      
-      this.bm.setBatchRollbackOnly();
-      
-      EasyMock.verify(this.tm);
-      
-      EasyMock.reset(this.tm);
-   }
-   
-   @Test
-   public void startBatch() throws Exception
-   {
-      this.tm.begin();
-      
-      EasyMock.replay(this.tm);
-      
-      this.bm.startBatch();
-      
-      EasyMock.verify(this.tm);
-      
-      EasyMock.reset(this.tm);
-   }
-   
-   @Test
-   public void endBatch() throws Exception
-   {
-      this.commitBatch(Status.STATUS_ACTIVE);
-      this.commitBatch(Status.STATUS_COMMITTED);
-      this.commitBatch(Status.STATUS_COMMITTING);
-      this.rollbackBatch(Status.STATUS_MARKED_ROLLBACK);
-      this.commitBatch(Status.STATUS_NO_TRANSACTION);
-      this.commitBatch(Status.STATUS_PREPARED);
-      this.commitBatch(Status.STATUS_PREPARING);
-      this.commitBatch(Status.STATUS_ROLLEDBACK);
-      this.commitBatch(Status.STATUS_ROLLING_BACK);
-      this.commitBatch(Status.STATUS_UNKNOWN);
-   }
-   
-   private void commitBatch(int status) throws Exception
-   {
-      Transaction transaction = EasyMock.createStrictMock(Transaction.class);
-      
-      EasyMock.expect(this.tm.getTransaction()).andReturn(transaction);
-      EasyMock.expect(transaction.getStatus()).andReturn(status);
-      
-      this.tm.commit();
-      
-      EasyMock.replay(this.tm, transaction);
-      
-      this.bm.endBatch();
-      
-      EasyMock.verify(this.tm, transaction);
-      EasyMock.reset(this.tm, transaction);
-   }
-   
-   private void rollbackBatch(int status) throws Exception
-   {
-      Transaction transaction = EasyMock.createStrictMock(Transaction.class);
-      
-      EasyMock.expect(this.tm.getTransaction()).andReturn(transaction);
-      EasyMock.expect(transaction.getStatus()).andReturn(status);
-      
-      this.tm.rollback();
-      
-      EasyMock.replay(this.tm, transaction);
-      
-      this.bm.endBatch();
-      
-      EasyMock.verify(this.tm, transaction);
-      EasyMock.reset(this.tm, transaction);
-   }
-}

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorageTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/CoarseSessionAttributeStorageTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/CoarseSessionAttributeStorageTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,14 +19,18 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.Collections;
 import java.util.Map;
 
 import org.easymock.EasyMock;
 import org.infinispan.atomic.AtomicMap;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.AtomicMapEntry;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.CoarseSessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingSessionGranularitySessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 import org.junit.Assert;
 import org.junit.Test;
 

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerFactoryTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerFactoryTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,16 +19,21 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.easymock.EasyMock;
 import org.jboss.ha.ispn.atomic.AtomicMapFactory;
 import org.jboss.ha.ispn.invoker.CacheInvoker;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.DistributedCacheManagerFactory;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.DistributedCacheManager;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorageFactory;
 import org.jboss.metadata.web.jboss.ReplicationConfig;
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshallerFactory;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -50,7 +55,7 @@
    @Test
    public void test() throws Exception
    {
-      DistributedCacheManagerFactoryImpl factory = new DistributedCacheManagerFactoryImpl();
+      DistributedCacheManagerFactory factory = new DistributedCacheManagerFactory();
       
       factory.setAtomicMapFactory(atomicMapFactory);
       factory.setSessionAttributeStorageFactory(this.storageFactory);
@@ -68,12 +73,12 @@
       
       EasyMock.replay(this.storageFactory, this.marshallerFactory, this.invoker, this.manager, this.storage, this.marshaller, this.atomicMapFactory);
       
-      DistributedCacheManager<?> result = factory.getDistributedCacheManager(this.manager);
+      org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager<?> result = factory.getDistributedCacheManager(this.manager);
       
       EasyMock.verify(this.storageFactory, this.marshallerFactory, this.invoker, this.manager, this.storage, this.marshaller, this.atomicMapFactory);
       
       Assert.assertNotNull(result);
-      Assert.assertTrue(result instanceof DistributedCacheManagerImpl);
+      Assert.assertTrue(result instanceof DistributedCacheManager);
       
       EasyMock.reset(this.storageFactory, this.marshallerFactory, this.invoker, this.manager, this.storage, this.marshaller, this.atomicMapFactory);
    }

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/DistributedCacheManagerTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/DistributedCacheManagerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,7 +19,7 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.Collections;
 import java.util.Map;
@@ -42,9 +42,11 @@
 import org.jboss.ha.ispn.CacheContainerRegistry;
 import org.jboss.ha.ispn.atomic.AtomicMapFactory;
 import org.jboss.ha.ispn.invoker.CacheInvoker;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.AtomicMapEntry;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.DistributedCacheManager;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage;
 import org.jboss.metadata.web.jboss.ReplicationConfig;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributableSessionMetadata;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.DistributedCacheManager;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.IncomingDistributableSessionData;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingDistributableSessionData;
@@ -96,9 +98,9 @@
       this.start("default", "session-cache", null, "", "localhost/ROOT", config, ComponentStatus.INSTANTIATED, true, new Configuration());
    }
    
-   private DistributedCacheManagerImpl<OutgoingDistributableSessionData> start(String containerName, String templateCacheName, String hostName, String contextName, String cacheName, ReplicationConfig config, ComponentStatus cacheStatus, boolean startCache, Configuration configuration)
+   private DistributedCacheManager<OutgoingDistributableSessionData> start(String containerName, String templateCacheName, String hostName, String contextName, String cacheName, ReplicationConfig config, ComponentStatus cacheStatus, boolean startCache, Configuration configuration)
    {
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = new DistributedCacheManagerImpl<OutgoingDistributableSessionData>(this.manager, this.registry, this.storage, this.invoker, this.atomicMapFactory);
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = new DistributedCacheManager<OutgoingDistributableSessionData>(this.manager, this.registry, this.storage, this.invoker, this.atomicMapFactory);
       
       @SuppressWarnings("unchecked")
       Cache<Object, Object> cache = EasyMock.createStrictMock(Cache.class);
@@ -138,7 +140,7 @@
       return manager;
    }
    
-   private DistributedCacheManagerImpl<OutgoingDistributableSessionData> startDistributedCacheManager()
+   private DistributedCacheManager<OutgoingDistributableSessionData> startDistributedCacheManager()
    {
       ReplicationConfig config = new ReplicationConfig();
       config.setCacheName("session-cache");
@@ -183,7 +185,7 @@
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> map = EasyMock.createNiceMock(AtomicMap.class);
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
       
       String sessionId = "abc";
       int version = 10;
@@ -210,7 +212,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker, this.atomicMapFactory, data, map);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       
       EasyMock.expect(this.atomicMapFactory.getAtomicMap(EasyMock.same(cache), EasyMock.same(sessionId), EasyMock.eq(true))).andReturn(map);
             
@@ -240,7 +242,7 @@
       AtomicMap<Object, Object> map = EasyMock.createNiceMock(AtomicMap.class);
       Map<String, Object> attributes = Collections.emptyMap();
       
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
 
       Integer version = Integer.valueOf(10);
       Long timestamp = Long.valueOf(System.currentTimeMillis());
@@ -295,7 +297,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker, this.atomicMapFactory, map);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> expectedMap = EasyMock.createMock(AtomicMap.class);
       
@@ -322,7 +324,7 @@
    
    private void getMissingSessionDataNoOwner(boolean includeAttributes)
    {
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -339,7 +341,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker, this.atomicMapFactory);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> expectedMap = EasyMock.createMock(AtomicMap.class);
       
@@ -384,7 +386,7 @@
    {
       String sessionId = "abc";
       
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -398,7 +400,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> expectedMap = EasyMock.createMock(AtomicMap.class);
       
@@ -420,7 +422,7 @@
    {
       String sessionId = "abc";
       
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -434,7 +436,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> expectedMap = EasyMock.createMock(AtomicMap.class);
       
@@ -458,7 +460,7 @@
    {
       String sessionId = "abc";
       
-      Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>>>();
+      Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>> capturedOperation = new Capture<DistributedCacheManager.Operation<AtomicMap<Object, Object>>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -472,7 +474,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker);
       
       
-      DistributedCacheManagerImpl.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<AtomicMap<Object, Object>> operation = capturedOperation.getValue();
       @SuppressWarnings("unchecked")
       AtomicMap<Object, Object> expectedMap = EasyMock.createMock(AtomicMap.class);
       
@@ -509,7 +511,7 @@
    {
       String sessionId = "abc";
       
-      Capture<DistributedCacheManagerImpl.Operation<Void>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<Void>>();
+      Capture<DistributedCacheManager.Operation<Void>> capturedOperation = new Capture<DistributedCacheManager.Operation<Void>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -523,7 +525,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker);
       
       
-      DistributedCacheManagerImpl.Operation<Void> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<Void> operation = capturedOperation.getValue();
       
       this.cache.evict(sessionId);
       
@@ -543,7 +545,7 @@
    {
       String sessionId = "abc";
       
-      Capture<DistributedCacheManagerImpl.Operation<Void>> capturedOperation = new Capture<DistributedCacheManagerImpl.Operation<Void>>();
+      Capture<DistributedCacheManager.Operation<Void>> capturedOperation = new Capture<DistributedCacheManager.Operation<Void>>();
       
       DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
@@ -557,7 +559,7 @@
       EasyMock.reset(this.manager, this.container, this.storage, this.cache, this.invoker);
       
       
-      DistributedCacheManagerImpl.Operation<Void> operation = capturedOperation.getValue();
+      DistributedCacheManager.Operation<Void> operation = capturedOperation.getValue();
       
       this.cache.evict(sessionId);
       
@@ -650,7 +652,7 @@
    {
       CacheEntryRemovedEvent event = EasyMock.createNiceMock(CacheEntryRemovedEvent.class);
       
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
       
       EasyMock.expect(event.isPre()).andReturn(true);
@@ -693,7 +695,7 @@
    {
       CacheEntryModifiedEvent event = EasyMock.createNiceMock(CacheEntryModifiedEvent.class);
       
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
       
       EasyMock.expect(event.isPre()).andReturn(true);
@@ -748,7 +750,7 @@
    {
       CacheEntryActivatedEvent event = EasyMock.createNiceMock(CacheEntryActivatedEvent.class);
       
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       
       EasyMock.expect(event.isPre()).andReturn(true);
       
@@ -784,7 +786,7 @@
    @Test
    public void isLocalReplicationMode()
    {
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       String sessionId = "ABC123";
       
       EasyMock.expect(this.cache.getAdvancedCache()).andReturn(this.cache);
@@ -812,7 +814,7 @@
    {
       DistributionManager distManager = EasyMock.createStrictMock(DistributionManager.class);
       
-      DistributedCacheManagerImpl<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
+      DistributedCacheManager<OutgoingDistributableSessionData> manager = this.startDistributedCacheManager();
       String sessionId = "ABC123";
       
       EasyMock.expect(this.cache.getAdvancedCache()).andReturn(this.cache);

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorageTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/FineSessionAttributeStorageTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/FineSessionAttributeStorageTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,7 +19,7 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import java.util.AbstractMap;
 import java.util.Arrays;
@@ -31,7 +31,10 @@
 
 import org.easymock.EasyMock;
 import org.infinispan.atomic.AtomicMap;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.FineSessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage;
 import org.jboss.web.tomcat.service.session.distributedcache.spi.OutgoingAttributeGranularitySessionData;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 import org.junit.Assert;
 import org.junit.Test;
 

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshallerFactoryTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerFactoryTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,53 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import org.junit.Assert;
-
-import org.easymock.EasyMock;
-import org.jboss.ha.framework.interfaces.ObjectStreamSource;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-import org.junit.Test;
-
-/**
- * @author Paul Ferraro
- *
- */
-public class SessionAttributeMarshallerFactoryTest
-{
-   @Test
-   public void test()
-   {
-      ObjectStreamSource source = EasyMock.createStrictMock(ObjectStreamSource.class);
-      LocalDistributableSessionManager manager = EasyMock.createStrictMock(LocalDistributableSessionManager.class);
-      SessionAttributeMarshallerFactory factory = new SessionAttributeMarshallerFactoryImpl(source);
-      
-      EasyMock.replay(source, manager);
-      
-      SessionAttributeMarshaller marshaller = factory.createMarshaller(manager);
-      
-      EasyMock.verify(source, manager);
-      
-      Assert.assertNotNull(marshaller);
-      Assert.assertTrue(marshaller instanceof SessionAttributeMarshallerImpl);
-   }
-}

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeMarshallerTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeMarshallerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,136 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, 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.jboss.ha.web.tomcat.service.session.distributedcache.impl;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.Date;
-
-import org.easymock.EasyMock;
-import org.jboss.ha.framework.server.MarshalledValueObjectStreamSource;
-import org.jboss.web.tomcat.service.session.distributedcache.spi.LocalDistributableSessionManager;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * @author Paul Ferraro
- *
- */
-public class SessionAttributeMarshallerTest
-{
-   private final LocalDistributableSessionManager manager = EasyMock.createStrictMock(LocalDistributableSessionManager.class);
-   
-   private final SessionAttributeMarshaller marshaller = new SessionAttributeMarshallerImpl(this.manager, new MarshalledValueObjectStreamSource());
-   
-   @Test
-   public void test() throws IOException, ClassNotFoundException
-   {
-      this.test((Serializable) null, true);
-      this.test("test", true);
-      this.test(Boolean.TRUE, true);
-      this.test(Byte.valueOf(Byte.MAX_VALUE), true);
-      this.test(Character.valueOf(Character.MAX_VALUE), true);
-      this.test(Double.valueOf(Double.MAX_VALUE), true);
-      this.test(Float.valueOf(Float.MAX_VALUE), true);
-      this.test(Integer.valueOf(Integer.MAX_VALUE), true);
-      this.test(Long.valueOf(Long.MAX_VALUE), true);
-      this.test(Short.valueOf(Short.MAX_VALUE), true);
-      this.test(new String[] { "test" }, true);
-      this.test(new boolean[] { Boolean.TRUE }, true);
-      this.test(new byte[] { Byte.MAX_VALUE }, true);
-      this.test(new char[] { Character.MAX_VALUE }, true);
-      this.test(new double[] { Double.MAX_VALUE }, true);
-      this.test(new float[] { Float.MAX_VALUE }, true);
-      this.test(new int[] { Integer.MAX_VALUE }, true);
-      this.test(new long[] { Long.MAX_VALUE }, true);
-      this.test(new short[] { Short.MAX_VALUE }, true);
-      this.test(new Boolean[] { Boolean.TRUE }, true);
-      this.test(new Byte[] { Byte.valueOf(Byte.MAX_VALUE) }, true);
-      this.test(new Character[] { Character.valueOf(Character.MAX_VALUE) }, true);
-      this.test(new Double[] { Double.valueOf(Double.MAX_VALUE) }, true);
-      this.test(new Float[] { Float.valueOf(Float.MAX_VALUE) }, true);
-      this.test(new Integer[] { Integer.valueOf(Integer.MAX_VALUE) }, true);
-      this.test(new Long[] { Long.valueOf(Long.MAX_VALUE) }, true);
-      this.test(new Short[] { Short.valueOf(Short.MAX_VALUE) }, true);
-      this.test(this.getClass(), false);
-      this.test(new Date(System.currentTimeMillis()), false);
-      this.test(new Object(), false);
-   }
-   
-   private void test(Object original, boolean same) throws IOException, ClassNotFoundException
-   {
-      EasyMock.replay(this.manager);
-      
-      try
-      {
-         Object marshalled = this.marshaller.marshal(original);
-         
-         if (original != null)
-         {
-            Assert.assertTrue(original instanceof Serializable);
-         }
-         if (marshalled != null)
-         {
-            Assert.assertTrue(marshalled instanceof Serializable);
-         }
-         
-         if (same)
-         {
-            Assert.assertSame(original, marshalled);
-         }
-         else
-         {
-            Assert.assertNotSame(original, marshalled);
-         }
-         
-         EasyMock.verify(this.manager);
-         EasyMock.reset(this.manager);
-         
-         if (!same)
-         {
-            EasyMock.expect(this.manager.getApplicationClassLoader()).andReturn(Thread.currentThread().getContextClassLoader());
-         }
-         
-         EasyMock.replay(this.manager);
-         
-         Object unmarshalled = this.marshaller.unmarshal(marshalled);
-         
-         if (same)
-         {
-            Assert.assertSame(marshalled, unmarshalled);
-         }
-         else
-         {
-            Assert.assertNotSame(marshalled, unmarshalled);
-            Assert.assertEquals(original, unmarshalled);
-         }
-      }
-      catch (IllegalArgumentException e)
-      {
-         Assert.assertFalse(same);
-         Assert.assertFalse(original instanceof Serializable);
-      }
-      
-      EasyMock.verify(this.manager);
-      EasyMock.reset(this.manager);
-   }
-}

Modified: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/impl/SessionAttributeStorageFactoryTest.java	2010-08-02 15:54:06 UTC (rev 107268)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/distributedcache/ispn/SessionAttributeStorageFactoryTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -19,10 +19,16 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
-package org.jboss.ha.web.tomcat.service.session.distributedcache.impl;
+package org.jboss.ha.web.tomcat.service.session.distributedcache.ispn;
 
 import org.easymock.EasyMock;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.CoarseSessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.FineSessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorage;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorageFactory;
+import org.jboss.ha.web.tomcat.service.session.distributedcache.ispn.SessionAttributeStorageFactoryImpl;
 import org.jboss.metadata.web.jboss.ReplicationGranularity;
+import org.jboss.web.tomcat.service.session.distributedcache.spi.SessionAttributeMarshaller;
 import org.junit.Assert;
 import org.junit.Test;
 

Deleted: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerTest.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerTest.java	2010-08-02 17:08:02 UTC (rev 107279)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -1,71 +0,0 @@
-package org.jboss.ha.web.tomcat.service.session.sso;
-
-import org.easymock.EasyMock;
-import org.infinispan.AdvancedCache;
-import org.infinispan.Cache;
-import org.infinispan.atomic.AtomicMap;
-import org.jboss.ha.framework.server.InfinispanHAPartitionCacheHandler;
-import org.jboss.web.tomcat.service.sso.spi.FullyQualifiedSessionId;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.Before;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-public class SSOClusterManagerTest
-{
-
-   SSOClusterManagerImpl ssoManager;
-   Cache<Object, Object> cache;
-   String ssoId;
-
-   @Before
-   public void setup() throws Exception
-   {
-      ssoManager = new SSOClusterManagerImpl();
-      cache = EasyMock.createMock(Cache.class);
-      InfinispanHAPartitionCacheHandler cacheHandler = EasyMock.createMock(InfinispanHAPartitionCacheHandler.class);
-      EasyMock.expect(cacheHandler.getCache()).andReturn(cache);
-      EasyMock.expectLastCall().anyTimes();
-
-      cache.addListener(ssoManager);
-
-      AdvancedCache advancedCache = EasyMock.createMock(AdvancedCache.class);
-      EasyMock.expect(cache.getAdvancedCache()).andReturn(advancedCache);
-      EasyMock.expectLastCall().anyTimes();
-
-      Transaction transaction = EasyMock.createMock(Transaction.class);
-      TransactionManager tm = EasyMock.createMock(TransactionManager.class);
-      EasyMock.expect(tm.getTransaction()).andReturn(transaction);
-      EasyMock.expectLastCall().anyTimes();
-
-      tm.begin();
-      EasyMock.expectLastCall().anyTimes();
-      tm.rollback();
-      EasyMock.expectLastCall().anyTimes();
-      tm.commit();
-      EasyMock.expectLastCall().anyTimes();
-
-      EasyMock.expect(advancedCache.getTransactionManager()).andReturn(tm);
-      EasyMock.expectLastCall().anyTimes();
-
-      ssoManager.setCacheHandler(cacheHandler);
-      ssoId = "sso session 1";
-      AtomicMap atomicMap = EasyMock.createMock(AtomicMap.class);
-      EasyMock.expect(cache.get(EasyMock.anyObject())).andReturn(atomicMap);
-      EasyMock.expectLastCall().anyTimes();
-      EasyMock.replay(cache, cacheHandler, advancedCache, tm, transaction, atomicMap);
-   }
-
-   @Test
-   public void addSession() throws Exception
-   {
-      ssoManager.start();
-
-      FullyQualifiedSessionId fqs = new FullyQualifiedSessionId(ssoId, "context", "Boston");
-      ssoManager.addSession(ssoId, fqs);
-     
-   }
-
-
-}

Copied: projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManagerTest.java (from rev 107268, projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/SSOClusterManagerTest.java)
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManagerTest.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/test/java/org/jboss/ha/web/tomcat/service/session/sso/ispn/SSOClusterManagerTest.java	2010-08-02 17:11:58 UTC (rev 107280)
@@ -0,0 +1,72 @@
+package org.jboss.ha.web.tomcat.service.session.sso.ispn;
+
+import org.easymock.EasyMock;
+import org.infinispan.AdvancedCache;
+import org.infinispan.Cache;
+import org.infinispan.atomic.AtomicMap;
+import org.jboss.ha.framework.server.ispn.InfinispanHAPartitionCacheHandler;
+import org.jboss.ha.web.tomcat.service.session.sso.ispn.SSOClusterManager;
+import org.jboss.web.tomcat.service.sso.spi.FullyQualifiedSessionId;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.Before;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+public class SSOClusterManagerTest
+{
+
+   SSOClusterManager ssoManager;
+   Cache<Object, Object> cache;
+   String ssoId;
+
+   @Before
+   public void setup() throws Exception
+   {
+      ssoManager = new SSOClusterManager();
+      cache = EasyMock.createMock(Cache.class);
+      InfinispanHAPartitionCacheHandler cacheHandler = EasyMock.createMock(InfinispanHAPartitionCacheHandler.class);
+      EasyMock.expect(cacheHandler.getCache()).andReturn(cache);
+      EasyMock.expectLastCall().anyTimes();
+
+      cache.addListener(ssoManager);
+
+      AdvancedCache advancedCache = EasyMock.createMock(AdvancedCache.class);
+      EasyMock.expect(cache.getAdvancedCache()).andReturn(advancedCache);
+      EasyMock.expectLastCall().anyTimes();
+
+      Transaction transaction = EasyMock.createMock(Transaction.class);
+      TransactionManager tm = EasyMock.createMock(TransactionManager.class);
+      EasyMock.expect(tm.getTransaction()).andReturn(transaction);
+      EasyMock.expectLastCall().anyTimes();
+
+      tm.begin();
+      EasyMock.expectLastCall().anyTimes();
+      tm.rollback();
+      EasyMock.expectLastCall().anyTimes();
+      tm.commit();
+      EasyMock.expectLastCall().anyTimes();
+
+      EasyMock.expect(advancedCache.getTransactionManager()).andReturn(tm);
+      EasyMock.expectLastCall().anyTimes();
+
+      ssoManager.setCacheHandler(cacheHandler);
+      ssoId = "sso session 1";
+      AtomicMap atomicMap = EasyMock.createMock(AtomicMap.class);
+      EasyMock.expect(cache.get(EasyMock.anyObject())).andReturn(atomicMap);
+      EasyMock.expectLastCall().anyTimes();
+      EasyMock.replay(cache, cacheHandler, advancedCache, tm, transaction, atomicMap);
+   }
+
+   @Test
+   public void addSession() throws Exception
+   {
+      ssoManager.start();
+
+      FullyQualifiedSessionId fqs = new FullyQualifiedSessionId(ssoId, "context", "Boston");
+      ssoManager.addSession(ssoId, fqs);
+     
+   }
+
+
+}



More information about the jboss-cvs-commits mailing list