[jbosscache-commits] JBoss Cache SVN: r7679 - in core/branches/flat/src: main/java/org/horizon/config and 28 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Wed Feb 11 04:52:13 EST 2009


Author: manik.surtani at jboss.com
Date: 2009-02-11 04:52:13 -0500 (Wed, 11 Feb 2009)
New Revision: 7679

Added:
   core/branches/flat/src/main/java/org/horizon/config/CacheLoaderManagerConfig.java
   core/branches/flat/src/main/java/org/horizon/container/CachedValue.java
   core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java
   core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/loader/
   core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoader.java
   core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoaderConfig.java
   core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheStore.java
   core/branches/flat/src/main/java/org/horizon/loader/CacheLoader.java
   core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderConfig.java
   core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManager.java
   core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManagerImpl.java
   core/branches/flat/src/main/java/org/horizon/loader/CacheStore.java
   core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/
   core/branches/flat/src/main/java/org/horizon/loader/decorators/AbstractDelegatingStore.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/AsyncStore.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/ChainingCacheLoader.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/ReadOnlyStore.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStore.java
   core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStoreConfig.java
   core/branches/flat/src/main/java/org/horizon/loader/jdbc/
   core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoader.java
   core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoaderConfig.java
   core/branches/flat/src/main/java/org/horizon/loader/modifications/
   core/branches/flat/src/main/java/org/horizon/loader/modifications/Clear.java
   core/branches/flat/src/main/java/org/horizon/loader/modifications/Modification.java
   core/branches/flat/src/main/java/org/horizon/loader/modifications/Remove.java
   core/branches/flat/src/main/java/org/horizon/loader/modifications/Store.java
   core/branches/flat/src/test/java/org/horizon/loader/
   core/branches/flat/src/test/java/org/horizon/loader/BaseCacheLoaderTest.java
   core/branches/flat/src/test/java/org/horizon/loader/dummy/
   core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoader.java
   core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoaderTest.java
Removed:
   core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java
   core/branches/flat/src/main/java/org/horizon/config/EvictionAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/container/CachedEntry.java
   core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
   core/branches/flat/src/main/java/org/horizon/loaderold/
Modified:
   core/branches/flat/src/main/java/org/horizon/config/Configuration.java
   core/branches/flat/src/main/java/org/horizon/config/EvictionConfig.java
   core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigHelper.java
   core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java
   core/branches/flat/src/main/java/org/horizon/config/parsing/element/LoadersElementParser.java
   core/branches/flat/src/main/java/org/horizon/container/DataContainer.java
   core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
   core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/EvictionManagerImpl.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithm.java
   core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithmConfig.java
   core/branches/flat/src/main/java/org/horizon/factories/EmptyConstructorNamedCacheFactory.java
   core/branches/flat/src/main/java/org/horizon/interceptors/CacheLoaderInterceptor.java
   core/branches/flat/src/main/java/org/horizon/interceptors/CacheStoreInterceptor.java
   core/branches/flat/src/main/java/org/horizon/statetransfer/DefaultStateTransferManager.java
   core/branches/flat/src/main/resources/config-samples/all.xml
   core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd
   core/branches/flat/src/test/java/org/horizon/api/tree/NodeMoveAPITest.java
   core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java
   core/branches/flat/src/test/java/org/horizon/eviction/EvictionFunctionalTest.java
   core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
   core/branches/flat/src/test/java/org/horizon/manager/CacheManagerComponentRegistryTest.java
   core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerCacheLoaderTest.java
   core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerPassivationTest.java
Log:
Loaders - work in progress

Deleted: core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,384 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 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.horizon.config;
-
-import org.horizon.loaderold.CacheLoaderOld;
-import org.horizon.loaderold.SingletonStoreCacheLoaderOld;
-import org.horizon.util.Util;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-/**
- * Holds the configuration of the cache loader chain.  ALL cache loaders should be defined using this class, adding
- * individual cache loaders to the chain by calling {@link CacheLoaderConfig#addIndividualCacheLoaderConfig}
- *
- * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
- * @author Brian Stansberry
- * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
- * @since 1.0
- */
-public class CacheLoaderConfig extends AbstractNamedCacheConfigurationBean {
-   private static final long serialVersionUID = 2210349340378984424L;
-
-   private boolean passivation;
-   private boolean preload;
-   private List<IndividualCacheLoaderConfig> cacheLoaderConfigs = new ArrayList<IndividualCacheLoaderConfig>();
-
-   private boolean shared;
-
-   public void setPreload(boolean preload) {
-      testImmutability("preload");
-      this.preload = preload;
-   }
-
-   public void setPassivation(boolean passivation) {
-      testImmutability("passivation");
-      this.passivation = passivation;
-   }
-
-   public boolean isPassivation() {
-      return passivation;
-   }
-
-   public void addIndividualCacheLoaderConfig(IndividualCacheLoaderConfig clc) {
-      testImmutability("cacheLoaderConfigs");
-      cacheLoaderConfigs.add(clc);
-   }
-
-   public List<IndividualCacheLoaderConfig> getIndividualCacheLoaderConfigs() {
-      return cacheLoaderConfigs;
-   }
-
-   public void setIndividualCacheLoaderConfigs(List<IndividualCacheLoaderConfig> configs) {
-      testImmutability("cacheLoaderConfigs");
-      this.cacheLoaderConfigs = configs == null ? new ArrayList<IndividualCacheLoaderConfig>() : configs;
-   }
-
-   public IndividualCacheLoaderConfig getFirstCacheLoaderConfig() {
-      if (cacheLoaderConfigs.size() == 0) return null;
-      return cacheLoaderConfigs.get(0);
-   }
-
-   public boolean useChainingCacheLoader() {
-      return !isPassivation() && cacheLoaderConfigs.size() > 1;
-   }
-
-   @Override
-   public String toString() {
-      return new StringBuilder().append("CacheLoaderConfig{").append("shared=").append(shared).append(", passivation=").append(passivation).append(", preload='").append(preload).append('\'').append(", cacheLoaderConfigs.size()=").append(cacheLoaderConfigs.size()).append('}').toString();
-   }
-
-   public void setShared(boolean shared) {
-      testImmutability("shared");
-      this.shared = shared;
-   }
-
-   public boolean isShared() {
-      return shared;
-   }
-
-   @Override
-   public boolean equals(Object obj) {
-      if (this == obj)
-         return true;
-
-      if (obj instanceof CacheLoaderConfig) {
-         CacheLoaderConfig other = (CacheLoaderConfig) obj;
-         return (this.passivation == other.passivation)
-               && (this.shared == other.shared)
-               && Util.safeEquals(this.preload, other.preload)
-               && Util.safeEquals(this.cacheLoaderConfigs, other.cacheLoaderConfigs);
-      }
-      return false;
-   }
-
-   @Override
-   public int hashCode() {
-      int result = 19;
-      result = 51 * result + (passivation ? 0 : 1);
-      result = 51 * result + (shared ? 0 : 1);
-      result = 51 * result + (preload ? 0 : 1);
-      result = 51 * result + (cacheLoaderConfigs == null ? 0 : cacheLoaderConfigs.hashCode());
-      return result;
-   }
-
-
-   @Override
-   public CacheLoaderConfig clone() throws CloneNotSupportedException {
-      CacheLoaderConfig clone = (CacheLoaderConfig) super.clone();
-      if (cacheLoaderConfigs != null) {
-         List<IndividualCacheLoaderConfig> clcs = new ArrayList<IndividualCacheLoaderConfig>(cacheLoaderConfigs.size());
-         for (IndividualCacheLoaderConfig clc : cacheLoaderConfigs) {
-            clcs.add(clc.clone());
-         }
-         clone.setIndividualCacheLoaderConfigs(clcs);
-      }
-      return clone;
-   }
-
-   /**
-    * Loops through all individual cache loader configs and checks if fetchPersistentState is set on any of them
-    */
-   public boolean isFetchPersistentState() {
-      for (IndividualCacheLoaderConfig iclc : cacheLoaderConfigs) {
-         if (iclc.isFetchPersistentState()) return true;
-      }
-      return false;
-   }
-
-   public boolean isPreload() {
-      return preload;
-   }
-
-
-   /**
-    * Configuration object that holds the confguration of an individual cache loader.
-    *
-    * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
-    * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
-    */
-   public static class IndividualCacheLoaderConfig extends PluggableConfigurationComponent {
-      private static final long serialVersionUID = -2282396799100828593L;
-
-      private boolean async;
-      private boolean ignoreModifications;
-      private boolean fetchPersistentState;
-
-      private boolean purgeOnStartup;
-
-      private SingletonStoreConfig singletonStoreConfig;
-      private transient CacheLoaderOld<Object, Object> cacheLoader;
-
-      protected void populateFromBaseConfig(IndividualCacheLoaderConfig base) {
-         if (base != null) {
-            setAsync(base.isAsync());
-            setIgnoreModifications(base.isIgnoreModifications());
-            setFetchPersistentState(base.isFetchPersistentState());
-            setSingletonStoreConfig(base.getSingletonStoreConfig());
-            setPurgeOnStartup(base.isPurgeOnStartup());
-            setProperties(base.getProperties());
-         }
-      }
-
-      public boolean isPurgeOnStartup() {
-         return purgeOnStartup;
-      }
-
-      public boolean isFetchPersistentState() {
-         return fetchPersistentState;
-      }
-
-      public void setFetchPersistentState(boolean fetchPersistentState) {
-         testImmutability("fetchPersistentState");
-         this.fetchPersistentState = fetchPersistentState;
-      }
-
-      public void setAsync(boolean async) {
-         testImmutability("async");
-         this.async = async;
-      }
-
-      public boolean isAsync() {
-         return async;
-      }
-
-      public void setIgnoreModifications(boolean ignoreModifications) {
-         testImmutability("ignoreModifications");
-         this.ignoreModifications = ignoreModifications;
-      }
-
-      public boolean isIgnoreModifications() {
-         return ignoreModifications;
-      }
-
-      public void setPurgeOnStartup(boolean purgeOnStartup) {
-         testImmutability("purgeOnStartup");
-         this.purgeOnStartup = purgeOnStartup;
-      }
-
-      public SingletonStoreConfig getSingletonStoreConfig() {
-         return singletonStoreConfig;
-      }
-
-      public void setSingletonStoreConfig(SingletonStoreConfig singletonStoreConfig) {
-         testImmutability("singletonStoreConfig");
-         this.singletonStoreConfig = singletonStoreConfig;
-      }
-
-      /**
-       * Provides the ability to get and set a running cache loader, which, if exists, will be used rather than
-       * constructing a new one.  Primarily to facilitate testing with mock objects.
-       *
-       * @return cache loader, if one exists
-       * @since 1.0
-       */
-      public CacheLoaderOld<Object, Object> getCacheLoader() {
-         return cacheLoader;
-      }
-
-      /**
-       * Provides the ability to get and set a running cache loader, which, if exists, will be used rather than
-       * constructing a new one.  Primarily to facilitate testing with mock objects.
-       *
-       * @param cacheLoader cacheLoader to set
-       * @since 1.0
-       */
-      public void setCacheLoader(CacheLoaderOld<Object, Object> cacheLoader) {
-         this.cacheLoader = cacheLoader;
-      }
-
-      @Override
-      public boolean equals(Object obj) {
-         if (super.equals(obj)) {
-            IndividualCacheLoaderConfig i = (IndividualCacheLoaderConfig) obj;
-            return equalsExcludingProperties(i);
-         }
-         return false;
-      }
-
-      protected boolean equalsExcludingProperties(Object obj) {
-         if (!(obj instanceof IndividualCacheLoaderConfig))
-            return false;
-         IndividualCacheLoaderConfig other = (IndividualCacheLoaderConfig) obj;
-
-         return Util.safeEquals(this.className, other.className)
-               && (this.async == other.async)
-               && (this.ignoreModifications == other.ignoreModifications)
-               && (this.fetchPersistentState == other.fetchPersistentState)
-               && Util.safeEquals(this.singletonStoreConfig, other.singletonStoreConfig);
-
-      }
-
-      @Override
-      public int hashCode() {
-         return 31 * hashCodeExcludingProperties() + (properties == null ? 0 : properties.hashCode());
-      }
-
-      protected int hashCodeExcludingProperties() {
-         int result = 17;
-         result = 31 * result + (className == null ? 0 : className.hashCode());
-         result = 31 * result + (async ? 0 : 1);
-         result = 31 * result + (ignoreModifications ? 0 : 1);
-         result = 31 * result + (fetchPersistentState ? 0 : 1);
-         result = 31 * result + (singletonStoreConfig == null ? 0 : singletonStoreConfig.hashCode());
-         result = 31 * result + (purgeOnStartup ? 0 : 1);
-         return result;
-      }
-
-      @Override
-      public String toString() {
-         return new StringBuilder().append("IndividualCacheLoaderConfig{").append("className='").append(className).append('\'')
-               .append(", async=").append(async)
-               .append(", ignoreModifications=").append(ignoreModifications)
-               .append(", fetchPersistentState=").append(fetchPersistentState)
-               .append(", properties=").append(properties)
-               .append(", purgeOnStartup=").append(purgeOnStartup).append("},")
-               .append("SingletonStoreConfig{").append(singletonStoreConfig).append('}')
-               .toString();
-      }
-
-      @Override
-      public IndividualCacheLoaderConfig clone() throws CloneNotSupportedException {
-         IndividualCacheLoaderConfig clone = (IndividualCacheLoaderConfig) super.clone();
-         if (singletonStoreConfig != null)
-            clone.setSingletonStoreConfig(singletonStoreConfig.clone());
-         clone.cacheLoader = cacheLoader;
-         return clone;
-      }
-
-      /**
-       * Configuration for a SingletonStoreCacheLoader
-       */
-      public static class SingletonStoreConfig extends PluggableConfigurationComponent {
-         private static final long serialVersionUID = 824251894176131850L;
-
-         /**
-          * Indicates whether the singleton store functionality is enabled or not.
-          */
-         private boolean singletonStoreEnabled;
-
-         public SingletonStoreConfig() {
-            // default value
-            className = SingletonStoreCacheLoaderOld.class.getName();
-         }
-
-         public boolean isSingletonStoreEnabled() {
-            return singletonStoreEnabled;
-         }
-
-         public void setSingletonStoreEnabled(boolean singletonStoreEnabled) {
-            testImmutability("singletonStoreEnabled");
-            this.singletonStoreEnabled = singletonStoreEnabled;
-         }
-
-         public String getSingletonStoreClass() {
-            return className;
-         }
-
-         public void setSingletonStoreClass(String className) {
-            setClassName(className);
-         }
-
-         public Properties getSingletonStoreProperties() {
-            return properties;
-         }
-
-         public void setSingletonStoreProperties(Properties properties) {
-            setProperties(properties);
-         }
-
-         @Override
-         public boolean equals(Object obj) {
-            if (this == obj)
-               return true;
-
-            if (super.equals(obj)) {
-               SingletonStoreConfig other = (SingletonStoreConfig) obj;
-               return this.singletonStoreEnabled == other.singletonStoreEnabled;
-            }
-            return false;
-         }
-
-         @Override
-         public int hashCode() {
-            int result = 19;
-            result = 41 * result + super.hashCode();
-            result = 41 * result + (singletonStoreEnabled ? 0 : 1);
-            return result;
-         }
-
-         @Override
-         public String toString() {
-            return super.toString() + " enabled=" + singletonStoreEnabled +
-                  " class=" + className +
-                  " properties=" + properties;
-         }
-
-         @Override
-         public SingletonStoreConfig clone() throws CloneNotSupportedException {
-            return (SingletonStoreConfig) super.clone();
-         }
-      }
-   }
-}

Copied: core/branches/flat/src/main/java/org/horizon/config/CacheLoaderManagerConfig.java (from rev 7675, core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/CacheLoaderManagerConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/config/CacheLoaderManagerConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 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.horizon.config;
+
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.util.Util;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Holds the configuration of the cache loader chain.  ALL cache loaders should be defined using this class, adding
+ * individual cache loaders to the chain by calling {@link CacheLoaderManagerConfig#addIndividualCacheLoaderConfig}
+ *
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
+ * @author Brian Stansberry
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ * @since 1.0
+ */
+public class CacheLoaderManagerConfig extends AbstractNamedCacheConfigurationBean {
+   private static final long serialVersionUID = 2210349340378984424L;
+
+   private boolean passivation;
+   private boolean preload;
+   private List<CacheLoaderConfig> cacheLoaderConfigs = new LinkedList<CacheLoaderConfig>();
+
+   private boolean shared;
+
+   public void setPreload(boolean preload) {
+      testImmutability("preload");
+      this.preload = preload;
+   }
+
+   public void setPassivation(boolean passivation) {
+      testImmutability("passivation");
+      this.passivation = passivation;
+   }
+
+   public boolean isPassivation() {
+      return passivation;
+   }
+
+   public void addIndividualCacheLoaderConfig(CacheLoaderConfig clc) {
+      testImmutability("cacheLoaderConfigs");
+      cacheLoaderConfigs.add(clc);
+   }
+
+   public List<CacheLoaderConfig> getIndividualCacheLoaderConfigs() {
+      return cacheLoaderConfigs;
+   }
+
+   public void setIndividualCacheLoaderConfigs(List<CacheLoaderConfig> configs) {
+      testImmutability("cacheLoaderConfigs");
+      this.cacheLoaderConfigs = configs == null ? new LinkedList<CacheLoaderConfig>() : configs;
+   }
+
+   public CacheLoaderConfig getFirstCacheLoaderConfig() {
+      if (cacheLoaderConfigs.size() == 0) return null;
+      return cacheLoaderConfigs.get(0);
+   }
+
+   public boolean useChainingCacheLoader() {
+      return !isPassivation() && cacheLoaderConfigs.size() > 1;
+   }
+
+   @Override
+   public String toString() {
+      return new StringBuilder().append("CacheLoaderManagerConfig{").append("shared=").append(shared).append(", passivation=").append(passivation).append(", preload='").append(preload).append('\'').append(", cacheLoaderConfigs.size()=").append(cacheLoaderConfigs.size()).append('}').toString();
+   }
+
+   public void setShared(boolean shared) {
+      testImmutability("shared");
+      this.shared = shared;
+   }
+
+   public boolean isShared() {
+      return shared;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+
+      if (obj instanceof CacheLoaderManagerConfig) {
+         CacheLoaderManagerConfig other = (CacheLoaderManagerConfig) obj;
+         return (this.passivation == other.passivation)
+               && (this.shared == other.shared)
+               && Util.safeEquals(this.preload, other.preload)
+               && Util.safeEquals(this.cacheLoaderConfigs, other.cacheLoaderConfigs);
+      }
+      return false;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = 19;
+      result = 51 * result + (passivation ? 0 : 1);
+      result = 51 * result + (shared ? 0 : 1);
+      result = 51 * result + (preload ? 0 : 1);
+      result = 51 * result + (cacheLoaderConfigs == null ? 0 : cacheLoaderConfigs.hashCode());
+      return result;
+   }
+
+
+   @Override
+   public CacheLoaderManagerConfig clone() throws CloneNotSupportedException {
+      CacheLoaderManagerConfig clone = (CacheLoaderManagerConfig) super.clone();
+      if (cacheLoaderConfigs != null) {
+         List<CacheLoaderConfig> clcs = new LinkedList<CacheLoaderConfig>();
+         for (CacheLoaderConfig clc : cacheLoaderConfigs) {
+            clcs.add(clc.clone());
+         }
+         clone.setIndividualCacheLoaderConfigs(clcs);
+      }
+      return clone;
+   }
+
+   /**
+    * Loops through all individual cache loader configs and checks if fetchPersistentState is set on any of them
+    */
+   public boolean isFetchPersistentState() {
+      for (CacheLoaderConfig iclc : cacheLoaderConfigs) {
+         if (iclc.isFetchPersistentState()) return true;
+      }
+      return false;
+   }
+
+   public boolean isPreload() {
+      return preload;
+   }
+}


Property changes on: core/branches/flat/src/main/java/org/horizon/config/CacheLoaderManagerConfig.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: core/branches/flat/src/main/java/org/horizon/config/Configuration.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/Configuration.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/Configuration.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -120,7 +120,7 @@
    private IsolationLevel isolationLevel = IsolationLevel.READ_COMMITTED;
    private EvictionConfig evictionConfig = null;
    private String transactionManagerLookupClass = null;
-   private CacheLoaderConfig cacheLoaderConfig = null;
+   private CacheLoaderManagerConfig cacheLoaderConfig = null;
    @Dynamic
    private boolean syncCommitPhase = false;
    @Dynamic
@@ -260,7 +260,7 @@
       this.transactionManagerLookupClass = transactionManagerLookupClass;
    }
 
-   public void setCacheLoaderConfig(CacheLoaderConfig config) {
+   public void setCacheLoaderConfig(CacheLoaderManagerConfig config) {
       testImmutability("cacheLoaderConfig");
       this.cacheLoaderConfig = config;
    }
@@ -367,7 +367,7 @@
       return transactionManagerLookupClass;
    }
 
-   public CacheLoaderConfig getCacheLoaderConfig() {
+   public CacheLoaderManagerConfig getCacheLoaderConfig() {
       return cacheLoaderConfig;
    }
 

Deleted: core/branches/flat/src/main/java/org/horizon/config/EvictionAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/EvictionAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/EvictionAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,61 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 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.horizon.config;
-
-/**
- * An interface used to configure an eviction algorithm.  Replaces the deprecated {@link EvictionCacheConfig}.
- * <p/>
- * In its most basic form, it is implemented by {@link org.horizon.eviction.EvictionAlgorithmConfigBase}, but more
- * specific eviction policies may subclass {@link org.horizon.eviction.EvictionAlgorithmConfigBase} or re-implement this
- * interface to provide access to more config variables.
- *
- * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @since 1.0
- */
-public interface EvictionAlgorithmConfig extends CloneableConfigurationComponent {
-   /**
-    * Gets the class name of the {@link org.horizon.eviction.EvictionAlgorithm} implementation this object will
-    * configure.
-    *
-    * @return fully qualified class name
-    */
-   String getEvictionAlgorithmClassName();
-
-   /**
-    * Validate the configuration. Will be called after any configuration properties are set.
-    *
-    * @throws ConfigurationException if any values for the configuration properties are invalid
-    */
-   void validate() throws ConfigurationException;
-
-   /**
-    * Resets the values to their defaults.
-    */
-   void reset();
-
-   /**
-    * @return a clone of the EvictionAlgorithmConfig.
-    */
-   EvictionAlgorithmConfig clone();
-
-
-}

Modified: core/branches/flat/src/main/java/org/horizon/config/EvictionConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/EvictionConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/EvictionConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,6 +22,7 @@
 package org.horizon.config;
 
 import org.horizon.eviction.DefaultEvictionAction;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 
 import java.util.concurrent.TimeUnit;
 

Modified: core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigHelper.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigHelper.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigHelper.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -291,6 +291,10 @@
       return properties;
    }
 
+   public static Properties readPropertiesContents(Element element) {
+      return readPropertiesContents(element, "properties");
+   }
+
    /**
     * Similar to {@link #readStringContents(org.w3c.dom.Element,String)} except that it returns a boolean.
     *

Modified: core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/parsing/XmlConfigurationParserImpl.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,16 +1,16 @@
 package org.horizon.config.parsing;
 
-import org.horizon.config.CacheLoaderConfig;
+import org.horizon.config.CacheLoaderManagerConfig;
 import org.horizon.config.Configuration;
 import org.horizon.config.ConfigurationException;
 import org.horizon.config.CustomInterceptorConfig;
 import org.horizon.config.DuplicateCacheNameException;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.config.EvictionConfig;
 import org.horizon.config.GlobalConfiguration;
 import org.horizon.config.parsing.element.CustomInterceptorsElementParser;
 import org.horizon.config.parsing.element.LoadersElementParser;
 import org.horizon.eviction.EvictionAlgorithm;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.lock.IsolationLevel;
 import org.horizon.transaction.GenericTransactionManagerLookup;
 import org.horizon.util.FileLookup;
@@ -241,7 +241,7 @@
    void configureCacheLoaders(Element element, Configuration config) {
       if (element == null) return; //null cache loaders are allowed
       LoadersElementParser clElementParser = new LoadersElementParser();
-      CacheLoaderConfig cacheLoaderConfig = clElementParser.parseLoadersElement(element);
+      CacheLoaderManagerConfig cacheLoaderConfig = clElementParser.parseLoadersElement(element);
       config.setCacheLoaderConfig(cacheLoaderConfig);
    }
 

Modified: core/branches/flat/src/main/java/org/horizon/config/parsing/element/LoadersElementParser.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/config/parsing/element/LoadersElementParser.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/config/parsing/element/LoadersElementParser.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -21,15 +21,17 @@
  */
 package org.horizon.config.parsing.element;
 
-import org.horizon.config.CacheLoaderConfig;
+import org.horizon.config.CacheLoaderManagerConfig;
 import org.horizon.config.ConfigurationException;
 import org.horizon.config.parsing.XmlConfigHelper;
 import org.horizon.config.parsing.XmlParserBase;
+import org.horizon.loader.CacheLoader;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.decorators.SingletonStoreConfig;
+import org.horizon.util.Util;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
-import java.util.Properties;
-
 /**
  * Utility class for parsing the 'loaders' element in the .xml configuration file.
  * <pre>
@@ -41,8 +43,8 @@
  * @since 1.0
  */
 public class LoadersElementParser extends XmlParserBase {
-   public CacheLoaderConfig parseLoadersElement(Element element) {
-      CacheLoaderConfig cacheLoaderConfig = new CacheLoaderConfig();
+   public CacheLoaderManagerConfig parseLoadersElement(Element element) {
+      CacheLoaderManagerConfig cacheLoaderConfig = new CacheLoaderManagerConfig();
       String passivation = getAttributeValue(element, "passivation");
       if (existsAttribute(passivation)) cacheLoaderConfig.setPassivation(getBoolean(passivation));
       String shared = getAttributeValue(element, "shared");
@@ -53,45 +55,55 @@
       NodeList cacheLoaderNodes = element.getElementsByTagName("loader");
       for (int i = 0; i < cacheLoaderNodes.getLength(); i++) {
          Element indivElement = (Element) cacheLoaderNodes.item(i);
-         CacheLoaderConfig.IndividualCacheLoaderConfig iclc = parseIndividualCacheLoaderConfig(indivElement);
+         CacheLoaderConfig iclc = parseIndividualCacheLoaderConfig(indivElement);
          cacheLoaderConfig.addIndividualCacheLoaderConfig(iclc);
       }
       return cacheLoaderConfig;
    }
 
-   private CacheLoaderConfig.IndividualCacheLoaderConfig parseIndividualCacheLoaderConfig(Element indivElement) {
-      CacheLoaderConfig.IndividualCacheLoaderConfig iclc = new CacheLoaderConfig.IndividualCacheLoaderConfig();
+   private CacheLoaderConfig parseIndividualCacheLoaderConfig(Element indivElement) {
+      String clClass = getAttributeValue(indivElement, "class");
+      if (!existsAttribute(clClass))
+         throw new ConfigurationException("Missing 'class'  attribute for cache loader configuration");
+      CacheLoader cl;
+      CacheLoaderConfig clc;
+      try {
+         cl = (CacheLoader) Util.getInstance(clClass);
+         clc = (CacheLoaderConfig) Util.getInstance(cl.getConfigurationClass());
+      } catch (Exception e) {
+         throw new ConfigurationException("Unable to instantiate cache loader or configuration", e);
+      }
 
       String async = getAttributeValue(indivElement, "async");
-      if (existsAttribute(async)) iclc.setAsync(getBoolean(async));
+      if (existsAttribute(async)) clc.setAsync(getBoolean(async));
       String fetchPersistentState = getAttributeValue(indivElement, "fetchPersistentState");
-      if (existsAttribute(fetchPersistentState)) iclc.setFetchPersistentState(getBoolean(fetchPersistentState));
+      if (existsAttribute(fetchPersistentState)) clc.setFetchPersistentState(getBoolean(fetchPersistentState));
       String ignoreModifications = getAttributeValue(indivElement, "ignoreModifications");
-      if (existsAttribute(ignoreModifications)) iclc.setIgnoreModifications(getBoolean(ignoreModifications));
+      if (existsAttribute(ignoreModifications)) clc.setIgnoreModifications(getBoolean(ignoreModifications));
       String purgeOnStartup = getAttributeValue(indivElement, "purgeOnStartup");
-      if (existsAttribute(purgeOnStartup)) iclc.setPurgeOnStartup(getBoolean(purgeOnStartup));
-      String clClass = getAttributeValue(indivElement, "class");
-      if (!existsAttribute(clClass))
-         throw new ConfigurationException("Missing 'class'  attribute for cache loader configuration");
-      iclc.setClassName(clClass);
-      iclc.setProperties(XmlConfigHelper.readPropertiesContents(indivElement, "properties"));
-      CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = parseSingletonStoreConfig(getSingleElementInCoreNS("singletonStore", indivElement));
-      if (ssc != null) {
-         iclc.setSingletonStoreConfig(ssc);
-      }
-      return iclc;
+      if (existsAttribute(purgeOnStartup)) clc.setPurgeOnStartup(getBoolean(purgeOnStartup));
+
+      clc.setClassName(clClass);
+      XmlConfigHelper.setValues(clc, XmlConfigHelper.readPropertiesContents(indivElement), false, true);
+      SingletonStoreConfig ssc = parseSingletonStoreConfig(getSingleElementInCoreNS("singletonStore", indivElement));
+      if (ssc != null) clc.setSingletonStoreConfig(ssc);
+      return clc;
    }
 
-   public CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig parseSingletonStoreConfig(Element element) {
-      if (element == null) return null; //might happen, this config option is not mandatory
-      boolean singletonStoreEnabled = getBoolean(getAttributeValue(element, "enabled"));
-      String singletonStoreClass = getAttributeValue(element, "class");
-      CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = new CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig();
-      if (existsAttribute(singletonStoreClass)) ssc.setSingletonStoreClass(singletonStoreClass);
-      Properties singletonStoreproperties = XmlConfigHelper.readPropertiesContents(element, "properties");
-      ssc.setSingletonStoreEnabled(singletonStoreEnabled);
-      ssc.setSingletonStoreClass(singletonStoreClass);
-      ssc.setSingletonStoreProperties(singletonStoreproperties);
+   public SingletonStoreConfig parseSingletonStoreConfig(Element element) {
+      SingletonStoreConfig ssc = new SingletonStoreConfig();
+      if (element == null) {
+         ssc.setSingletonStoreEnabled(false);
+      } else {
+         boolean singletonStoreEnabled = getBoolean(getAttributeValue(element, "enabled"));
+         ssc.setSingletonStoreEnabled(singletonStoreEnabled);
+
+         String tmp = getAttributeValue(element, "pushStateWhenCoordinator");
+         if (existsAttribute(tmp)) ssc.setPushStateWhenCoordinator(getBoolean(tmp));
+
+         tmp = getAttributeValue(element, "pushStateTimeout");
+         if (existsAttribute(tmp)) ssc.setPushStateTimeout(getLong(tmp));
+      }
       return ssc;
    }
 }

Deleted: core/branches/flat/src/main/java/org/horizon/container/CachedEntry.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/CachedEntry.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/container/CachedEntry.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,9 +0,0 @@
-package org.horizon.container;
-
-/**
- * This is a wrapper for a cached entry, containing a reference to key, value and metadata.
- *
- * @author Manik Surtani
- * @since 1.0
- */
-

Added: core/branches/flat/src/main/java/org/horizon/container/CachedValue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/CachedValue.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/container/CachedValue.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,30 @@
+package org.horizon.container;
+
+public class CachedValue<V> {
+   protected V value;
+   protected long modifiedTime;
+
+   protected CachedValue() {
+   }
+
+   public CachedValue(V value) {
+      this.value = value;
+      touch();
+   }
+
+   public final void touch() {
+      modifiedTime = System.currentTimeMillis();
+   }
+
+   public final long getModifiedTime() {
+      return modifiedTime;
+   }
+
+   public final V getValue() {
+      return value;
+   }
+
+   public final void setValue(V value) {
+      this.value = value;
+   }
+}
\ No newline at end of file

Modified: core/branches/flat/src/main/java/org/horizon/container/DataContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/DataContainer.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/container/DataContainer.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -23,6 +23,7 @@
 
 import org.horizon.factories.scopes.Scope;
 import org.horizon.factories.scopes.Scopes;
+import org.horizon.loader.StoredEntry;
 
 import java.util.Set;
 
@@ -56,4 +57,6 @@
     * @return set of keys that have been purged.
     */
    Set<K> purgeExpiredEntries();
+
+   StoredEntry<K, V> createEntryForStorage(K key);
 }

Added: core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/container/ExpirableCachedValue.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,37 @@
+package org.horizon.container;
+
+public class ExpirableCachedValue<V> extends CachedValue<V> {
+   protected long createdTime;
+   protected long expiryTime;
+
+   protected ExpirableCachedValue() {
+   }
+
+   public ExpirableCachedValue(V value, long createdTime, long expiryTime) {
+      super(value);
+      this.createdTime = createdTime;
+      this.expiryTime = expiryTime;
+   }
+
+   public ExpirableCachedValue(V value, long lifespan) {
+      super(value);
+      createdTime = getModifiedTime();
+      setLifespan(lifespan);
+   }
+
+   public final boolean isExpired() {
+      return expiryTime >= 0 && System.currentTimeMillis() > expiryTime;
+   }
+
+   public final long getCreatedTime() {
+      return createdTime;
+   }
+
+   public final long getExpiryTime() {
+      return expiryTime;
+   }
+
+   public final void setLifespan(long lifespan) {
+      expiryTime = lifespan < 0 ? -1 : lifespan + createdTime;
+   }
+}
\ No newline at end of file

Modified: core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/container/UnsortedDataContainer.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,8 +22,9 @@
 package org.horizon.container;
 
 import org.horizon.factories.annotations.Inject;
-import org.horizon.loaderold.CacheLoaderManager;
-import org.horizon.loaderold.CacheLoaderOld;
+import org.horizon.loader.CacheLoaderManager;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
 
 import java.util.AbstractSet;
 import java.util.ArrayList;
@@ -48,7 +49,7 @@
    final ConcurrentMap<K, ExpirableCachedValue<V>> expirableData = new ConcurrentHashMap<K, ExpirableCachedValue<V>>();
    private static final Object NULL = new Object();
    private CacheLoaderManager clm;
-   private CacheLoaderOld cacheLoader;
+   private CacheStore cacheStore;
 
    @Inject
    public void injectDependencies(CacheLoaderManager clm) {
@@ -61,9 +62,9 @@
    }
 
    private void expireOnCacheLoader(K key) {
-      if (cacheLoader == null && clm != null) cacheLoader = clm.getCacheLoader();
-      if (cacheLoader != null) {
-         cacheLoader.remove(key);
+      if (cacheStore == null && clm != null) cacheStore = clm.getCacheStore();
+      if (cacheStore != null) {
+         cacheStore.remove(key);
       }
    }
 
@@ -82,15 +83,15 @@
       CachedValue<V> cv = immortalData.get(maskedKey);
       if (cv != null) {
          cv.touch();
-         return cv.value;
+         return cv.getValue();
       } else {
          ExpirableCachedValue<V> ecv = expirableData.get(maskedKey);
          if (ecv != null) {
-            if (ecv.expired()) {
+            if (ecv.isExpired()) {
                expire(maskedKey);
             } else {
                ecv.touch();
-               return ecv.value;
+               return ecv.getValue();
             }
          }
       }
@@ -107,7 +108,7 @@
          // do we need to move this to expirable?
          if (lifespan < 0) {
             // no.
-            cv.value = v;
+            cv.setValue(v);
             cv.touch();
          } else {
             ecv = new ExpirableCachedValue<V>(v, lifespan);
@@ -122,7 +123,7 @@
             expirableData.remove(maskedKey);
             immortalData.put(maskedKey, cv);
          } else {
-            ecv.value = v;
+            ecv.setValue(v);
             ecv.touch();
          }
       } else {
@@ -142,7 +143,7 @@
       if (!immortalData.containsKey(maskedKey)) {
          ExpirableCachedValue<V> ecv = expirableData.get(maskedKey);
          if (ecv == null) return false;
-         if (ecv.expired()) {
+         if (ecv.isExpired()) {
             expire(maskedKey);
             return false;
          }
@@ -152,9 +153,9 @@
 
    public long getModifiedTimestamp(K key) {
       K maskedKey = maskNullKey(key);
-      CachedValue cv = immortalData.get(maskedKey);
+      CachedValue<V> cv = immortalData.get(maskedKey);
       if (cv == null) cv = expirableData.get(maskedKey);
-      return cv == null ? -1 : cv.modified;
+      return cv == null ? -1 : cv.getModifiedTime();
    }
 
    @SuppressWarnings("unchecked")
@@ -166,7 +167,7 @@
       if (cv == null) {
          return null;
       } else {
-         return cv.value;
+         return cv.getValue();
       }
    }
 
@@ -191,8 +192,8 @@
       Set<K> purged = new HashSet<K>();
       for (Iterator<Map.Entry<K, ExpirableCachedValue<V>>> iter = expirableData.entrySet().iterator(); iter.hasNext();) {
          Map.Entry<K, ExpirableCachedValue<V>> entry = iter.next();
-         ExpirableCachedValue<?> cv = entry.getValue();
-         if (cv.expired()) {
+         ExpirableCachedValue<V> cv = entry.getValue();
+         if (cv.isExpired()) {
             expireOnCacheLoader(entry.getKey());
             purged.add(entry.getKey());
             iter.remove();
@@ -201,6 +202,15 @@
       return purged;
    }
 
+   public StoredEntry<K, V> createEntryForStorage(K key) {
+      CachedValue<V> immortal = immortalData.get(key);
+      if (immortal != null)
+         return new StoredEntry<K, V>(key, immortal.getValue(), -1, -1);
+      ExpirableCachedValue<V> ecv = expirableData.get(key);
+      if (ecv == null) return null;
+      return new StoredEntry<K, V>(key, ecv.getValue(), ecv.getCreatedTime(), ecv.getExpiryTime());
+   }
+
    private class KeySet extends AbstractSet<K> {
       Set<K> immortalKeys;
       Set<K> expirableKeys;
@@ -265,37 +275,4 @@
          throw new UnsupportedOperationException();
       }
    }
-
-   private static class CachedValue<V> {
-      V value;
-      long modified;
-
-      private CachedValue(V value) {
-         this.value = value;
-         modified = System.currentTimeMillis();
-      }
-
-      void touch() {
-         modified = System.currentTimeMillis();
-      }
-   }
-
-   private static class ExpirableCachedValue<V> extends CachedValue<V> {
-      long created;
-      long expiryTime;
-
-      private ExpirableCachedValue(V value, long lifespan) {
-         super(value);
-         created = modified;
-         setLifespan(lifespan);
-      }
-
-      private boolean expired() {
-         return expiryTime >= 0 && System.currentTimeMillis() > expiryTime;
-      }
-
-      private void setLifespan(long lifespan) {
-         expiryTime = lifespan < 0 ? -1 : lifespan + created;
-      }
-   }
 }
\ No newline at end of file

Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,7 +22,6 @@
 package org.horizon.eviction;
 
 import org.horizon.Cache;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.events.EvictionEvent;
 import org.horizon.eviction.events.EvictionEvent.Type;
@@ -82,8 +81,8 @@
    boolean canIgnoreEvent(Type eventType);
 
    /**
-    * @return the type of the {@link org.horizon.config.EvictionAlgorithmConfig} bean used to configure this
-    *         implementation of {@link org.horizon.eviction.EvictionAlgorithm}
+    * @return the type of the {@link EvictionAlgorithmConfig} bean used to configure this implementation of {@link
+    *         org.horizon.eviction.EvictionAlgorithm}
     */
    Class<? extends EvictionAlgorithmConfig> getConfigurationClass();
 }

Copied: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfig.java (from rev 7673, core/branches/flat/src/main/java/org/horizon/config/EvictionAlgorithmConfig.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 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.horizon.eviction;
+
+import org.horizon.config.CloneableConfigurationComponent;
+import org.horizon.config.ConfigurationException;
+
+/**
+ * An interface used to configure an eviction algorithm.  Replaces the deprecated {@link EvictionCacheConfig}.
+ * <p/>
+ * In its most basic form, it is implemented by {@link org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig}, but
+ * more specific eviction policies may subclass {@link org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig} or
+ * re-implement this interface to provide access to more config variables.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 1.0
+ */
+public interface EvictionAlgorithmConfig extends CloneableConfigurationComponent {
+   /**
+    * Gets the class name of the {@link org.horizon.eviction.EvictionAlgorithm} implementation this object will
+    * configure.
+    *
+    * @return fully qualified class name
+    */
+   String getEvictionAlgorithmClassName();
+
+   /**
+    * Validate the configuration. Will be called after any configuration properties are set.
+    *
+    * @throws org.horizon.config.ConfigurationException
+    *          if any values for the configuration properties are invalid
+    */
+   void validate() throws ConfigurationException;
+
+   /**
+    * Resets the values to their defaults.
+    */
+   void reset();
+
+   /**
+    * @return a clone of the EvictionAlgorithmConfig.
+    */
+   EvictionAlgorithmConfig clone();
+}


Property changes on: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfig.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Deleted: core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,163 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 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.horizon.eviction;
-
-import org.horizon.config.AbstractNamedCacheConfigurationBean;
-import org.horizon.config.ConfigurationException;
-import org.horizon.config.Dynamic;
-import org.horizon.config.EvictionAlgorithmConfig;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * A base class used for configuring eviction algorithms.
- *
- * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @since 1.0
- */
-public abstract class EvictionAlgorithmConfigBase extends AbstractNamedCacheConfigurationBean implements EvictionAlgorithmConfig {
-   private static final long serialVersionUID = 4591691674370188932L;
-
-   protected String evictionAlgorithmClassName;
-   @Dynamic
-   protected int maxEntries = -1;
-   @Dynamic
-   protected int minEntries = -1;
-   @Dynamic
-   protected long minTimeToLive = -1;
-
-   /**
-    * Can only be instantiated by a subclass.
-    */
-   protected EvictionAlgorithmConfigBase() {
-   }
-
-   public String getEvictionAlgorithmClassName() {
-      return evictionAlgorithmClassName;
-   }
-
-   public int getMaxEntries() {
-      return maxEntries;
-   }
-
-   /**
-    * @param maxEntries max entries to hold in the cache. 0 denotes immediate expiry and -1 denotes unlimited entries.
-    *                   -1 is the default
-    */
-   public void setMaxEntries(int maxEntries) {
-      testImmutability("maxEntries");
-      this.maxEntries = maxEntries;
-   }
-
-   public int getMinEntries() {
-      return minEntries;
-   }
-
-   /**
-    * This specifies the minimum entries to prune down to when maxExtries has been hit.  -1 is the default value, which
-    * means this feature is effectively unset, and eviction algorithms would be expected to evict until the cache
-    * contains no more than maxEntries.  Any other value means that if a pruning process starts, it will not stop until
-    * minEntries has been reached.  So, for example, minEntries of 0 would mean that the cache is emptied the moment
-    * maxEntries is exceeded.
-    *
-    * @param minEntries minEntries value
-    */
-   public void setMinEntries(int minEntries) {
-      testImmutability("minEntries");
-      this.minEntries = minEntries;
-   }
-
-   /**
-    * @return The minimum time to live, in milliseconds.
-    */
-   public long getMinTimeToLive() {
-      return minTimeToLive;
-   }
-
-   /**
-    * @param minTimeToLive time to live, in milliseconds.  This defaults to -1, meaning that it is excluded from
-    *                      calculations.
-    */
-   public void setMinTimeToLive(long minTimeToLive) {
-      testImmutability("minTimeToLive");
-      this.minTimeToLive = minTimeToLive;
-   }
-
-   public void setMinTimeToLive(long time, TimeUnit timeUnit) {
-      testImmutability("minTimeToLive");
-      minTimeToLive = timeUnit.toMillis(time);
-   }
-
-   public void validate() throws ConfigurationException {
-      if (evictionAlgorithmClassName == null)
-         throw new ConfigurationException("Eviction algorithm class name cannot be null!");
-   }
-
-   @Override
-   public boolean equals(Object o) {
-      if (this == o) return true;
-      if (o == null || getClass() != o.getClass()) return false;
-
-      EvictionAlgorithmConfigBase that = (EvictionAlgorithmConfigBase) o;
-
-      if (maxEntries != that.maxEntries) return false;
-      if (minEntries != that.minEntries) return false;
-      if (minTimeToLive != that.minTimeToLive) return false;
-      if (evictionAlgorithmClassName != null ? !evictionAlgorithmClassName.equals(that.evictionAlgorithmClassName) : that.evictionAlgorithmClassName != null)
-         return false;
-
-      return true;
-   }
-
-   @Override
-   public int hashCode() {
-      int result = evictionAlgorithmClassName != null ? evictionAlgorithmClassName.hashCode() : 0;
-      result = 31 * result + maxEntries;
-      result = 31 * result + minEntries;
-      result = 31 * result + (int) (minTimeToLive ^ (minTimeToLive >>> 32));
-      return result;
-   }
-
-   @Override
-   public String toString() {
-      return getClass().getSimpleName() + "{" +
-            "evictionAlgorithmClassName='" + evictionAlgorithmClassName + '\'' +
-            ", maxEntries=" + maxEntries +
-            ", minEntries=" + minEntries +
-            ", minTimeToLive=" + minTimeToLive +
-            '}';
-   }
-
-   public void reset() {
-      maxEntries = -1;
-      minEntries = -1;
-      minTimeToLive = -1;
-   }
-
-   public EvictionAlgorithmConfigBase clone() {
-      try {
-         return (EvictionAlgorithmConfigBase) super.clone();
-      } catch (CloneNotSupportedException e) {
-         throw new RuntimeException("Should never happen", e);
-      }
-   }
-}

Modified: core/branches/flat/src/main/java/org/horizon/eviction/EvictionManagerImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/EvictionManagerImpl.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/EvictionManagerImpl.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -3,7 +3,6 @@
 import net.jcip.annotations.ThreadSafe;
 import org.horizon.Cache;
 import org.horizon.config.Configuration;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.config.EvictionConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.events.EvictionEvent;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,11 +22,10 @@
 package org.horizon.eviction.algorithms;
 
 import org.horizon.Cache;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.EvictionAction;
 import org.horizon.eviction.EvictionAlgorithm;
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.events.EvictionEvent;
@@ -57,7 +56,7 @@
    private static final boolean trace = log.isTraceEnabled();
 
    protected EvictionAction action;
-   protected EvictionAlgorithmConfigBase config;
+   protected BaseEvictionAlgorithmConfig config;
    // blocking queue of cache keys
    protected BlockingQueue<Object> recycleQueue;
    protected EvictionQueue evictionQueue;
@@ -120,7 +119,7 @@
    public void init(Cache<?, ?> cache, DataContainer<?, ?> dataContainer, EvictionAlgorithmConfig evictionAlgorithmConfig) {
       this.cache = cache;
       this.dataContainer = dataContainer;
-      this.config = (EvictionAlgorithmConfigBase) evictionAlgorithmConfig;
+      this.config = (BaseEvictionAlgorithmConfig) evictionAlgorithmConfig;
    }
 
    public boolean canIgnoreEvent(Type eventType) {

Copied: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithmConfig.java (from rev 7673, core/branches/flat/src/main/java/org/horizon/eviction/EvictionAlgorithmConfigBase.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithmConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,163 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 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.horizon.eviction.algorithms;
+
+import org.horizon.config.AbstractNamedCacheConfigurationBean;
+import org.horizon.config.ConfigurationException;
+import org.horizon.config.Dynamic;
+import org.horizon.eviction.EvictionAlgorithmConfig;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A base class used for configuring eviction algorithms.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 1.0
+ */
+public abstract class BaseEvictionAlgorithmConfig extends AbstractNamedCacheConfigurationBean implements EvictionAlgorithmConfig {
+   private static final long serialVersionUID = 4591691674370188932L;
+
+   protected String evictionAlgorithmClassName;
+   @Dynamic
+   protected int maxEntries = -1;
+   @Dynamic
+   protected int minEntries = -1;
+   @Dynamic
+   protected long minTimeToLive = -1;
+
+   /**
+    * Can only be instantiated by a subclass.
+    */
+   protected BaseEvictionAlgorithmConfig() {
+   }
+
+   public String getEvictionAlgorithmClassName() {
+      return evictionAlgorithmClassName;
+   }
+
+   public int getMaxEntries() {
+      return maxEntries;
+   }
+
+   /**
+    * @param maxEntries max entries to hold in the cache. 0 denotes immediate expiry and -1 denotes unlimited entries.
+    *                   -1 is the default
+    */
+   public void setMaxEntries(int maxEntries) {
+      testImmutability("maxEntries");
+      this.maxEntries = maxEntries;
+   }
+
+   public int getMinEntries() {
+      return minEntries;
+   }
+
+   /**
+    * This specifies the minimum entries to prune down to when maxExtries has been hit.  -1 is the default value, which
+    * means this feature is effectively unset, and eviction algorithms would be expected to evict until the cache
+    * contains no more than maxEntries.  Any other value means that if a pruning process starts, it will not stop until
+    * minEntries has been reached.  So, for example, minEntries of 0 would mean that the cache is emptied the moment
+    * maxEntries is exceeded.
+    *
+    * @param minEntries minEntries value
+    */
+   public void setMinEntries(int minEntries) {
+      testImmutability("minEntries");
+      this.minEntries = minEntries;
+   }
+
+   /**
+    * @return The minimum time to live, in milliseconds.
+    */
+   public long getMinTimeToLive() {
+      return minTimeToLive;
+   }
+
+   /**
+    * @param minTimeToLive time to live, in milliseconds.  This defaults to -1, meaning that it is excluded from
+    *                      calculations.
+    */
+   public void setMinTimeToLive(long minTimeToLive) {
+      testImmutability("minTimeToLive");
+      this.minTimeToLive = minTimeToLive;
+   }
+
+   public void setMinTimeToLive(long time, TimeUnit timeUnit) {
+      testImmutability("minTimeToLive");
+      minTimeToLive = timeUnit.toMillis(time);
+   }
+
+   public void validate() throws ConfigurationException {
+      if (evictionAlgorithmClassName == null)
+         throw new ConfigurationException("Eviction algorithm class name cannot be null!");
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      BaseEvictionAlgorithmConfig that = (BaseEvictionAlgorithmConfig) o;
+
+      if (maxEntries != that.maxEntries) return false;
+      if (minEntries != that.minEntries) return false;
+      if (minTimeToLive != that.minTimeToLive) return false;
+      if (evictionAlgorithmClassName != null ? !evictionAlgorithmClassName.equals(that.evictionAlgorithmClassName) : that.evictionAlgorithmClassName != null)
+         return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = evictionAlgorithmClassName != null ? evictionAlgorithmClassName.hashCode() : 0;
+      result = 31 * result + maxEntries;
+      result = 31 * result + minEntries;
+      result = 31 * result + (int) (minTimeToLive ^ (minTimeToLive >>> 32));
+      return result;
+   }
+
+   @Override
+   public String toString() {
+      return getClass().getSimpleName() + "{" +
+            "evictionAlgorithmClassName='" + evictionAlgorithmClassName + '\'' +
+            ", maxEntries=" + maxEntries +
+            ", minEntries=" + minEntries +
+            ", minTimeToLive=" + minTimeToLive +
+            '}';
+   }
+
+   public void reset() {
+      maxEntries = -1;
+      minEntries = -1;
+      minTimeToLive = -1;
+   }
+
+   public BaseEvictionAlgorithmConfig clone() {
+      try {
+         return (BaseEvictionAlgorithmConfig) super.clone();
+      } catch (CloneNotSupportedException e) {
+         throw new RuntimeException("Should never happen", e);
+      }
+   }
+}


Property changes on: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/BaseEvictionAlgorithmConfig.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,7 +22,7 @@
 package org.horizon.eviction.algorithms.fifo;
 
 import net.jcip.annotations.NotThreadSafe;
-import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/fifo/FIFOAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -21,7 +21,7 @@
  */
 package org.horizon.eviction.algorithms.fifo;
 
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig;
 
 /**
  * Configuration for {@link FIFOAlgorithm}.
@@ -29,7 +29,7 @@
  * @author Manik Surtani
  * @since 1.0
  */
-public class FIFOAlgorithmConfig extends EvictionAlgorithmConfigBase {
+public class FIFOAlgorithmConfig extends BaseEvictionAlgorithmConfig {
    /**
     * The serialVersionUID
     */

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,7 +22,7 @@
 package org.horizon.eviction.algorithms.lfu;
 
 import net.jcip.annotations.NotThreadSafe;
-import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lfu/LFUAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -21,7 +21,7 @@
  */
 package org.horizon.eviction.algorithms.lfu;
 
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig;
 
 /**
  * Configuration implementation for {@link LFUAlgorithm}.
@@ -29,7 +29,7 @@
  * @author Manik Surtani
  * @since 1.0
  */
-public class LFUAlgorithmConfig extends EvictionAlgorithmConfigBase {
+public class LFUAlgorithmConfig extends BaseEvictionAlgorithmConfig {
    /**
     * The serialVersionUID
     */

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,7 +22,7 @@
 package org.horizon.eviction.algorithms.lru;
 
 import net.jcip.annotations.NotThreadSafe;
-import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/lru/LRUAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -21,7 +21,7 @@
  */
 package org.horizon.eviction.algorithms.lru;
 
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig;
 
 /**
  * Configuration implementation for {@link LRUAlgorithm}.
@@ -30,7 +30,7 @@
  * @author Manik Surtani
  * @since 1.0
  */
-public class LRUAlgorithmConfig extends EvictionAlgorithmConfigBase {
+public class LRUAlgorithmConfig extends BaseEvictionAlgorithmConfig {
    /**
     * The serialVersionUID
     */

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,7 +22,7 @@
 package org.horizon.eviction.algorithms.mru;
 
 import net.jcip.annotations.NotThreadSafe;
-import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.algorithms.BaseEvictionAlgorithm;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/mru/MRUAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -21,7 +21,7 @@
  */
 package org.horizon.eviction.algorithms.mru;
 
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.algorithms.BaseEvictionAlgorithmConfig;
 
 /**
  * Configuration for {@link MRUAlgorithm}.
@@ -29,7 +29,7 @@
  * @author Manik Surtani
  * @since 1.0
  */
-public class MRUAlgorithmConfig extends EvictionAlgorithmConfigBase {
+public class MRUAlgorithmConfig extends BaseEvictionAlgorithmConfig {
    /**
     * The serialVersionUID
     */

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithm.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithm.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithm.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -22,10 +22,10 @@
 package org.horizon.eviction.algorithms.nullalgo;
 
 import org.horizon.Cache;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.EvictionAction;
 import org.horizon.eviction.EvictionAlgorithm;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.EvictionException;
 import org.horizon.eviction.EvictionQueue;
 import org.horizon.eviction.events.EvictionEvent;

Modified: core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithmConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithmConfig.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/eviction/algorithms/nullalgo/NullEvictionAlgorithmConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -23,7 +23,7 @@
 
 import org.horizon.config.AbstractNamedCacheConfigurationBean;
 import org.horizon.config.ConfigurationException;
-import org.horizon.config.EvictionAlgorithmConfig;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 
 /**
  * Configuration class for {@link NullEvictionAlgorithm}.

Modified: core/branches/flat/src/main/java/org/horizon/factories/EmptyConstructorNamedCacheFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/factories/EmptyConstructorNamedCacheFactory.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/factories/EmptyConstructorNamedCacheFactory.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -28,7 +28,7 @@
 import org.horizon.factories.annotations.DefaultFactoryFor;
 import org.horizon.factories.context.ContextFactory;
 import org.horizon.invocation.InvocationContextContainer;
-import org.horizon.loaderold.CacheLoaderManager;
+import org.horizon.loader.CacheLoaderManager;
 import org.horizon.marshall.Marshaller;
 import org.horizon.marshall.VersionAwareMarshaller;
 import org.horizon.notifications.cachelistener.CacheNotifier;

Modified: core/branches/flat/src/main/java/org/horizon/interceptors/CacheLoaderInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/interceptors/CacheLoaderInterceptor.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/interceptors/CacheLoaderInterceptor.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -35,8 +35,8 @@
 import org.horizon.factories.annotations.Inject;
 import org.horizon.factories.annotations.Start;
 import org.horizon.interceptors.base.JmxStatsCommandInterceptor;
-import org.horizon.loaderold.CacheLoaderManager;
-import org.horizon.loaderold.CacheLoaderOld;
+import org.horizon.loader.CacheLoader;
+import org.horizon.loader.CacheLoaderManager;
 import org.horizon.notifications.cachelistener.CacheNotifier;
 import org.horizon.transaction.TransactionTable;
 
@@ -55,7 +55,7 @@
    private CacheLoaderManager clm;
 
    protected TransactionTable txTable = null;
-   protected CacheLoaderOld<Object, Object> loader;
+   protected CacheLoader loader;
    protected DataContainer<Object, Object> dataContainer;
    protected CacheNotifier notifier;
    protected EntryFactory entryFactory;
@@ -126,7 +126,7 @@
    }
 
    private void loadIfNeeded(InvocationContext ctx, Object key) throws Throwable {
-      if (dataContainer.containsKey(key) || !loader.exists(key))
+      if (dataContainer.containsKey(key) || !loader.containsKey(key))
          return;
 
       // Obtain a temporary lock to verify the key is not being concurrently added
@@ -149,7 +149,7 @@
    private MVCCEntry loadEntry(InvocationContext ctx, Object key, MVCCEntry entry) throws Exception {
       if (trace) log.trace("loading entry " + key + " entry is " + entry);
 
-      Object value = loader.get(key);
+      Object value = loader.load(key);
       boolean nodeExists = (value != null);
       if (trace) log.trace("nodeExists " + nodeExists);
 

Modified: core/branches/flat/src/main/java/org/horizon/interceptors/CacheStoreInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/interceptors/CacheStoreInterceptor.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/interceptors/CacheStoreInterceptor.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -30,7 +30,8 @@
 import org.horizon.commands.write.PutKeyValueCommand;
 import org.horizon.commands.write.PutMapCommand;
 import org.horizon.commands.write.RemoveCommand;
-import org.horizon.config.CacheLoaderConfig;
+import org.horizon.config.CacheLoaderManagerConfig;
+import org.horizon.container.DataContainer;
 import org.horizon.context.InvocationContext;
 import org.horizon.context.TransactionContext;
 import org.horizon.factories.annotations.Inject;
@@ -39,10 +40,13 @@
 import org.horizon.invocation.Options;
 import org.horizon.jmx.annotations.ManagedAttribute;
 import org.horizon.jmx.annotations.ManagedOperation;
-import org.horizon.loaderold.CacheLoaderManager;
-import org.horizon.loaderold.CacheLoaderOld;
-import org.horizon.loaderold.Modification;
-import org.horizon.loaderold.Modification.ModificationType;
+import org.horizon.loader.CacheLoaderManager;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.loader.modifications.Clear;
+import org.horizon.loader.modifications.Modification;
+import org.horizon.loader.modifications.Remove;
+import org.horizon.loader.modifications.Store;
 import org.horizon.logging.LogFactory;
 import org.horizon.transaction.GlobalTransaction;
 
@@ -64,14 +68,15 @@
  * @since 1.0
  */
 public class CacheStoreInterceptor extends JmxStatsCommandInterceptor {
-   private CacheLoaderConfig loaderConfig = null;
+   private CacheLoaderManagerConfig loaderConfig = null;
    private TransactionManager txMgr = null;
    private HashMap<GlobalTransaction, Integer> txStores = new HashMap<GlobalTransaction, Integer>();
    private Map<GlobalTransaction, Set<Object>> preparingTxs = new ConcurrentHashMap<GlobalTransaction, Set<Object>>();
    private long cacheStores = 0;
-   CacheLoaderOld<Object, Object> loader;
+   CacheStore store;
    private CacheLoaderManager loaderManager;
    private boolean statsEnabled;
+   private DataContainer dataContainer;
 
    public CacheStoreInterceptor() {
       log = LogFactory.getLog(getClass());
@@ -79,17 +84,18 @@
    }
 
    @Inject
-   protected void init(CacheLoaderManager loaderManager, TransactionManager txManager, CacheLoaderConfig clConfig) {
+   protected void init(CacheLoaderManager loaderManager, TransactionManager txManager, CacheLoaderManagerConfig clConfig, DataContainer dataContainer) {
       // never inject a CacheLoaderOld at this stage - only a CacheLoaderManager, since the CacheLoaderManager only creates a CacheLoaderOld instance when it @Starts.
       this.loaderManager = loaderManager;
       this.loaderConfig = clConfig;
       txMgr = txManager;
+      this.dataContainer = dataContainer;
    }
 
    @Start
    protected void start() {
       // this should only happen after the CacheLoaderManager has started, since the CacheLoaderManager only creates the CacheLoaderOld instance in its @Start method.
-      loader = loaderManager.getCacheLoader();
+      store = loaderManager.getCacheStore();
       this.setStatisticsEnabled(configuration.isExposeManagementStatistics());
    }
 
@@ -97,6 +103,7 @@
     * if this is a shared cache loader and the call is of remote origin, pass up the chain
     */
    public final boolean skip(InvocationContext ctx, VisitableCommand command) {
+      if (store == null) return true;
       if ((!ctx.isOriginLocal() && loaderConfig.isShared()) || ctx.hasOption(Options.SKIP_CACHE_STORE)) {
          if (trace)
             log.trace("Passing up method call and bypassing this interceptor since the cache loader is shared and this call originated remotely.");
@@ -116,7 +123,7 @@
             // ignore modified FQNs
             // List fqnsModified = getFqnsFromModificationList(txTable.get(globalTransaction).getCacheLoaderModifications());
             try {
-               loader.commit(gtx);
+//               store.commit(gtx);
             }
             catch (Throwable t) {
                preparingTxs.remove(gtx);
@@ -146,7 +153,7 @@
             // this is a rollback method
             if (preparingTxs.containsKey(gtx)) {
                preparingTxs.remove(gtx);
-               loader.rollback(gtx);
+//               store.rollback(gtx);
             }
             if (getStatisticsEnabled()) txStores.remove(gtx);
          } else {
@@ -168,7 +175,7 @@
    @Override
    public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
       if (!skip(ctx, command) && !inTransaction()) {
-         Object returnValue = loader.remove(command.getKey());
+         Object returnValue = store.remove(command.getKey());
          invokeNextInterceptor(ctx, command);
          return returnValue;
       }
@@ -181,7 +188,7 @@
       if (skip(ctx, command) || inTransaction())
          return returnValue;
 
-      returnValue = loader.put(command.getKey(), command.getValue());
+      store.store((StoredEntry) null);//command.getKey(), command.getValue());
       if (getStatisticsEnabled()) cacheStores++;
 
       return returnValue;
@@ -196,7 +203,7 @@
       // Perhaps this should be optimized
       Map<Object, Object> map = command.getMap();
       List<Modification> modifications = toModifications(map);
-      loader.put(modifications);
+//      store.put(modifications);
 
       if (getStatisticsEnabled()) cacheStores++;
 
@@ -205,8 +212,9 @@
 
    private static List<Modification> toModifications(Map<Object, Object> map) {
       List<Modification> modifications = new ArrayList<Modification>(map.size());
-      for (Map.Entry<Object, Object> entry : map.entrySet())
-         modifications.add(new Modification(ModificationType.PUT, entry.getKey(), entry.getValue()));
+      // TODO fix me
+//      for (Map.Entry<Object, Object> entry : map.entrySet())
+//         modifications.add(new Modification(ModificationType.PUT, entry.getKey(), entry.getValue()));
       return modifications;
    }
 
@@ -232,7 +240,7 @@
          log.trace("Converted method calls to cache loader modifications.  List size: " + modsBuilder.modifications.size());
       }
       if (modsBuilder.modifications.size() > 0) {
-         loader.prepare(gtx, modsBuilder.modifications, onePhase);
+//         loader.prepare(gtx, modsBuilder.modifications, onePhase);
 
          preparingTxs.put(gtx, modsBuilder.affectedKeys);
          if (getStatisticsEnabled() && modsBuilder.putCount > 0) {
@@ -241,7 +249,7 @@
       }
    }
 
-   public static class StoreModificationsBuilder extends AbstractVisitor {
+   public class StoreModificationsBuilder extends AbstractVisitor {
 
       boolean generateStatistics;
 
@@ -256,32 +264,37 @@
       }
 
       @Override
+      @SuppressWarnings("unchecked")
       public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
          if (generateStatistics) putCount++;
-         modifications.add(new Modification(Modification.ModificationType.PUT, command.getKey(), command.getValue()));
+         modifications.add(new Store(dataContainer.createEntryForStorage(command.getKey())));
          affectedKeys.add(command.getKey());
          return null;
       }
 
       @Override
+      @SuppressWarnings("unchecked")
       public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
          Map<Object, Object> map = command.getMap();
          if (generateStatistics) putCount += map.size();
          affectedKeys.addAll(map.keySet());
-         modifications.addAll(toModifications(map));
+         Set<StoredEntry> entries = new HashSet<StoredEntry>();
+         for (Object key : map.keySet()) modifications.add(new Store(dataContainer.createEntryForStorage(key)));
          return null;
       }
 
       @Override
+      @SuppressWarnings("unchecked")
       public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
-         modifications.add(new Modification(Modification.ModificationType.REMOVE, command.getKey(), null));
+         modifications.add(new Remove(command.getKey()));
          affectedKeys.add(command.getKey());
          return null;
       }
 
       @Override
+      @SuppressWarnings("unchecked")
       public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
-         modifications.add(new Modification(Modification.ModificationType.CLEAR, null, null));
+         modifications.add(new Clear());
          return null;
       }
    }

Added: core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoader.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoader.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,10 @@
+package org.horizon.loader;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public abstract class AbstractCacheLoader<K, V> implements CacheLoader<K, V> {
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoaderConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoaderConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheLoaderConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,129 @@
+package org.horizon.loader;
+
+import org.horizon.config.PluggableConfigurationComponent;
+import org.horizon.loader.decorators.SingletonStoreConfig;
+import org.horizon.util.Util;
+
+public class AbstractCacheLoaderConfig extends PluggableConfigurationComponent implements CacheLoaderConfig {
+   private boolean async;
+   private boolean ignoreModifications;
+   private boolean fetchPersistentState;
+   private boolean purgeOnStartup;
+   private SingletonStoreConfig singletonStoreConfig;
+
+//   protected void populateFromBaseConfig(CacheLoaderManagerConfig.IndividualCacheLoaderConfig base) {
+//      if (base != null) {
+//         setAsync(base.isAsync());
+//         setIgnoreModifications(base.isIgnoreModifications());
+//         setFetchPersistentState(base.isFetchPersistentState());
+//         setSingletonStoreConfig(base.getSingletonStoreConfig());
+//         setPurgeOnStartup(base.isPurgeOnStartup());
+//         setProperties(base.getProperties());
+//      }
+//   }
+
+   public boolean isPurgeOnStartup() {
+      return purgeOnStartup;
+   }
+
+   public boolean isFetchPersistentState() {
+      return fetchPersistentState;
+   }
+
+   public void setFetchPersistentState(boolean fetchPersistentState) {
+      testImmutability("fetchPersistentState");
+      this.fetchPersistentState = fetchPersistentState;
+   }
+
+   public void setAsync(boolean async) {
+      testImmutability("async");
+      this.async = async;
+   }
+
+   public boolean isAsync() {
+      return async;
+   }
+
+   public void setIgnoreModifications(boolean ignoreModifications) {
+      testImmutability("ignoreModifications");
+      this.ignoreModifications = ignoreModifications;
+   }
+
+   public boolean isIgnoreModifications() {
+      return ignoreModifications;
+   }
+
+   public void setPurgeOnStartup(boolean purgeOnStartup) {
+      testImmutability("purgeOnStartup");
+      this.purgeOnStartup = purgeOnStartup;
+   }
+
+   public SingletonStoreConfig getSingletonStoreConfig() {
+      return singletonStoreConfig;
+   }
+
+   public void setSingletonStoreConfig(SingletonStoreConfig singletonStoreConfig) {
+      testImmutability("singletonStoreConfig");
+      this.singletonStoreConfig = singletonStoreConfig;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (super.equals(obj)) {
+         if (!(obj instanceof AbstractCacheLoaderConfig)) return false;
+         AbstractCacheLoaderConfig i = (AbstractCacheLoaderConfig) obj;
+         return equalsExcludingProperties(i);
+      }
+      return false;
+   }
+
+   protected boolean equalsExcludingProperties(Object obj) {
+      AbstractCacheLoaderConfig other = (AbstractCacheLoaderConfig) obj;
+
+      return Util.safeEquals(this.className, other.className)
+            && (this.async == other.async)
+            && (this.ignoreModifications == other.ignoreModifications)
+            && (this.fetchPersistentState == other.fetchPersistentState)
+            && Util.safeEquals(this.singletonStoreConfig, other.singletonStoreConfig);
+   }
+
+   @Override
+   public int hashCode() {
+      return 31 * hashCodeExcludingProperties() + (properties == null ? 0 : properties.hashCode());
+   }
+
+   protected int hashCodeExcludingProperties() {
+      int result = 17;
+      result = 31 * result + (className == null ? 0 : className.hashCode());
+      result = 31 * result + (async ? 0 : 1);
+      result = 31 * result + (ignoreModifications ? 0 : 1);
+      result = 31 * result + (fetchPersistentState ? 0 : 1);
+      result = 31 * result + (singletonStoreConfig == null ? 0 : singletonStoreConfig.hashCode());
+      result = 31 * result + (purgeOnStartup ? 0 : 1);
+      return result;
+   }
+
+   @Override
+   public String toString() {
+      return new StringBuilder().append("IndividualCacheLoaderConfig{").append("className='").append(className).append('\'')
+            .append(", async=").append(async)
+            .append(", ignoreModifications=").append(ignoreModifications)
+            .append(", fetchPersistentState=").append(fetchPersistentState)
+            .append(", properties=").append(properties)
+            .append(", purgeOnStartup=").append(purgeOnStartup).append("},")
+            .append("SingletonStoreConfig{").append(singletonStoreConfig).append('}')
+            .toString();
+   }
+
+   @Override
+   public AbstractCacheLoaderConfig clone() {
+      AbstractCacheLoaderConfig clone = null;
+      try {
+         clone = (AbstractCacheLoaderConfig) super.clone();
+      } catch (CloneNotSupportedException e) {
+         throw new RuntimeException("Should not happen!", e);
+      }
+      if (singletonStoreConfig != null) clone.setSingletonStoreConfig(singletonStoreConfig.clone());
+      return clone;
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheStore.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/AbstractCacheStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,38 @@
+package org.horizon.loader;
+
+import org.horizon.loader.modifications.Modification;
+import org.horizon.loader.modifications.Remove;
+import org.horizon.loader.modifications.Store;
+
+import java.util.List;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public abstract class AbstractCacheStore<K, V> extends AbstractCacheLoader<K, V> implements CacheStore<K, V> {
+
+   @SuppressWarnings("unchecked")
+   protected void applyModifications(List<Modification> mods) {
+      for (Modification m : mods) {
+         switch (m.getType()) {
+            case STORE:
+               Store<K, V> s = (Store<K, V>) m;
+               store(s.getStoredEntry());
+               break;
+            case CLEAR:
+               clear();
+               break;
+            case REMOVE:
+               Remove<K> r = (Remove<K>) m;
+               remove(r.getKey());
+               break;
+            default:
+               throw new IllegalArgumentException("Unknown modification type " + m.getType());
+         }
+      }
+   }
+
+}

Copied: core/branches/flat/src/main/java/org/horizon/loader/CacheLoader.java (from rev 7675, core/branches/flat/src/main/java/org/horizon/loaderold/CacheLoader.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/CacheLoader.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/CacheLoader.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,56 @@
+package org.horizon.loader;
+
+import org.horizon.Cache;
+import org.horizon.lifecycle.Lifecycle;
+import org.horizon.marshall.Marshaller;
+
+import java.util.Set;
+
+/**
+ * Responsible for loading cache data from an external source
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public interface CacheLoader<K, V> extends Lifecycle {
+
+   /**
+    * Used to initialize a cache loader.  Typically invoked by the {@link org.horizon.loader.CacheLoaderManager} when
+    * setting up cache loaders.
+    *
+    * @param config the cache loader configuration bean
+    * @param cache  cache associated with this cache loader. Implementations may use this to determine cache name when
+    *               selecting where refer to state in storage, for example, a different database table name.
+    * @param m      marshaller to use when loading state from a stream, if supported by the implementation.
+    */
+   void init(CacheLoaderConfig config, Cache cache, Marshaller m);
+
+   /**
+    * Loads an entry mapped to by a given key.  Should return null if the entry does not exist.  Expired entries are not
+    * returned.
+    *
+    * @param key key
+    * @return an entry
+    */
+   StoredEntry<K, V> load(K key);
+
+   /**
+    * Loads all entries in the loader.  Expired entries are not returned.
+    *
+    * @return a set of entries, or an empty set if the loader is emptied.
+    */
+   Set<StoredEntry<K, V>> loadAll();
+
+   /**
+    * @param key key to test
+    * @return true if the key exists, false otherwise
+    */
+   boolean containsKey(K key);
+
+
+   /**
+    * @return the type of the {@link org.horizon.loader.CacheLoaderConfig} bean used to configure this implementation of
+    *         {@link org.horizon.loader.CacheLoader}
+    */
+   Class<? extends CacheLoaderConfig> getConfigurationClass();
+}

Copied: core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderConfig.java (from rev 7675, core/branches/flat/src/main/java/org/horizon/config/CacheLoaderConfig.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,37 @@
+package org.horizon.loader;
+
+import org.horizon.loader.decorators.SingletonStoreConfig;
+
+/**
+ * Configures individual cache loaders
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public interface CacheLoaderConfig extends Cloneable {
+   boolean isPurgeOnStartup();
+
+   boolean isFetchPersistentState();
+
+   void setFetchPersistentState(boolean fetchPersistentState);
+
+   void setAsync(boolean async);
+
+   boolean isAsync();
+
+   void setIgnoreModifications(boolean ignoreModifications);
+
+   boolean isIgnoreModifications();
+
+   void setPurgeOnStartup(boolean purgeOnStartup);
+
+   SingletonStoreConfig getSingletonStoreConfig();
+
+   void setSingletonStoreConfig(SingletonStoreConfig singletonStoreConfig);
+
+   CacheLoaderConfig clone();
+
+   String getClassName();
+
+   void setClassName(String s);
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManager.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManager.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManager.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,28 @@
+package org.horizon.loader;
+
+import org.horizon.lifecycle.Lifecycle;
+
+/**
+ * The cache loader manager interface
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public interface CacheLoaderManager extends Lifecycle {
+
+   CacheLoader getCacheLoader();
+
+   CacheStore getCacheStore();
+
+   void purge();
+
+   boolean isUsingPassivation();
+
+   boolean isShared();
+
+   boolean isFetchPersistentState();
+
+   void preload();
+}
+
+

Added: core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManagerImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManagerImpl.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/CacheLoaderManagerImpl.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,200 @@
+package org.horizon.loader;
+
+import org.horizon.Cache;
+import org.horizon.CacheException;
+import org.horizon.config.CacheLoaderManagerConfig;
+import org.horizon.config.Configuration;
+import org.horizon.config.ConfigurationException;
+import org.horizon.factories.annotations.Inject;
+import org.horizon.factories.annotations.Start;
+import org.horizon.factories.annotations.Stop;
+import org.horizon.invocation.Options;
+import org.horizon.loader.decorators.AsyncStore;
+import org.horizon.loader.decorators.ChainingCacheLoader;
+import org.horizon.loader.decorators.ReadOnlyStore;
+import org.horizon.loader.decorators.SingletonStore;
+import org.horizon.loader.decorators.SingletonStoreConfig;
+import org.horizon.logging.Log;
+import org.horizon.logging.LogFactory;
+import org.horizon.marshall.Marshaller;
+import org.horizon.util.ReflectionUtil;
+import org.horizon.util.Util;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+public class CacheLoaderManagerImpl implements CacheLoaderManager {
+
+   Configuration configuration;
+   CacheLoaderManagerConfig clmConfig;
+   Cache<Object, Object> cache;
+   Marshaller m;
+   CacheLoader loader;
+   private static final Log log = LogFactory.getLog(CacheLoaderManagerImpl.class);
+
+   @Inject
+   public void inject(Cache cache, Marshaller marshaller, Configuration configuration) {
+      this.cache = cache;
+      this.m = marshaller;
+      this.configuration = configuration;
+   }
+
+   public CacheLoader getCacheLoader() {
+      return loader;
+   }
+
+   public final CacheStore getCacheStore() {
+      if (loader != null && loader instanceof CacheStore) {
+         return (CacheStore) loader;
+      } else {
+         return null;
+      }
+   }
+
+   public void purge() {
+      CacheStore cs = getCacheStore();
+      if (cs != null) cs.clear();
+   }
+
+   private void purgeLoaders(boolean force) throws Exception {
+      CacheStore cs = getCacheStore();
+      if (cs != null) {
+         if ((cs instanceof ChainingCacheLoader) && !force) {
+            ((ChainingCacheLoader) loader).purgeIfNecessary();
+         } else {
+            CacheLoaderConfig first = clmConfig.getFirstCacheLoaderConfig();
+            if (force || (first != null && first.isPurgeOnStartup())) {
+               cs.clear();
+            }
+         }
+      }
+   }
+
+   public boolean isUsingPassivation() {
+      return clmConfig.isPassivation();
+   }
+
+   public boolean isShared() {
+      return clmConfig.isShared();
+   }
+
+   public boolean isFetchPersistentState() {
+      return clmConfig.isFetchPersistentState();
+   }
+
+   @Start
+   public void start() {
+      clmConfig = configuration.getCacheLoaderConfig();
+      if (clmConfig != null) {
+         try {
+            loader = createCacheLoader();
+            if (loader != null) loader.start();
+            purgeLoaders(false);
+         } catch (Exception e) {
+            throw new CacheException("Unable to start cache loaders", e);
+         }
+      }
+   }
+
+   /**
+    * Performs a preload on the cache based on the cache loader preload configs used when configuring the cache.
+    */
+   @Start(priority = 50)
+   public void preload() {
+      if (loader != null) {
+         if (clmConfig.isPreload()) {
+            log.debug("Preloading transient state from cache loader {0}", loader);
+            long start = 0, stop = 0, total = 0;
+            if (log.isDebugEnabled()) start = System.currentTimeMillis();
+            Set<StoredEntry> state = loader.loadAll();
+
+            for (StoredEntry se : state)
+               cache.getAdvancedCache().put(se.getKey(), se.getValue(), se.getLifespan(),
+                                            TimeUnit.MILLISECONDS, Options.SKIP_CACHE_STATUS_CHECK);
+
+            if (log.isDebugEnabled()) stop = System.currentTimeMillis();
+            if (log.isDebugEnabled()) total = stop - start;
+            log.debug("Preloaded {0} keys in {1} milliseconds", state.size(), total);
+         }
+      }
+   }
+
+   @Stop
+   public void stop() {
+      if (loader != null) loader.stop();
+      loader = null;
+   }
+
+   CacheLoader createCacheLoader() throws Exception {
+      CacheLoader tmpLoader;
+      // if we only have a single cache loader configured in the chaining cacheloader then
+      // don't use a chaining cache loader at all.
+      // also if we are using passivation then just directly use the first cache loader.
+      if (clmConfig.useChainingCacheLoader()) {
+         // create chaining cache loader.
+         ChainingCacheLoader ccl = new ChainingCacheLoader();
+         tmpLoader = ccl;
+
+         // only one cache loader may have fetchPersistentState to true.
+         int numLoadersWithFetchPersistentState = 0;
+         for (CacheLoaderConfig cfg : clmConfig.getIndividualCacheLoaderConfigs()) {
+            if (cfg.isFetchPersistentState()) numLoadersWithFetchPersistentState++;
+
+            if (numLoadersWithFetchPersistentState > 1)
+               throw new Exception("Invalid cache loader configuration!!  Only ONE cache loader may have fetchPersistentState set to true.  Cache will not start!");
+
+            assertNotSingletonAndShared(cfg);
+
+            CacheLoader l = createCacheLoader(cfg, cache);
+            ccl.addCacheLoader(l, cfg);
+         }
+      } else {
+         CacheLoaderConfig cfg = clmConfig.getFirstCacheLoaderConfig();
+         tmpLoader = createCacheLoader(cfg, cache);
+         assertNotSingletonAndShared(cfg);
+      }
+
+      // Update the config with those actually used by the loaders
+      ReflectionUtil.setValue(clmConfig, "accessible", true);
+
+      return tmpLoader;
+   }
+
+   CacheLoader createCacheLoader(CacheLoaderConfig cfg, Cache cache) throws Exception {
+      CacheLoader tmpLoader = (CacheLoader) Util.getInstance(cfg.getClassName());
+
+      if (tmpLoader != null) {
+         if (tmpLoader instanceof CacheStore) {
+            CacheStore tmpStore = (CacheStore) tmpLoader;
+            // async?
+            if (cfg.isAsync()) {
+               tmpStore = new AsyncStore(tmpStore);
+               tmpLoader = tmpStore;
+            }
+
+            // read only?
+            if (cfg.isIgnoreModifications()) {
+               tmpStore = new ReadOnlyStore(tmpStore);
+               tmpLoader = tmpStore;
+            }
+
+            // singleton?
+            SingletonStoreConfig ssc = cfg.getSingletonStoreConfig();
+            if (ssc != null && ssc.isSingletonStoreEnabled()) {
+               tmpStore = new SingletonStore(tmpStore);
+               tmpLoader = tmpStore;
+            }
+         }
+
+         // load props
+         tmpLoader.init(cfg, cache, m);
+      }
+      return tmpLoader;
+   }
+
+   void assertNotSingletonAndShared(CacheLoaderConfig cfg) {
+      SingletonStoreConfig ssc = cfg.getSingletonStoreConfig();
+      if (ssc != null && ssc.isSingletonStoreEnabled() && clmConfig.isShared())
+         throw new ConfigurationException("Invalid cache loader configuration!!  If a cache loader is configured as a singleton, the cache loader cannot be shared in a cluster!");
+   }
+}

Copied: core/branches/flat/src/main/java/org/horizon/loader/CacheStore.java (from rev 7675, core/branches/flat/src/main/java/org/horizon/loaderold/CacheStore.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/CacheStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/CacheStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,89 @@
+package org.horizon.loader;
+
+import org.horizon.loader.modifications.Modification;
+
+import javax.transaction.Transaction;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * A specialization of the {@link CacheLoader} interface that can be written to.
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public interface CacheStore<K, V> extends CacheLoader<K, V> {
+
+   /**
+    * Stores an entry
+    *
+    * @param ed entry to store
+    */
+   void store(StoredEntry<K, V> ed);
+
+   /**
+    * Writes contents of the stream to the store.  Implementations should expect that the stream contains data in an
+    * implementation-specific format, typically generated using {@link #load(java.io.OutputStream)}.  While not a
+    * requirement, it is recommended that implementations make use of the {@link org.horizon.marshall.Marshaller} when
+    * dealing with the stream to make use of efficient marshalling.
+    *
+    * @param inputStream stream to read from
+    */
+   void store(InputStream inputStream) throws IOException, ClassNotFoundException;
+
+   /**
+    * Loads the entire state into a stream, using whichever format is most efficient for the cache loader
+    * implementation. Typically read and parsed by {@link #store(java.io.InputStream)}.
+    * <p/>
+    * While not a requirement, it is recommended that implementations make use of the {@link
+    * org.horizon.marshall.Marshaller} when dealing with the stream to make use of efficient marshalling.
+    *
+    * @param outputStream stream to write to
+    * @throws java.io.IOException in the event of problems writing to the stream
+    */
+   void load(OutputStream outputStream) throws IOException;
+
+   /**
+    * Clears all entries in the store
+    */
+   void clear();
+
+   /**
+    * Removes an entry in the store.
+    *
+    * @param key key to remove
+    * @return true if the entry was removed; false if the entry wasn't found.
+    */
+   boolean remove(K key);
+
+   /**
+    * Purges expired entries from the store.
+    */
+   void purgeExpired();
+
+   /**
+    * Issues a prepare call with a set of modifications to be applied to the cache store
+    *
+    * @param modifications modifications to be applied
+    * @param tx            transaction identifier
+    * @param isOnePhase    if true, there will not be a commit or rollback phase and changes should be flushed
+    *                      immediately
+    */
+   void prepare(List<Modification> modifications, Transaction tx, boolean isOnePhase);
+
+   /**
+    * Commits a transaction that has been previously prepared
+    *
+    * @param tx tx to commit
+    */
+   void commit(Transaction tx);
+
+   /**
+    * Rolls back a transaction that has been previously prepared
+    *
+    * @param tx tx to roll back
+    */
+   void rollback(Transaction tx);
+}

Copied: core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java (from rev 7675, core/branches/flat/src/main/java/org/horizon/loaderold/StoredEntry.java)
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/StoredEntry.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,74 @@
+package org.horizon.loader;
+
+import org.horizon.container.ExpirableCachedValue;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * An entry that is stored in a cache loader.
+ *
+ * @author Manik Surtani
+ */
+public class StoredEntry<K, V> extends ExpirableCachedValue<V> implements Externalizable {
+   private K key;
+
+   public StoredEntry() {
+   }
+
+   public StoredEntry(K key, V value, long created, long expiry) {
+      super(value, created, expiry);
+      this.key = key;
+   }
+
+   public final K getKey() {
+      return key;
+   }
+
+   public final long getLifespan() {
+      if (createdTime < 0 || expiryTime < 0) return -1;
+      return expiryTime - createdTime;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      StoredEntry that = (StoredEntry) o;
+
+      if (key != null ? !key.equals(that.key) : that.key != null) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      return key != null ? key.hashCode() : 0;
+   }
+
+   @Override
+   public String toString() {
+      return "StoredEntry{" +
+            "key=" + key +
+            '}';
+   }
+
+   public void writeExternal(ObjectOutput out) throws IOException {
+      out.writeObject(key);
+      out.writeObject(value);
+      out.writeLong(createdTime);
+      out.writeLong(expiryTime);
+   }
+
+   @SuppressWarnings("unchecked")
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      key = (K) in.readObject();
+      value = (V) in.readObject();
+      createdTime = in.readLong();
+      expiryTime = in.readLong();
+      modifiedTime = System.currentTimeMillis();
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/AbstractDelegatingStore.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/AbstractDelegatingStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/AbstractDelegatingStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,21 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.loader.CacheStore;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ */
+public abstract class AbstractDelegatingStore implements CacheStore {
+
+   CacheStore delegate;
+
+   public void setDelegate(CacheStore cacheStore) {
+      this.delegate = cacheStore;
+   }
+
+   public CacheStore getDelegate() {
+      return delegate;
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/AsyncStore.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/AsyncStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/AsyncStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,107 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.Cache;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An asynchronous wrapper around a cache store
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class AsyncStore implements CacheStore {
+
+   CacheStore delegate;
+
+   public AsyncStore(CacheStore delegate) {
+      this.delegate = delegate;
+   }
+
+   public void store(StoredEntry ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void storeAll(Collection ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void store(InputStream inputStream) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void clear() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public boolean remove(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public void purgeExpired() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void commit(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void rollback(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void prepare(List list, Transaction tx, boolean isOnePhase) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, TransactionManager tm, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public StoredEntry load(Object key) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll(Collection keys) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public boolean containsKey(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public Class getConfigurationClass() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public void start() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void stop() {
+      // TODO: Manik: Customise this generated block
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/ChainingCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/ChainingCacheLoader.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/ChainingCacheLoader.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,114 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.Cache;
+import org.horizon.loader.CacheLoader;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A chaining cache loader that allows us to configure > 1 cache loader.
+ * <p/>
+ * READ operations are directed to each of the cache loaders (in the order which they were configured) until a non-null
+ * (or non-empty in the case of retrieving collection objects) result is achieved.
+ * <p/>
+ * WRITE operations are propagated to ALL registered cache stores specified, that set ignoreModifications to false.
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class ChainingCacheLoader implements CacheStore {
+   public void store(StoredEntry ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void storeAll(Collection ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void store(InputStream inputStream) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void clear() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public boolean remove(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public void purgeExpired() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void commit(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void rollback(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void prepare(List list, Transaction tx, boolean isOnePhase) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, TransactionManager tm, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public StoredEntry load(Object key) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll(Collection keys) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public boolean containsKey(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+      return null;
+   }
+
+   public void start() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void stop() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void addCacheLoader(CacheLoader loader, CacheLoaderConfig cfg) {
+      // TODO: Manik: Customise this generated block      
+   }
+
+   public void purgeIfNecessary() {
+      // TODO: Manik: Customise this generated block
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/ReadOnlyStore.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/ReadOnlyStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/ReadOnlyStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,106 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.Cache;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ */
+public class ReadOnlyStore implements CacheStore {
+
+   CacheStore delegate;
+
+   public ReadOnlyStore(CacheStore delegate) {
+      this.delegate = delegate;
+   }
+
+   public void store(StoredEntry ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void storeAll(Collection ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void store(InputStream inputStream) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void clear() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public boolean remove(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public void purgeExpired() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void commit(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void rollback(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void prepare(List list, Transaction tx, boolean isOnePhase) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, TransactionManager tm, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public StoredEntry load(Object key) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll(Collection keys) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public boolean containsKey(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public Class getConfigurationClass() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public void start() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void stop() {
+      // TODO: Manik: Customise this generated block
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStore.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStore.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStore.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,98 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.Cache;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ */
+public class SingletonStore extends AbstractDelegatingStore {
+   public SingletonStore(CacheStore tmpStore) {
+      setDelegate(tmpStore);
+   }
+
+   public void store(StoredEntry ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void storeAll(Collection ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void store(InputStream inputStream) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void clear() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public boolean remove(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public void purgeExpired() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void commit(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void rollback(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void prepare(List list, Transaction tx, boolean isOnePhase) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public StoredEntry load(Object key) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll(Collection keys) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public boolean containsKey(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+      return null;
+   }
+
+   public void start() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void stop() {
+      // TODO: Manik: Customise this generated block
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStoreConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStoreConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/decorators/SingletonStoreConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,55 @@
+package org.horizon.loader.decorators;
+
+import org.horizon.config.AbstractNamedCacheConfigurationBean;
+
+/**
+ * Configuration for a singleton store
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class SingletonStoreConfig extends AbstractNamedCacheConfigurationBean {
+
+   private static final long serialVersionUID = 824251894176131850L;
+
+   boolean singletonStoreEnabled;
+   boolean pushStateWhenCoordinator;
+   long pushStateTimeout = 10000;
+
+   public boolean isSingletonStoreEnabled() {
+      return singletonStoreEnabled;
+   }
+
+   public void setSingletonStoreEnabled(boolean singletonStoreEnabled) {
+      testImmutability("singletonStoreEnabled");
+      this.singletonStoreEnabled = singletonStoreEnabled;
+   }
+
+
+   public boolean isPushStateWhenCoordinator() {
+      return pushStateWhenCoordinator;
+   }
+
+   public void setPushStateWhenCoordinator(boolean pushStateWhenCoordinator) {
+      testImmutability("pushStateWhenCoordinator");
+      this.pushStateWhenCoordinator = pushStateWhenCoordinator;
+   }
+
+   public long getPushStateTimeout() {
+      return pushStateTimeout;
+   }
+
+   public void setPushStateTimeout(long pushStateTimeout) {
+      testImmutability("pushStateTimeout");
+      this.pushStateTimeout = pushStateTimeout;
+   }
+
+   @Override
+   public SingletonStoreConfig clone() {
+      try {
+         return (SingletonStoreConfig) super.clone();
+      } catch (CloneNotSupportedException e) {
+         throw new RuntimeException("Should not happen", e);
+      }
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoader.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoader.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,94 @@
+package org.horizon.loader.jdbc;
+
+import org.horizon.Cache;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.CacheStore;
+import org.horizon.loader.StoredEntry;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ */
+public class JDBCCacheLoader implements CacheStore {
+   public void store(StoredEntry ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void storeAll(Collection ed) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void store(InputStream inputStream) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void clear() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public boolean remove(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public void purgeExpired() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void commit(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void rollback(Transaction tx) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void prepare(List list, Transaction tx, boolean isOnePhase) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public StoredEntry load(Object key) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll(Collection keys) {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public Set loadAll() {
+      return null;  // TODO: Manik: Customise this generated block
+   }
+
+   public boolean containsKey(Object key) {
+      return false;  // TODO: Manik: Customise this generated block
+   }
+
+   public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+      return JDBCCacheLoaderConfig.class;
+   }
+
+   public void start() {
+      // TODO: Manik: Customise this generated block
+   }
+
+   public void stop() {
+      // TODO: Manik: Customise this generated block
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoaderConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoaderConfig.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/jdbc/JDBCCacheLoaderConfig.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,51 @@
+package org.horizon.loader.jdbc;
+
+import org.horizon.loader.AbstractCacheLoaderConfig;
+
+/**
+ * // TODO: Manik: Document this!
+ *
+ * @author Manik Surtani
+ */
+public class JDBCCacheLoaderConfig extends AbstractCacheLoaderConfig {
+   String dataSource;
+   String tableNamePrefix = "horizon";
+   boolean createTable = true;
+   boolean dropTable = false;
+
+   public JDBCCacheLoaderConfig() {
+      className = JDBCCacheLoader.class.getName();
+   }
+
+   public String getDataSource() {
+      return dataSource;
+   }
+
+   public void setDataSource(String dataSource) {
+      this.dataSource = dataSource;
+   }
+
+   public String getTableNamePrefix() {
+      return tableNamePrefix;
+   }
+
+   public void setTableNamePrefix(String tableNamePrefix) {
+      this.tableNamePrefix = tableNamePrefix;
+   }
+
+   public boolean isCreateTable() {
+      return createTable;
+   }
+
+   public void setCreateTable(boolean createTable) {
+      this.createTable = createTable;
+   }
+
+   public boolean isDropTable() {
+      return dropTable;
+   }
+
+   public void setDropTable(boolean dropTable) {
+      this.dropTable = dropTable;
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/modifications/Clear.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/modifications/Clear.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/modifications/Clear.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,20 @@
+package org.horizon.loader.modifications;
+
+/**
+ * Represents a {@link org.horizon.loader.CacheStore#clear()} modification
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class Clear implements Modification {
+   final Type type = Type.CLEAR;
+
+   public Type getType() {
+      return type;
+   }
+
+   @Override
+   public String toString() {
+      return "Clear";
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/modifications/Modification.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/modifications/Modification.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/modifications/Modification.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,15 @@
+package org.horizon.loader.modifications;
+
+/**
+ * An interface that defines a {@link org.horizon.loader.CacheStore} modification
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public interface Modification {
+   public static enum Type {
+      STORE, REMOVE, CLEAR
+   }
+
+   Type getType();
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/modifications/Remove.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/modifications/Remove.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/modifications/Remove.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,52 @@
+package org.horizon.loader.modifications;
+
+/**
+ * Represents a {@link org.horizon.loader.CacheStore#remove(Object)} modification
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class Remove<K> implements Modification {
+
+   final Type type = Type.REMOVE;
+   final K key;
+
+   public Remove(K key) {
+      this.key = key;
+   }
+
+   public Type getType() {
+      return type;
+   }
+
+   public K getKey() {
+      return key;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      Remove remove = (Remove) o;
+
+      if (key != null ? !key.equals(remove.key) : remove.key != null) return false;
+      if (type != remove.type) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = type != null ? type.hashCode() : 0;
+      result = 31 * result + (key != null ? key.hashCode() : 0);
+      return result;
+   }
+
+   @Override
+   public String toString() {
+      return "Remove{" +
+            "key=" + key +
+            '}';
+   }
+}

Added: core/branches/flat/src/main/java/org/horizon/loader/modifications/Store.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/loader/modifications/Store.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/horizon/loader/modifications/Store.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,54 @@
+package org.horizon.loader.modifications;
+
+import org.horizon.loader.StoredEntry;
+
+/**
+ * Modification representing {@link org.horizon.loader.CacheStore#store(org.horizon.loader.StoredEntry)}
+ *
+ * @author Manik Surtani
+ * @since 1.0
+ */
+public class Store<K, V> implements Modification {
+
+   final Type type = Type.STORE;
+   final StoredEntry<K, V> storedEntry;
+
+   public Store(StoredEntry<K, V> storedEntry) {
+      this.storedEntry = storedEntry;
+   }
+
+   public Type getType() {
+      return type;
+   }
+
+   public StoredEntry<K, V> getStoredEntry() {
+      return storedEntry;
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+
+      Store store = (Store) o;
+
+      if (storedEntry != null ? !storedEntry.equals(store.storedEntry) : store.storedEntry != null) return false;
+      if (type != store.type) return false;
+
+      return true;
+   }
+
+   @Override
+   public int hashCode() {
+      int result = type != null ? type.hashCode() : 0;
+      result = 31 * result + (storedEntry != null ? storedEntry.hashCode() : 0);
+      return result;
+   }
+
+   @Override
+   public String toString() {
+      return "Store{" +
+            "storedEntry=" + storedEntry +
+            '}';
+   }
+}

Modified: core/branches/flat/src/main/java/org/horizon/statetransfer/DefaultStateTransferManager.java
===================================================================
--- core/branches/flat/src/main/java/org/horizon/statetransfer/DefaultStateTransferManager.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/java/org/horizon/statetransfer/DefaultStateTransferManager.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -24,7 +24,7 @@
 import org.horizon.config.Configuration;
 import org.horizon.factories.annotations.Inject;
 import org.horizon.factories.annotations.Start;
-import org.horizon.loaderold.CacheLoaderManager;
+import org.horizon.loader.CacheLoaderManager;
 import org.horizon.logging.Log;
 import org.horizon.logging.LogFactory;
 import org.horizon.marshall.Marshaller;

Modified: core/branches/flat/src/main/resources/config-samples/all.xml
===================================================================
--- core/branches/flat/src/main/resources/config-samples/all.xml	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/resources/config-samples/all.xml	2009-02-11 09:52:13 UTC (rev 7679)
@@ -154,12 +154,7 @@
                horizon.jdbc.table.drop=false
             </properties>
 
-            <singletonStore enabled="true" class="org.horizon.loader.SingletonStoreCacheLoaderOld">
-               <properties>
-                  horizon.singletonStore.pushStateWhenCoordinator=true
-                  horizon.singletonStore.pushStateWhenCoordinatorTimeout=20000
-               </properties>
-            </singletonStore>
+            <singletonStore enabled="true" pushStateWhenCoordinator="true" pushStateTimeout="20000"/>
          </loader>
       </loaders>
 

Modified: core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd
===================================================================
--- core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/main/resources/schema/horizon-config-1.0.xsd	2009-02-11 09:52:13 UTC (rev 7679)
@@ -171,11 +171,9 @@
                   <xs:element name="properties"/>
                   <xs:element name="singletonStore" minOccurs="0" maxOccurs="1">
                      <xs:complexType>
-                        <xs:all>
-                           <xs:element name="properties" type="xs:string" minOccurs="0" maxOccurs="1"/>
-                        </xs:all>
                         <xs:attribute name="enabled" type="tns:booleanType"/>
-                        <xs:attribute name="class" type="xs:string"/>
+                        <xs:attribute name="pushStateWhenCoordinator" type="tns:booleanType"/>
+                        <xs:attribute name="pushStateTimeout" type="xs:positiveInteger"/>
                      </xs:complexType>
                   </xs:element>
                </xs:all>

Modified: core/branches/flat/src/test/java/org/horizon/api/tree/NodeMoveAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/api/tree/NodeMoveAPITest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/api/tree/NodeMoveAPITest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -3,7 +3,7 @@
 import org.horizon.Cache;
 import org.horizon.UnitTestCacheFactory;
 import org.horizon.api.mvcc.LockAssert;
-import org.horizon.config.CacheLoaderConfig;
+import org.horizon.config.CacheLoaderManagerConfig;
 import org.horizon.config.Configuration;
 import org.horizon.config.parsing.XmlConfigHelper;
 import org.horizon.config.parsing.element.LoadersElementParser;
@@ -532,7 +532,7 @@
       assertNoLocks();
    }
 
-   protected CacheLoaderConfig getSingleCacheLoaderConfig(boolean passivation, String preload, String cacheloaderClass, String properties, boolean async, boolean fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception {
+   protected CacheLoaderManagerConfig getSingleCacheLoaderConfig(boolean passivation, String preload, String cacheloaderClass, String properties, boolean async, boolean fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception {
       String xml =
             "      <loaders passivation=\"" + passivation + "\" shared=\"" + shared + "\">\n" +
                   "         <preload>\n" +

Modified: core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/config/parsing/ConfigurationParserTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,11 +1,14 @@
 package org.horizon.config.parsing;
 
-import org.horizon.config.CacheLoaderConfig;
+import org.horizon.config.CacheLoaderManagerConfig;
 import org.horizon.config.Configuration;
 import org.horizon.config.ConfigurationException;
 import org.horizon.config.EvictionConfig;
 import org.horizon.eviction.DefaultEvictionAction;
 import org.horizon.eviction.algorithms.fifo.FIFOAlgorithmConfig;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.decorators.SingletonStoreConfig;
+import org.horizon.loader.jdbc.JDBCCacheLoaderConfig;
 import org.horizon.lock.IsolationLevel;
 import org.horizon.transaction.GenericTransactionManagerLookup;
 import org.testng.annotations.Test;
@@ -141,20 +144,15 @@
    public void testCacheLoaders() throws Exception {
       XmlConfigurationParserImpl parser = new XmlConfigurationParserImpl();
       String xml = "<loaders passivation=\"true\" shared=\"true\" preload=\"true\">\n" +
-            "         <loader class=\"org.horizon.loader.JDBCCacheLoader\" async=\"true\" fetchPersistentState=\"true\"\n" +
+            "         <loader class=\"org.horizon.loader.jdbc.JDBCCacheLoader\" async=\"true\" fetchPersistentState=\"true\"\n" +
             "                 ignoreModifications=\"false\" purgeOnStartup=\"false\">\n" +
             "            <properties>\n" +
-            "               horizon.jdbc.datasource=HorizonDS\n" +
-            "               horizon.jdbc.table.name=horizon\n" +
-            "               horizon.jdbc.table.create=true\n" +
-            "               horizon.jdbc.table.drop=false\n" +
+            "               dataSource=HorizonDS\n" +
+            "               tableNamePrefix=horizon\n" +
+            "               createTable=true\n" +
+            "               dropTable=false\n" +
             "            </properties>\n" +
-            "            <singletonStore enabled=\"true\" class=\"com.blah.Blah\">\n" +
-            "               <properties>\n" +
-            "                  horizon.singletonStore.pushStateWhenCoordinator=true\n" +
-            "                  horizon.singletonStore.pushStateWhenCoordinatorTimeout=20000\n" +
-            "               </properties>\n" +
-            "            </singletonStore>\n" +
+            "            <singletonStore enabled=\"true\" pushStateWhenCoordinator=\"true\" pushStateTimeout=\"20000\" />\n" +
             "         </loader>\n" +
             "      </loaders>";
       Element e = XmlConfigHelper.stringToElement(xml);
@@ -162,32 +160,37 @@
       Configuration c = new Configuration();
       parser.configureCacheLoaders(e, c);
 
-      CacheLoaderConfig clc = c.getCacheLoaderConfig();
+      CacheLoaderManagerConfig clc = c.getCacheLoaderConfig();
       assert clc != null;
       assert clc.isFetchPersistentState();
       assert clc.isPassivation();
       assert clc.isShared();
       assert clc.isPreload();
 
-      CacheLoaderConfig.IndividualCacheLoaderConfig iclc = clc.getFirstCacheLoaderConfig();
-      assert iclc.getClassName().equals("org.horizon.loader.JDBCCacheLoader");
+      CacheLoaderConfig iclc = clc.getFirstCacheLoaderConfig();
+      assert iclc.getClassName().equals("org.horizon.loader.jdbc.JDBCCacheLoader");
       assert iclc.isAsync();
       assert iclc.isFetchPersistentState();
       assert !iclc.isIgnoreModifications();
       assert !iclc.isPurgeOnStartup();
 
-      CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = iclc.getSingletonStoreConfig();
+      JDBCCacheLoaderConfig jdbcclc = (JDBCCacheLoaderConfig) iclc;
+      assert jdbcclc.getDataSource().equals("HorizonDS");
+      assert jdbcclc.getTableNamePrefix().equals("horizon");
+      assert jdbcclc.isCreateTable();
+      assert !jdbcclc.isDropTable();
+
+      SingletonStoreConfig ssc = iclc.getSingletonStoreConfig();
       assert ssc.isSingletonStoreEnabled();
-      assert ssc.getClassName().equals("com.blah.Blah");
-      assert ssc.getSingletonStoreProperties().size() == 2;
+      assert ssc.isPushStateWhenCoordinator();
+      assert ssc.getPushStateTimeout() == 20000;
    }
 
    public void testCacheLoadersDefaults() throws Exception {
       XmlConfigurationParserImpl parser = new XmlConfigurationParserImpl();
       String xml = "<loaders>\n" +
-            "         <loader class=\"org.horizon.loader.JDBCCacheLoader\">\n" +
+            "         <loader class=\"org.horizon.loader.jdbc.JDBCCacheLoader\">\n" +
             "            <properties />\n" +
-            "            <singletonStore enabled=\"true\" />\n" +
             "         </loader>\n" +
             "      </loaders>";
       Element e = XmlConfigHelper.stringToElement(xml);
@@ -195,24 +198,22 @@
       Configuration c = new Configuration();
       parser.configureCacheLoaders(e, c);
 
-      CacheLoaderConfig clc = c.getCacheLoaderConfig();
+      CacheLoaderManagerConfig clc = c.getCacheLoaderConfig();
       assert clc != null;
       assert !clc.isFetchPersistentState();
       assert !clc.isPassivation();
       assert !clc.isShared();
       assert !clc.isPreload();
 
-      CacheLoaderConfig.IndividualCacheLoaderConfig iclc = clc.getFirstCacheLoaderConfig();
-      assert iclc.getClassName().equals("org.horizon.loader.JDBCCacheLoader");
+      CacheLoaderConfig iclc = clc.getFirstCacheLoaderConfig();
+      assert iclc.getClassName().equals("org.horizon.loader.jdbc.JDBCCacheLoader");
       assert !iclc.isAsync();
       assert !iclc.isFetchPersistentState();
       assert !iclc.isIgnoreModifications();
       assert !iclc.isPurgeOnStartup();
 
-      CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig ssc = iclc.getSingletonStoreConfig();
-      assert ssc.isSingletonStoreEnabled();
-      assert ssc.getClassName().equals("org.horizon.loader.SingletonStoreCacheLoaderOld");
-      assert ssc.getSingletonStoreProperties().isEmpty();
+      SingletonStoreConfig ssc = iclc.getSingletonStoreConfig();
+      assert !ssc.isSingletonStoreEnabled();
    }
 
    public void testInsufficientEviction() throws Exception {

Modified: core/branches/flat/src/test/java/org/horizon/eviction/EvictionFunctionalTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/EvictionFunctionalTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/eviction/EvictionFunctionalTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -2,7 +2,6 @@
 
 import org.horizon.Cache;
 import org.horizon.config.Configuration;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.config.EvictionConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.algorithms.fifo.FIFOAlgorithmConfig;

Modified: core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/eviction/algorithms/BaseAlgorithmTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -2,11 +2,10 @@
 
 import org.easymock.EasyMock;
 import static org.easymock.EasyMock.*;
-import org.horizon.config.EvictionAlgorithmConfig;
 import org.horizon.container.DataContainer;
 import org.horizon.eviction.EvictionAction;
 import org.horizon.eviction.EvictionAlgorithm;
-import org.horizon.eviction.EvictionAlgorithmConfigBase;
+import org.horizon.eviction.EvictionAlgorithmConfig;
 import org.horizon.eviction.events.EvictionEvent;
 import static org.horizon.eviction.events.EvictionEvent.Type.*;
 import org.horizon.eviction.events.InUseEvictionEvent;
@@ -20,7 +19,7 @@
 @Test(groups = "unit")
 public abstract class BaseAlgorithmTest {
 
-   protected abstract EvictionAlgorithmConfigBase getNewEvictionAlgorithmConfig();
+   protected abstract BaseEvictionAlgorithmConfig getNewEvictionAlgorithmConfig();
 
    protected BaseEvictionAlgorithm createAndInit(EvictionAlgorithmConfig cfg) throws Exception {
       DataContainer dc = createNiceMock(DataContainer.class);
@@ -37,7 +36,7 @@
    }
 
    public void testMinTimeToLive() throws Exception {
-      EvictionAlgorithmConfigBase cfg = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig cfg = getNewEvictionAlgorithmConfig();
       cfg.setMinTimeToLive(2 * 60 * 60 * 1000); // something enormous - 2 hrs
       cfg.setMaxEntries(5);
       DataContainer dc = createMock(DataContainer.class);
@@ -97,7 +96,7 @@
    }
 
    public void testNumEntries1() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(4);
       config.setMinEntries(2);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
@@ -131,7 +130,7 @@
    }
 
    public void testNumEntries2() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(0);
       config.setMinEntries(20);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
@@ -150,7 +149,7 @@
    }
 
    public void testNumEntries3() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(3);
       config.setMinEntries(20);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
@@ -179,7 +178,7 @@
    }
 
    public void testNumEntries4() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(-1);
       config.setMinEntries(2);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
@@ -198,7 +197,7 @@
    }
 
    public void testNumEntries5() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(3);
       config.setMinEntries(-1);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
@@ -226,7 +225,7 @@
    }
 
    public void testRemoveEvent() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMinTimeToLive(24 * 60 * 60, TimeUnit.SECONDS);  // huge - so evictions wont happen
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
       eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
@@ -251,7 +250,7 @@
    }
 
    public void testClearEvent() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMinTimeToLive(24 * 60 * 60, TimeUnit.SECONDS);  // huge - so evictions wont happen
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
       eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
@@ -276,7 +275,7 @@
    }
 
    public void testMarkInUseControl() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(1);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
       eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));
@@ -304,7 +303,7 @@
    }
 
    public void testMarkInUse() throws Exception {
-      EvictionAlgorithmConfigBase config = getNewEvictionAlgorithmConfig();
+      BaseEvictionAlgorithmConfig config = getNewEvictionAlgorithmConfig();
       config.setMaxEntries(1);
       BlockingQueue<EvictionEvent> eventQueue = new LinkedBlockingQueue<EvictionEvent>();
       eventQueue.put(new EvictionEvent("one", ADD_ENTRY_EVENT));

Added: core/branches/flat/src/test/java/org/horizon/loader/BaseCacheLoaderTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/loader/BaseCacheLoaderTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/loader/BaseCacheLoaderTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,241 @@
+package org.horizon.loader;
+
+import org.easymock.EasyMock;
+import org.horizon.loader.modifications.Clear;
+import org.horizon.loader.modifications.Modification;
+import org.horizon.loader.modifications.Remove;
+import org.horizon.loader.modifications.Store;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+ at Test(groups = "unit", sequential = true)
+ at SuppressWarnings("unchecked")
+public abstract class BaseCacheLoaderTest {
+
+   protected abstract CacheStore createCacheStore();
+
+   CacheStore cs;
+
+   @BeforeTest
+   public void setUp() {
+      cs = createCacheStore();
+   }
+
+   @AfterTest
+   public void tearDown() {
+      if (cs != null) cs.clear();
+      cs = null;
+   }
+
+   @AfterMethod
+   public void cleanCL() {
+      cs.clear();
+   }
+
+   public void testLoadAndStore() throws InterruptedException {
+      assert !cs.containsKey("k");
+      StoredEntry se = new StoredEntry("k", "v", -1, -1);
+      cs.store(se);
+
+      assert cs.load("k").getValue().equals("v");
+      assert cs.load("k").getLifespan() == -1;
+      assert !cs.load("k").isExpired();
+      assert cs.containsKey("k");
+
+      long now = System.currentTimeMillis();
+      long lifespan = 120000;
+      se = new StoredEntry("k", "v", now, now + lifespan);
+      cs.store(se);
+
+      assert cs.load("k").getValue().equals("v");
+      assert cs.load("k").getLifespan() == lifespan;
+      assert !cs.load("k").isExpired();
+      assert cs.containsKey("k");
+
+      now = System.currentTimeMillis();
+      lifespan = 1;
+      se = new StoredEntry("k", "v", now, now + lifespan);
+      cs.store(se);
+      Thread.sleep(2);
+      assert se.isExpired();
+      assert cs.load("k") == null;
+      assert !cs.containsKey("k");
+   }
+
+   public void testOnePhaseCommit() {
+      List<Modification> mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Remove("k1"));
+      Transaction tx = EasyMock.createNiceMock(Transaction.class);
+      cs.prepare(mods, tx, true);
+
+      assert cs.load("k2").getValue().equals("v2");
+      assert !cs.containsKey("k1");
+
+      cs.clear();
+
+      mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Clear());
+      mods.add(new Store(new StoredEntry("k3", "v3", -1, -1)));
+
+      cs.prepare(mods, tx, true);
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert cs.containsKey("k3");
+   }
+
+   public void testTwoPhaseCommit() {
+      List<Modification> mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Remove("k1"));
+      Transaction tx = EasyMock.createNiceMock(Transaction.class);
+      cs.prepare(mods, tx, false);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+
+      cs.commit(tx);
+
+      assert cs.load("k2").getValue().equals("v2");
+      assert !cs.containsKey("k1");
+
+      cs.clear();
+
+      mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Clear());
+      mods.add(new Store(new StoredEntry("k3", "v3", -1, -1)));
+
+      cs.prepare(mods, tx, false);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert !cs.containsKey("k3");
+
+      cs.commit(tx);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert cs.containsKey("k3");
+   }
+
+   public void testRollback() {
+
+      cs.store(new StoredEntry("old", "old", -1, -1));
+
+      List<Modification> mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Remove("k1"));
+      mods.add(new Remove("old"));
+      Transaction tx = EasyMock.createNiceMock(Transaction.class);
+      cs.prepare(mods, tx, false);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert cs.containsKey("old");
+
+      cs.rollback(tx);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert cs.containsKey("old");
+
+      mods = new ArrayList<Modification>();
+      mods.add(new Store(new StoredEntry("k1", "v1", -1, -1)));
+      mods.add(new Store(new StoredEntry("k2", "v2", -1, -1)));
+      mods.add(new Clear());
+      mods.add(new Store(new StoredEntry("k3", "v3", -1, -1)));
+
+      cs.prepare(mods, tx, false);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert !cs.containsKey("k3");
+
+      cs.rollback(tx);
+
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert !cs.containsKey("k3");
+      assert cs.containsKey("old");
+   }
+
+   public void testCommitAndRollbackWithoutPrepare() {
+      cs.store(new StoredEntry("old", "old", -1, -1));
+      Transaction tx = EasyMock.createNiceMock(Transaction.class);
+      cs.commit(tx);
+      cs.store(new StoredEntry("old", "old", -1, -1));
+      cs.rollback(tx);
+
+      assert cs.containsKey("old");
+   }
+
+   public void testPreload() {
+      cs.store(new StoredEntry("k1", "v1", -1, -1));
+      cs.store(new StoredEntry("k2", "v2", -1, -1));
+      cs.store(new StoredEntry("k3", "v3", -1, -1));
+
+      Set<StoredEntry> set = cs.loadAll();
+
+      assert set.size() == 3;
+      Set expected = new HashSet();
+      expected.add("k1");
+      expected.add("k2");
+      expected.add("k3");
+      for (StoredEntry se : set) assert expected.remove(se.getKey());
+      assert expected.isEmpty();
+   }
+
+   public void testPurgeExpired() throws InterruptedException {
+      long now = System.currentTimeMillis();
+      long lifespan = 1000;
+      cs.store(new StoredEntry("k1", "v1", now, now + lifespan));
+      cs.store(new StoredEntry("k2", "v2", now, now + lifespan));
+      cs.store(new StoredEntry("k3", "v3", now, now + lifespan));
+      Thread.sleep(lifespan + 100);
+      cs.purgeExpired();
+      assert !cs.containsKey("k1");
+      assert !cs.containsKey("k2");
+      assert !cs.containsKey("k3");
+   }
+
+   public void testStreamingAPI() throws IOException, ClassNotFoundException {
+      cs.store(new StoredEntry("k1", "v1", -1, -1));
+      cs.store(new StoredEntry("k2", "v2", -1, -1));
+      cs.store(new StoredEntry("k3", "v3", -1, -1));
+
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      cs.load(out);
+      out.flush();
+      out.close();
+      cs.clear();
+      cs.store(new ByteArrayInputStream(out.toByteArray()));
+
+      Set<StoredEntry> set = cs.loadAll();
+
+      assert set.size() == 3;
+      Set expected = new HashSet();
+      expected.add("k1");
+      expected.add("k2");
+      expected.add("k3");
+      for (StoredEntry se : set) assert expected.remove(se.getKey());
+      assert expected.isEmpty();
+   }
+}

Added: core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoader.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoader.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoader.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,156 @@
+package org.horizon.loader.dummy;
+
+import org.horizon.Cache;
+import org.horizon.loader.AbstractCacheLoaderConfig;
+import org.horizon.loader.AbstractCacheStore;
+import org.horizon.loader.CacheLoaderConfig;
+import org.horizon.loader.StoredEntry;
+import org.horizon.loader.modifications.Modification;
+import org.horizon.marshall.Marshaller;
+
+import javax.transaction.Transaction;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class DummyInMemoryCacheLoader<K, V> extends AbstractCacheStore<K, V> {
+
+   static final ConcurrentMap<String, Map> stores = new ConcurrentHashMap<String, Map>();
+   String storeName = "__DEFAULT_STORES__";
+   Map<K, StoredEntry<K, V>> store;
+   Cfg config;
+   ConcurrentMap<Transaction, List<Modification>> txs = new ConcurrentHashMap<Transaction, List<Modification>>();
+
+
+   public void store(StoredEntry<K, V> ed) {
+      store.put(ed.getKey(), ed);
+   }
+
+   @SuppressWarnings("unchecked")
+   public void store(InputStream inputStream) throws IOException, ClassNotFoundException {
+      ObjectInputStream ois = inputStream instanceof ObjectInputStream ? (ObjectInputStream) inputStream :
+            new ObjectInputStream(inputStream);
+      int numEntries = ois.readInt();
+      store.clear();
+      for (int i = 0; i < numEntries; i++) {
+         StoredEntry<K, V> e = (StoredEntry<K, V>) ois.readObject();
+         store.put(e.getKey(), e);
+      }
+   }
+
+   public void load(OutputStream outputStream) throws IOException {
+      ObjectOutputStream oos = outputStream instanceof ObjectOutputStream ? (ObjectOutputStream) outputStream :
+            new ObjectOutputStream(outputStream);
+      oos.writeInt(store.size());
+      for (StoredEntry<K, V> se : store.values()) oos.writeObject(se);
+   }
+
+   public void clear() {
+      store.clear();
+   }
+
+   public boolean remove(K key) {
+      return store.remove(key) != null;
+   }
+
+   public void purgeExpired() {
+      for (Iterator<StoredEntry<K, V>> i = store.values().iterator(); i.hasNext();) {
+         StoredEntry<K, V> se = i.next();
+         if (se.isExpired()) i.remove();
+      }
+   }
+
+   public void commit(Transaction tx) {
+      List<Modification> mods = txs.remove(tx);
+      if (mods != null) applyModifications(mods);
+   }
+
+   public void rollback(Transaction tx) {
+      txs.remove(tx);
+   }
+
+   public void prepare(List<Modification> list, Transaction tx, boolean isOnePhase) {
+      if (isOnePhase)
+         applyModifications(list);
+      else
+         txs.put(tx, list);
+   }
+
+   public void init(CacheLoaderConfig config, Cache cache, Marshaller m) {
+      this.config = (Cfg) config;
+   }
+
+   public StoredEntry<K, V> load(K key) {
+      if (key == null) return null;
+      StoredEntry<K, V> se = store.get(key);
+      if (se == null) return null;
+      if (se.isExpired()) {
+         store.remove(key);
+         return null;
+      }
+
+      return se;
+   }
+
+   public Set<StoredEntry<K, V>> loadAll() {
+      Set<StoredEntry<K, V>> s = new HashSet<StoredEntry<K, V>>();
+      for (Iterator<StoredEntry<K, V>> i = store.values().iterator(); i.hasNext();) {
+         StoredEntry<K, V> se = i.next();
+         if (se.isExpired())
+            i.remove();
+         else
+            s.add(se);
+      }
+      return s;
+   }
+
+   public boolean containsKey(K key) {
+      return load(key) != null;
+   }
+
+   public Class<? extends CacheLoaderConfig> getConfigurationClass() {
+      return Cfg.class;
+   }
+
+   @SuppressWarnings("unchecked")
+   public void start() {
+      storeName = config.getStore();
+      Map m = new ConcurrentHashMap();
+      Map existing = stores.putIfAbsent(storeName, m);
+      store = existing == null ? m : existing;
+   }
+
+   public void stop() {
+      stores.remove(storeName);
+   }
+
+   public static class Cfg extends AbstractCacheLoaderConfig {
+      boolean debug;
+      String store;
+
+      public boolean isDebug() {
+         return debug;
+      }
+
+      public void setDebug(boolean debug) {
+         this.debug = debug;
+      }
+
+      public String getStore() {
+         return store;
+      }
+
+      public void setStore(String store) {
+         this.store = store;
+      }
+   }
+}

Added: core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoaderTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoaderTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/horizon/loader/dummy/DummyInMemoryCacheLoaderTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -0,0 +1,18 @@
+package org.horizon.loader.dummy;
+
+import org.horizon.loader.BaseCacheLoaderTest;
+import org.horizon.loader.CacheStore;
+import org.testng.annotations.Test;
+
+ at Test(groups = "unit", sequential = true)
+public class DummyInMemoryCacheLoaderTest extends BaseCacheLoaderTest {
+
+   protected CacheStore createCacheStore() {
+      DummyInMemoryCacheLoader cl = new DummyInMemoryCacheLoader();
+      DummyInMemoryCacheLoader.Cfg cfg = new DummyInMemoryCacheLoader.Cfg();
+      cfg.setStore(DummyInMemoryCacheLoaderTest.class.getName());
+      cl.init(cfg, null, null);
+      cl.start();
+      return cl;
+   }
+}

Modified: core/branches/flat/src/test/java/org/horizon/manager/CacheManagerComponentRegistryTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/manager/CacheManagerComponentRegistryTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/manager/CacheManagerComponentRegistryTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -1,13 +1,13 @@
 package org.horizon.manager;
 
 import org.horizon.Cache;
-import org.horizon.config.CacheLoaderConfig;
 import org.horizon.config.Configuration;
+import org.horizon.config.EvictionConfig;
 import org.horizon.config.GlobalConfiguration;
+import org.horizon.eviction.EvictionManager;
+import org.horizon.eviction.algorithms.fifo.FIFOAlgorithmConfig;
 import org.horizon.interceptors.BatchingInterceptor;
 import org.horizon.interceptors.InterceptorChain;
-import org.horizon.loaderold.CacheLoaderManager;
-import org.horizon.loaderold.FileCacheLoaderConfig;
 import org.horizon.remoting.RPCManager;
 import org.horizon.transaction.DummyTransactionManager;
 import org.horizon.transaction.DummyTransactionManagerLookup;
@@ -57,15 +57,12 @@
    }
 
    public void testForceUnsharedComponents() throws NamedCacheNotFoundException {
-      CacheLoaderConfig clc = new CacheLoaderConfig();
-      // TODO change this to use a dummy in memory cache loaderold instead!!
-      FileCacheLoaderConfig fc = new FileCacheLoaderConfig();
-      fc.setLocation("/tmp");
-      clc.addIndividualCacheLoaderConfig(fc);
+      EvictionConfig ec = new EvictionConfig();
+      ec.setAlgorithmConfig(new FIFOAlgorithmConfig());
 
       Configuration defaultCfg = new Configuration();
       defaultCfg.setCacheMode(Configuration.CacheMode.REPL_SYNC);
-      defaultCfg.setCacheLoaderConfig(clc);
+      defaultCfg.setEvictionConfig(ec);
       // cache manager with default configuration
       cm = new DefaultCacheManager(GlobalConfiguration.getClusteredDefault(), defaultCfg);
 
@@ -78,9 +75,9 @@
       Cache transactional = cm.getCache("transactional");
 
       // assert components.
-      assert TestingUtil.extractComponent(c, CacheLoaderManager.class) != null;
-      assert TestingUtil.extractComponent(transactional, CacheLoaderManager.class) != null;
-      assert TestingUtil.extractComponent(c, CacheLoaderManager.class) != TestingUtil.extractComponent(transactional, CacheLoaderManager.class);
+      assert TestingUtil.extractComponent(c, EvictionManager.class) != null;
+      assert TestingUtil.extractComponent(transactional, EvictionManager.class) != null;
+      assert TestingUtil.extractComponent(c, EvictionManager.class) != TestingUtil.extractComponent(transactional, EvictionManager.class);
    }
 
    public void testOverridingComponents() throws NamedCacheNotFoundException {

Modified: core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerCacheLoaderTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerCacheLoaderTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerCacheLoaderTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -17,7 +17,7 @@
 //      c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
 //      c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
 //
-//      CacheLoaderConfig clc = new CacheLoaderConfig();
+//      CacheLoaderManagerConfig clc = new CacheLoaderManagerConfig();
 //      IndividualCacheLoaderConfig iclc = new IndividualCacheLoaderConfig();
 //      iclc.setClassName(DummyInMemoryCacheLoader.class.getName());
 //      clc.addIndividualCacheLoaderConfig(iclc);

Modified: core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerPassivationTest.java
===================================================================
--- core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerPassivationTest.java	2009-02-11 06:00:34 UTC (rev 7678)
+++ core/branches/flat/src/test/java/org/horizon/notifications/CacheListenerPassivationTest.java	2009-02-11 09:52:13 UTC (rev 7679)
@@ -17,7 +17,7 @@
 //      c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
 //      c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
 //
-//      CacheLoaderConfig clc = new CacheLoaderConfig();
+//      CacheLoaderManagerConfig clc = new CacheLoaderManagerConfig();
 //      IndividualCacheLoaderConfig iclc = new IndividualCacheLoaderConfig();
 //      iclc.setClassName(DummyInMemoryCacheLoader.class.getName());
 //      clc.addIndividualCacheLoaderConfig(iclc);




More information about the jbosscache-commits mailing list