[infinispan-commits] Infinispan SVN: r522 - in trunk/core/src: main/java/org/infinispan/config/parsing and 3 other directories.

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Wed Jul 8 09:08:14 EDT 2009


Author: vblagojevic at jboss.com
Date: 2009-07-08 09:08:14 -0400 (Wed, 08 Jul 2009)
New Revision: 522

Added:
   trunk/core/src/main/java/org/infinispan/config/parsing/AutomatedXmlConfigurationParserImpl.java
   trunk/core/src/main/java/org/infinispan/config/parsing/CacheLoaderManagerConfigReader.java
   trunk/core/src/main/java/org/infinispan/config/parsing/ClusteringConfigReader.java
   trunk/core/src/main/java/org/infinispan/config/parsing/ConfigurationElementReader.java
   trunk/core/src/main/java/org/infinispan/util/ClassFinder.java
   trunk/core/src/test/java/org/infinispan/config/parsing/AutomatedXmlFileParsingTest.java
Modified:
   trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java
   trunk/core/src/main/java/org/infinispan/config/Configuration.java
   trunk/core/src/main/java/org/infinispan/config/ConfigurationElement.java
   trunk/core/src/main/java/org/infinispan/config/GlobalConfiguration.java
   trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java
Log:
[ISPN-96] - Parse configuration XML files 

Modified: trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java	2009-07-08 09:03:28 UTC (rev 521)
+++ trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -21,6 +21,7 @@
  */
 package org.infinispan.config;
 
+import org.infinispan.config.parsing.CacheLoaderManagerConfigReader;
 import org.infinispan.loaders.CacheLoaderConfig;
 import org.infinispan.loaders.CacheStoreConfig;
 import org.infinispan.util.Util;
@@ -37,6 +38,7 @@
  * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @since 4.0
  */
+ at ConfigurationElement(name="loaders",parent="default",customReader=CacheLoaderManagerConfigReader.class)
 public class CacheLoaderManagerConfig extends AbstractNamedCacheConfigurationBean {
    private static final long serialVersionUID = 2210349340378984424L;
 
@@ -46,11 +48,17 @@
 
    private boolean shared;
 
+
+   @ConfigurationAttribute(name = "preload", 
+            containingElement = "loaders")
    public void setPreload(boolean preload) {
       testImmutability("preload");
       this.preload = preload;
    }
 
+
+   @ConfigurationAttribute(name = "passivation", 
+            containingElement = "loaders")
    public void setPassivation(boolean passivation) {
       testImmutability("passivation");
       this.passivation = passivation;
@@ -85,9 +93,15 @@
 
    @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();
+      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();
    }
 
+
+   @ConfigurationAttribute(name = "shared", 
+            containingElement = "loaders")
    public void setShared(boolean shared) {
       testImmutability("shared");
       this.shared = shared;

Modified: trunk/core/src/main/java/org/infinispan/config/Configuration.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/Configuration.java	2009-07-08 09:03:28 UTC (rev 521)
+++ trunk/core/src/main/java/org/infinispan/config/Configuration.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -21,6 +21,7 @@
  */
 package org.infinispan.config;
 
+import org.infinispan.config.parsing.ClusteringConfigReader;
 import org.infinispan.distribution.DefaultConsistentHash;
 import org.infinispan.eviction.EvictionStrategy;
 import org.infinispan.factories.annotations.Inject;
@@ -40,6 +41,20 @@
  * @since 4.0
  */
 @NonVolatile
+ at ConfigurationElements(elements = {
+         @ConfigurationElement(name = "default", parent = "infinispan", description = ""),
+         @ConfigurationElement(name = "namedCache", parent = "infinispan", description = ""),
+         @ConfigurationElement(name = "locking", parent = "default", description = ""),
+         @ConfigurationElement(name = "transaction", parent = "default", description = ""), 
+         @ConfigurationElement(name = "jmxStatistics", parent = "default", description = ""),
+         @ConfigurationElement(name = "lazyDeserialization", parent = "default", description = ""),  
+         @ConfigurationElement(name = "invocationBatching", parent = "default", description = ""),   
+         @ConfigurationElement(name = "clustering", parent = "default", description = "", customReader=ClusteringConfigReader.class),
+         @ConfigurationElement(name = "hash", parent = "default", description = ""),
+         @ConfigurationElement(name = "eviction", parent = "default", description = ""),
+         @ConfigurationElement(name = "expiration", parent = "default", description = ""),
+         @ConfigurationElement(name = "customInterceptors", parent = "default", description = "")         
+})
 public class Configuration extends AbstractNamedCacheConfigurationBean {
    private static final long serialVersionUID = 5553791890144997466L;
 
@@ -79,6 +94,8 @@
       this.unsafeUnreliableReturnValues = unsafeUnreliableReturnValues;
    }
 
+   @ConfigurationAttribute(name = "rehashRpcTimeout", 
+            containingElement = "hash")    
    public void setRehashRpcTimeout(long rehashRpcTimeout) {
       testImmutability("rehashRpcTimeout");
       this.rehashRpcTimeout = rehashRpcTimeout;
@@ -255,6 +272,9 @@
       return writeSkewCheck;
    }
 
+
+   @ConfigurationAttribute(name = "writeSkewCheck", 
+            containingElement = "locking")    
    public void setWriteSkewCheck(boolean writeSkewCheck) {
       testImmutability("writeSkewCheck");
       this.writeSkewCheck = writeSkewCheck;
@@ -264,16 +284,23 @@
       return concurrencyLevel;
    }
 
+
+   @ConfigurationAttribute(name = "concurrencyLevel", 
+            containingElement = "locking")    
    public void setConcurrencyLevel(int concurrencyLevel) {
       testImmutability("concurrencyLevel");
       this.concurrencyLevel = concurrencyLevel;
    }
 
+   @ConfigurationAttribute(name = "replQueueMaxElements", 
+            containingElement = "async")
    public void setReplQueueMaxElements(int replQueueMaxElements) {
       testImmutability("replQueueMaxElements");
       this.replQueueMaxElements = replQueueMaxElements;
    }
 
+   @ConfigurationAttribute(name = "replQueueInterval", 
+            containingElement = "async")
    public void setReplQueueInterval(long replQueueInterval) {
       testImmutability("replQueueInterval");
       this.replQueueInterval = replQueueInterval;
@@ -283,7 +310,8 @@
       setReplQueueInterval(timeUnit.toMillis(replQueueInterval));
    }
 
-
+   @ConfigurationAttribute(name = "enabled", 
+            containingElement = "jmxStatistics")   
    public void setExposeJmxStatistics(boolean useMbean) {
       testImmutability("exposeJmxStatistics");
       this.exposeJmxStatistics = useMbean;
@@ -297,16 +325,23 @@
     * @param enabled if true, batching is enabled.
     * @since 4.0
     */
+   
+   @ConfigurationAttribute(name = "enabled", 
+            containingElement = "invocationBatching") 
    public void setInvocationBatchingEnabled(boolean enabled) {
       testImmutability("invocationBatchingEnabled");
       this.invocationBatchingEnabled = enabled;
    }
 
+   @ConfigurationAttribute(name = "fetchInMemoryState", 
+            containingElement = "stateRetrieval")
    public void setFetchInMemoryState(boolean fetchInMemoryState) {
       testImmutability("fetchInMemoryState");
       this.fetchInMemoryState = fetchInMemoryState;
    }
 
+   @ConfigurationAttribute(name = "lockAcquisitionTimeout", 
+            containingElement = "locking")    
    public void setLockAcquisitionTimeout(long lockAcquisitionTimeout) {
       testImmutability("lockAcquisitionTimeout");
       this.lockAcquisitionTimeout = lockAcquisitionTimeout;
@@ -316,6 +351,8 @@
       setLockAcquisitionTimeout(timeUnit.toMillis(lockAcquisitionTimeout));
    }
 
+   @ConfigurationAttribute(name = "replTimeout", 
+            containingElement = "sync")    
    public void setSyncReplTimeout(long syncReplTimeout) {
       testImmutability("syncReplTimeout");
       this.syncReplTimeout = syncReplTimeout;
@@ -330,6 +367,8 @@
       this.cacheMode = cacheModeInt;
    }
 
+   @ConfigurationAttribute(name = "mode", 
+            containingElement = "clustering")
    public void setCacheMode(String cacheMode) {
       testImmutability("cacheMode");
       if (cacheMode == null) throw new ConfigurationException("Cache mode cannot be null", "CacheMode");
@@ -352,6 +391,8 @@
       return evictionWakeUpInterval;
    }
 
+   @ConfigurationAttribute(name = "wakeUpInterval", 
+            containingElement = "eviction")
    public void setEvictionWakeUpInterval(long evictionWakeUpInterval) {
       testImmutability("evictionWakeUpInterval");
       this.evictionWakeUpInterval = evictionWakeUpInterval;
@@ -365,11 +406,24 @@
       testImmutability("evictionStrategy");
       this.evictionStrategy = evictionStrategy;
    }
+   
+   @ConfigurationAttribute(name = "strategy", 
+            containingElement = "eviction")
+   public void setEvictionStrategy(String eStrategy){
+      testImmutability("evictionStrategy");
+      this.evictionStrategy = EvictionStrategy.valueOf(uc(eStrategy));
+      if (this.evictionStrategy == null) {
+         log.warn("Unknown evictionStrategy  '" + eStrategy + "', using defaults.");
+         this.evictionStrategy = EvictionStrategy.NONE;
+      }
+   }
 
    public int getEvictionMaxEntries() {
       return evictionMaxEntries;
    }
 
+   @ConfigurationAttribute(name = "maxEntries", 
+            containingElement = "eviction")
    public void setEvictionMaxEntries(int evictionMaxEntries) {
       testImmutability("evictionMaxEntries");
       this.evictionMaxEntries = evictionMaxEntries;
@@ -379,6 +433,8 @@
       return expirationLifespan;
    }
 
+   @ConfigurationAttribute(name = "lifespan", 
+            containingElement = "expiration")
    public void setExpirationLifespan(long expirationLifespan) {
       testImmutability("expirationLifespan");
       this.expirationLifespan = expirationLifespan;
@@ -388,11 +444,16 @@
       return expirationMaxIdle;
    }
 
+   @ConfigurationAttribute(name = "maxIdle", 
+            containingElement = "expiration")
    public void setExpirationMaxIdle(long expirationMaxIdle) {
       testImmutability("expirationMaxIdle");
       this.expirationMaxIdle = expirationMaxIdle;
    }
 
+   @ConfigurationAttribute(name = "transactionManagerLookupClass", 
+            containingElement = "transaction", 
+            description = "")
    public void setTransactionManagerLookupClass(String transactionManagerLookupClass) {
       testImmutability("transactionManagerLookupClass");
       this.transactionManagerLookupClass = transactionManagerLookupClass;
@@ -403,21 +464,29 @@
       this.cacheLoaderManagerConfig = cacheLoaderManagerConfig;
    }
 
+   @ConfigurationAttribute(name = "syncCommitPhase", 
+            containingElement = "transaction")
    public void setSyncCommitPhase(boolean syncCommitPhase) {
       testImmutability("syncCommitPhase");
       this.syncCommitPhase = syncCommitPhase;
    }
 
+   @ConfigurationAttribute(name = "syncRollbackPhase", 
+            containingElement = "transaction")
    public void setSyncRollbackPhase(boolean syncRollbackPhase) {
       testImmutability("syncRollbackPhase");
       this.syncRollbackPhase = syncRollbackPhase;
    }
    
+   @ConfigurationAttribute(name = "useEagerLocking", 
+            containingElement = "transaction")           
    public void setUseEagerLocking(boolean useEagerLocking) {
       testImmutability("useEagerLocking");
       this.useEagerLocking = useEagerLocking;
    }
 
+   @ConfigurationAttribute(name = "useReplQueue", 
+            containingElement = "async")
    public void setUseReplQueue(boolean useReplQueue) {
       testImmutability("useReplQueue");
       this.useReplQueue = useReplQueue;
@@ -428,6 +497,8 @@
       this.isolationLevel = isolationLevel;
    }
 
+   @ConfigurationAttribute(name = "timeout", 
+            containingElement = "stateRetrieval")
    public void setStateRetrievalTimeout(long stateRetrievalTimeout) {
       testImmutability("stateRetrievalTimeout");
       this.stateRetrievalTimeout = stateRetrievalTimeout;
@@ -437,6 +508,8 @@
       setStateRetrievalTimeout(timeUnit.toMillis(stateRetrievalTimeout));
    }
 
+   @ConfigurationAttribute(name = "isolationLevel", 
+            containingElement = "locking")    
    public void setIsolationLevel(String isolationLevel) {
       testImmutability("isolationLevel");
       if (isolationLevel == null) throw new ConfigurationException("Isolation level cannot be null", "IsolationLevel");
@@ -447,41 +520,58 @@
       }
    }
 
+   @ConfigurationAttribute(name = "enabled", 
+            containingElement = "lazyDeserialization") 
    public void setUseLazyDeserialization(boolean useLazyDeserialization) {
       testImmutability("useLazyDeserialization");
       this.useLazyDeserialization = useLazyDeserialization;
    }
 
+   @ConfigurationAttribute(name = "enabled", 
+            containingElement = "l1")   
    public void setL1CacheEnabled(boolean l1CacheEnabled) {
       testImmutability("l1CacheEnabled");
       this.l1CacheEnabled = l1CacheEnabled;
    }
 
+
+   @ConfigurationAttribute(name = "lifespan", 
+            containingElement = "l1")   
    public void setL1Lifespan(long l1Lifespan) {
       testImmutability("l1Lifespan");
       this.l1Lifespan = l1Lifespan;
    }
 
+   @ConfigurationAttribute(name = "onRehash", 
+            containingElement = "l1")   
    public void setL1OnRehash(boolean l1OnRehash) {
       testImmutability("l1OnRehash");
       this.l1OnRehash = l1OnRehash;
    }
 
+   @ConfigurationAttribute(name = "consistentHashClass", 
+            containingElement = "hash")   
    public void setConsistentHashClass(String consistentHashClass) {
       testImmutability("consistentHashClass");
       this.consistentHashClass = consistentHashClass;
    }
-
+   
+   @ConfigurationAttribute(name = "numOwners", 
+            containingElement = "hash")    
    public void setNumOwners(int numOwners) {
       testImmutability("numOwners");
       this.numOwners = numOwners;
    }
 
+   @ConfigurationAttribute(name = "rehashWait", 
+            containingElement = "hash")    
    public void setRehashWaitTime(long rehashWaitTime) {
       testImmutability("rehashWaitTime");
       this.rehashWaitTime = rehashWaitTime;
    }
 
+   @ConfigurationAttribute(name = "asyncMarshalling", 
+            containingElement = "async")
    public void setUseAsyncMarshalling(boolean useAsyncMarshalling) {
       testImmutability("useAsyncMarshalling");
       this.useAsyncMarshalling = useAsyncMarshalling;

Modified: trunk/core/src/main/java/org/infinispan/config/ConfigurationElement.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/ConfigurationElement.java	2009-07-08 09:03:28 UTC (rev 521)
+++ trunk/core/src/main/java/org/infinispan/config/ConfigurationElement.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -22,6 +22,7 @@
 package org.infinispan.config;
 
 import java.lang.annotation.*;
+import org.infinispan.config.parsing.ConfigurationElementReader;
 
 
 /**
@@ -40,5 +41,7 @@
     String parent();
 
     String description() default "";
+    
+    Class <? extends ConfigurationElementReader> customReader() default ConfigurationElementReader.class;
       
 }

Modified: trunk/core/src/main/java/org/infinispan/config/GlobalConfiguration.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/GlobalConfiguration.java	2009-07-08 09:03:28 UTC (rev 521)
+++ trunk/core/src/main/java/org/infinispan/config/GlobalConfiguration.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -101,6 +101,9 @@
       return mBeanServerLookup;
    }
 
+   @ConfigurationAttribute(name = "mBeanServerLookup", 
+            containingElement = "globalJmxStatistics", 
+            description = "")
    public void setMBeanServerLookup(String mBeanServerLookup) {
       testImmutability("mBeanServerLookup");
       this.mBeanServerLookup = mBeanServerLookup;
@@ -110,6 +113,9 @@
       return allowDuplicateDomains;
    }
 
+   @ConfigurationAttribute(name = "allowDuplicateDomains", 
+            containingElement = "globalJmxStatistics", 
+            description = "")
    public void setAllowDuplicateDomains(boolean allowDuplicateDomains) {
       testImmutability("allowDuplicateDomains");
       this.allowDuplicateDomains = allowDuplicateDomains;

Added: trunk/core/src/main/java/org/infinispan/config/parsing/AutomatedXmlConfigurationParserImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/parsing/AutomatedXmlConfigurationParserImpl.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/config/parsing/AutomatedXmlConfigurationParserImpl.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,364 @@
+package org.infinispan.config.parsing;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.infinispan.config.AbstractConfigurationBean;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.ConfigurationAttribute;
+import org.infinispan.config.ConfigurationElement;
+import org.infinispan.config.ConfigurationElements;
+import org.infinispan.config.ConfigurationException;
+import org.infinispan.config.ConfigurationProperties;
+import org.infinispan.config.ConfigurationProperty;
+import org.infinispan.config.DuplicateCacheNameException;
+import org.infinispan.config.GlobalConfiguration;
+import org.infinispan.util.ClassFinder;
+import org.infinispan.util.FileLookup;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * The default XML configuration parser
+ *
+ * @author Manik Surtani
+ * @since 4.0
+ */
+public class AutomatedXmlConfigurationParserImpl extends XmlParserBase implements XmlConfigurationParser {
+   
+   public static List<Class<?>> INFINISPAN_CLASSES = null;
+   public static  List<Class<?>> CONFIG_BEANS =null;
+   
+   static {
+      try {
+         INFINISPAN_CLASSES = ClassFinder.infinispanClasses();
+         CONFIG_BEANS = ClassFinder.isAssignableFrom(INFINISPAN_CLASSES,AbstractConfigurationBean.class);
+      } catch (Exception e) {        
+        //TODO what to do here?
+      }
+   }
+
+   // this parser will need to be initialized.
+   boolean initialized = false;
+
+   // the root element, representing the <infinispan /> tag
+   Element rootElement;
+
+   GlobalConfiguration gc;
+   Map<String, Configuration> namedCaches;
+
+   /**
+    * Constructs a new parser
+    */
+   public AutomatedXmlConfigurationParserImpl() {}
+
+   /**
+    * Constructs a parser and initializes it with the file name passed in, by calling {@link #initialize(String)}.
+    *
+    * @param fileName file name to initialize the parser with
+    * @throws IOException if there is a problem reading or locating the file.
+    */
+   public AutomatedXmlConfigurationParserImpl(String fileName) throws IOException {
+      initialize(fileName);
+   }
+
+   /**
+    * Constructs a parser and initializes it with the input stream passed in, by calling {@link
+    * #initialize(InputStream)}.
+    *
+    * @param inputStream input stream to initialize the parser with
+    * @throws IOException if there is a problem reading the stream
+    */
+   public AutomatedXmlConfigurationParserImpl(InputStream inputStream) throws IOException {
+      initialize(inputStream);
+   }
+
+   public void initialize(String fileName) throws IOException {
+      if (fileName == null) throw new NullPointerException("File name cannot be null!");
+      FileLookup fileLookup = new FileLookup();
+      InputStream is = fileLookup.lookupFile(fileName);
+      if (is == null)
+         throw new FileNotFoundException("File " + fileName + " could not be found, either on the classpath or on the file system!");
+      initialize(is);
+   }
+
+   public void initialize(InputStream inputStream) throws IOException {
+      if (inputStream == null) throw new NullPointerException("Input stream cannot be null!");
+      initialized = true;
+      rootElement = new RootElementBuilder().readRoot(inputStream);
+   }
+
+   public Configuration parseDefaultConfiguration() throws ConfigurationException {
+      assertInitialized();
+      if (gc == null) {
+         Element defaultElement = getSingleElementInCoreNS("default", rootElement);
+         // there may not be a <default /> element!
+         if (defaultElement == null) {
+            return new Configuration();
+         } else {
+            defaultElement.normalize();            
+            AbstractConfigurationBean bean = findAndInstantiateBean(CONFIG_BEANS, defaultElement);
+            visitElement(defaultElement, bean);
+            return (Configuration) bean;
+         }
+      } else {
+         return gc.getDefaultConfiguration();
+      }
+   }
+
+   public Map<String, Configuration> parseNamedConfigurations() throws ConfigurationException {
+      assertInitialized();
+      // there may not be any namedCache elements!
+      if (namedCaches == null) {
+         Set<Element> elements = getAllElementsInCoreNS("namedCache", rootElement);
+         if (elements.isEmpty()) return Collections.emptyMap();
+         namedCaches = new HashMap<String, Configuration>(elements.size(), 1.0f);
+         for (Element e : elements) {
+            String configurationName = getAttributeValue(e, "name");
+            if (namedCaches.containsKey(configurationName)) {
+               namedCaches = null;
+               throw new DuplicateCacheNameException("Named cache " + configurationName + " is declared more than once!");
+            }
+            try {
+               AbstractConfigurationBean bean = findAndInstantiateBean(CONFIG_BEANS, e);
+               visitElement(e, bean);               
+               namedCaches.put(configurationName,(Configuration) bean);
+            } catch (ConfigurationException ce) {
+               throw new ConfigurationException("Problems configuring named cache '" + configurationName + "'", ce);
+            }
+         }
+      }
+
+      return namedCaches;
+   }
+
+   public GlobalConfiguration parseGlobalConfiguration() {
+      assertInitialized();
+      if (gc == null) {
+         Configuration defaultConfiguration = parseDefaultConfiguration();
+         Element globalElement = getSingleElementInCoreNS("global", rootElement);         
+         AbstractConfigurationBean bean = findAndInstantiateBean(CONFIG_BEANS, globalElement);
+         visitElement(globalElement, bean);
+         gc = (GlobalConfiguration) bean;
+         gc.setDefaultConfiguration(defaultConfiguration);
+      }
+      return gc;
+   }
+   
+   public AbstractConfigurationBean findAndInstantiateBean(List<Class<?>> b, Element e) throws ConfigurationException {
+      String name = e.getTagName();
+      for (Class<?> clazz : b) {
+         ConfigurationElements elements = clazz.getAnnotation(ConfigurationElements.class);
+         if (elements != null) {
+            for (ConfigurationElement ce : elements.elements()) {
+               if (ce.name().equals(name)) {
+                  try {
+                     return (AbstractConfigurationBean) clazz.newInstance();
+                  } catch (Exception e1) {
+                     throw new ConfigurationException("Could not instantiate class " + clazz, e1);
+                  }
+               }
+            }
+         } else {
+            ConfigurationElement ce = clazz.getAnnotation(ConfigurationElement.class);
+            if (ce != null && ce.name().equals(name)) {
+               try {
+                  return (AbstractConfigurationBean) clazz.newInstance();
+               } catch (Exception e1) {
+                  throw new ConfigurationException("Could not instantiate class " + clazz, e1);
+               }
+            }
+         }
+      }
+      return null;
+   }
+   
+   private ConfigurationElement findConfigurationElement(Element e, Class<?> bean) {
+      ConfigurationElement ces[] = null;
+      ConfigurationElements configurationElements = bean.getAnnotation(ConfigurationElements.class);
+      ConfigurationElement configurationElement = bean.getAnnotation(ConfigurationElement.class);
+
+      if (configurationElement != null && configurationElements == null) {
+         ces = new ConfigurationElement[] { configurationElement };
+      }
+      if (configurationElements != null && configurationElement == null) {
+         ces = configurationElements.elements();
+      }
+      if (ces != null) {
+         for (ConfigurationElement el : ces) {
+            if (el.name().equals(e.getNodeName())) {
+               return el;
+            }
+         }
+      }
+      return null;
+   }
+   
+   private ConfigurationElement customReader(Element e, Class<?> bean) {     
+      ConfigurationElement result = findConfigurationElement(e, bean);
+      if (result == null) {
+         for (Class<?> beanClass : CONFIG_BEANS) {
+            result = findConfigurationElement(e, beanClass);
+            if (result != null)
+               break;
+         }
+      }
+      if(result != null){
+         if(!result.customReader().equals(ConfigurationElementReader.class)){
+            return result;
+         }
+      }
+      return null;
+   }
+   
+   public void visitElement(Element e, AbstractConfigurationBean bean) throws ConfigurationException {     
+      ConfigurationElement ce = customReader(e, bean.getClass());      
+      //has customer reader, use it
+      if (ce != null) {
+         Class<? extends ConfigurationElementReader> readerClass = ce.customReader();
+         ConfigurationElementReader reader = null;
+         try {            
+            reader = readerClass.newInstance();
+            reader.setParser(this);
+            reader.process(e, bean);
+         } catch (Exception e1) {
+            throw new ConfigurationException(e1);
+         }
+      } else {
+         for (Method m : bean.getClass().getMethods()) {
+            boolean setter = m.getName().startsWith("set") && m.getParameterTypes().length == 1;
+            if (setter) {
+               reflectAndInvokeAttribute(bean, m, e);
+               reflectAndInvokeProperties(bean, m, e);              
+            }
+         }
+         NodeList nodeList = e.getChildNodes();
+         for (int numChildren = nodeList.getLength(), i = 0; i < numChildren; i++) {
+            Node node = nodeList.item(i);
+            if (node instanceof Element) {
+               Element childNode = (Element) node;
+               // recursive step
+               visitElement(childNode, bean);
+            }
+         }
+      }
+   }
+   
+   private void reflectAndInvokeAttribute(AbstractConfigurationBean bean, Method m, Element node) {     
+      Class<?> parameterType = m.getParameterTypes()[0];
+      // is there a ConfigurationAttribute matching the current node iterated?
+      ConfigurationAttribute a = m.getAnnotation(ConfigurationAttribute.class);
+      boolean matchedAttributeToSetter = a != null && a.containingElement().equals(node.getNodeName());
+      boolean isConfigBean = AbstractConfigurationBean.class.isAssignableFrom(parameterType);
+      if (matchedAttributeToSetter) {
+         String attValue = getAttributeValue((Element) node, a.name());
+         if (attValue != null && attValue.length() > 0) {
+            Object o = convertToType(attValue, parameterType);
+            try {              
+               m.invoke(bean, o);
+            } catch (Exception ae) {
+               throw new ConfigurationException("Illegal attribute value " + attValue + ",type="
+                        + parameterType + ", method=" + m, ae);
+            }
+         }
+      } else if (isConfigBean) {
+         AbstractConfigurationBean childBean = findAndInstantiateBean(CONFIG_BEANS, node);
+         boolean foundMatchingChild = childBean != null
+                  && !bean.getClass().equals(childBean.getClass())
+                  && parameterType.isInstance(childBean);
+         if (foundMatchingChild) {                   
+            try {
+               m.invoke(bean, childBean);
+            } catch (Exception ae) {
+               throw new ConfigurationException("Illegal bean value " + childBean + ",type="
+                        + parameterType + ", method=" + m, ae);
+            }
+         }
+      }
+   }
+   
+   private boolean reflectAndInvokeProperties(AbstractConfigurationBean bean, Method m, Element node){
+      Class<?> parameterType = m.getParameterTypes()[0];
+      
+      //how about ConfigurationProperties or ConfigurationProperty matching the current node iterated?
+      ConfigurationProperty[] cprops = null;
+      ConfigurationProperties cp = m.getAnnotation(ConfigurationProperties.class);               
+      if (cp != null) {
+         cprops = cp.elements();
+      } else {
+         ConfigurationProperty p = null;
+         p = m.getAnnotation(ConfigurationProperty.class);
+         if (p != null) {
+            cprops = new ConfigurationProperty[] { p };
+         }
+      }
+      boolean matchedPropertyToSetter  = cprops != null && cprops.length >0;
+      if(matchedPropertyToSetter){
+         String parentElement = cprops[0].parentElement();
+         String propertyName = cprops[0].name();
+         if(parentElement.equals(node.getParentNode().getNodeName())){           
+            if(node.getNodeName().equals("property")){
+               Properties props = XmlConfigHelper.extractProperties((Element) node.getParentNode());
+               if (Properties.class.isAssignableFrom(parameterType)) {
+                  try {
+                     m.invoke(bean, props);
+                  } catch (Exception ae) {
+                     throw new ConfigurationException("Illegal props " + props + ",type="
+                              + parameterType + ", method=" + m, ae);
+                  } 
+               } else if (parameterType.isAssignableFrom(String.class) || parameterType.isPrimitive()) {                  
+                  String value = props.getProperty(propertyName);
+                  if (value != null && value.length() > 0) {
+                     Object o = value;
+                     if (parameterType.isPrimitive()) {
+                        o = convertToType(value, parameterType);
+                     }
+                     try {
+                        m.invoke(bean, o);
+                     } catch (Exception ae) {
+                        throw new ConfigurationException("Illegal value " + o
+                                 + ",type=" + parameterType + ", method=" + m, ae);
+                     }
+                  }
+               }
+               //we assume that all other siblings of <property> element are also <property> elements 
+               // there no need to iterate them as we have extracted them all using the  method above
+               // therefore skip them by returning
+               return true;
+            }
+         }         
+      }
+      return false;
+   }
+   
+   private Object convertToType(String attValue, Class<?> clazz) {
+      if (clazz.isPrimitive()) {
+         if (clazz.isAssignableFrom(Boolean.TYPE)) {
+            return Boolean.parseBoolean(attValue);
+         } else if (clazz.isAssignableFrom(Integer.TYPE)) {
+            return Integer.parseInt(attValue);
+         } else if (clazz.isAssignableFrom(Double.TYPE)) {
+            return Double.parseDouble(attValue);
+         } else if (clazz.isAssignableFrom(Long.TYPE)) {
+            return Long.parseLong(attValue);
+         } else if (clazz.isAssignableFrom(Short.TYPE)) {            
+            return Short.parseShort(attValue);
+         }
+      }
+      return attValue;
+   }
+   
+   private void assertInitialized() {
+      if (!initialized)
+         throw new ConfigurationException("Parser not initialized.  Please invoke initialize() first, or use a constructor that initializes the parser.");
+   }
+}
\ No newline at end of file

Added: trunk/core/src/main/java/org/infinispan/config/parsing/CacheLoaderManagerConfigReader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/parsing/CacheLoaderManagerConfigReader.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/config/parsing/CacheLoaderManagerConfigReader.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.config.parsing;
+
+import java.util.Set;
+
+import org.infinispan.config.AbstractConfigurationBean;
+import org.infinispan.config.CacheLoaderManagerConfig;
+import org.infinispan.config.ConfigurationException;
+import org.infinispan.config.Configuration;
+import org.infinispan.loaders.CacheLoader;
+import org.infinispan.loaders.CacheLoaderConfig;
+import org.infinispan.util.Util;
+import org.w3c.dom.Element;
+
+public class CacheLoaderManagerConfigReader implements ConfigurationElementReader {
+
+   private AutomatedXmlConfigurationParserImpl parser;
+
+   public CacheLoaderManagerConfigReader() {
+      super();
+   }
+
+   public void setParser(AutomatedXmlConfigurationParserImpl parser) {
+      this.parser = parser;
+   }
+
+   public void process(Element e, AbstractConfigurationBean bean) {
+      
+      CacheLoaderManagerConfig cBean = (CacheLoaderManagerConfig) parser.findAndInstantiateBean(
+               AutomatedXmlConfigurationParserImpl.CONFIG_BEANS, e);
+
+      Set<Element> elements = parser.getAllElementsInCoreNS("loader", e);
+      if (elements.isEmpty())
+         throw new ConfigurationException("No loader elements found!");
+
+      for (Element element : elements) {
+         String clClass = parser.getAttributeValue(element, "class");
+         if (!parser.existsAttribute(clClass))
+            throw new ConfigurationException("Missing 'class'  attribute for cache loader configuration");
+
+         CacheLoader cl;
+         CacheLoaderConfig clc;
+         try {
+            cl = (CacheLoader) Util.getInstance(clClass);
+            clc = Util.getInstance(cl.getConfigurationClass());
+         } catch (Exception ex) {
+            throw new ConfigurationException("Unable to instantiate cache loader or configuration",
+                     ex);
+         }
+
+         clc.setCacheLoaderClassName(clClass);
+         Element propertiesElement = parser.getSingleElementInCoreNS("properties", element);
+         if (propertiesElement == null)
+            throw new ConfigurationException("loader " + clClass + " is missing properties element");
+         parser.visitElement(element, (AbstractConfigurationBean) clc);
+         cBean.addCacheLoaderConfig(clc);
+      }
+      ((Configuration)bean).setCacheLoaderManagerConfig(cBean);
+   }
+}

Added: trunk/core/src/main/java/org/infinispan/config/parsing/ClusteringConfigReader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/parsing/ClusteringConfigReader.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/config/parsing/ClusteringConfigReader.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.config.parsing;
+
+import org.infinispan.config.AbstractConfigurationBean;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.ConfigurationException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class ClusteringConfigReader implements ConfigurationElementReader {
+
+   private AutomatedXmlConfigurationParserImpl parser;
+
+   public ClusteringConfigReader() {
+      super();
+   }
+
+   public void setParser(AutomatedXmlConfigurationParserImpl parser) {
+      this.parser = parser;
+   }
+
+   public void process(Element e, AbstractConfigurationBean bean) {
+      if (e == null) return; //we might not have this configured
+
+      Configuration config = (Configuration) bean;
+      Configuration.CacheMode cacheMode;
+      String mode = parser.getAttributeValue(e, "mode").toUpperCase();
+      if (mode.startsWith("R"))
+         cacheMode = Configuration.CacheMode.REPL_SYNC;
+      else if (mode.startsWith("I"))
+         cacheMode = Configuration.CacheMode.INVALIDATION_SYNC;
+      else
+         cacheMode = Configuration.CacheMode.DIST_SYNC; // the default
+
+      Element asyncEl = parser.getSingleElementInCoreNS("async", e);
+      Element syncEl = parser.getSingleElementInCoreNS("sync", e);
+      if (syncEl != null && asyncEl != null)
+         throw new ConfigurationException("Cannot have sync and async elements within the same cluster element!");
+      boolean sync = asyncEl == null; // even if both are null, we default to sync
+      if (sync) {
+         config.setCacheMode(cacheMode);        
+      } else {
+         cacheMode = cacheMode.toAsync(); // get the async version of this mode
+         config.setCacheMode(cacheMode);
+      }
+      
+      NodeList nodeList = e.getChildNodes();
+      for (int numChildren = nodeList.getLength(), i = 0; i < numChildren; i++) {
+         Node node = nodeList.item(i);
+         if (node instanceof Element) {
+            Element childNode = (Element) node;
+            // recursive step
+            parser.visitElement(childNode, bean);
+         }
+      }    
+   }
+}

Added: trunk/core/src/main/java/org/infinispan/config/parsing/ConfigurationElementReader.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/parsing/ConfigurationElementReader.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/config/parsing/ConfigurationElementReader.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.config.parsing;
+
+import org.infinispan.config.AbstractConfigurationBean;
+import org.w3c.dom.Element;
+
+public interface ConfigurationElementReader {
+   
+   public void process(Element e, AbstractConfigurationBean c);   
+   public void setParser(AutomatedXmlConfigurationParserImpl parser);
+
+}

Modified: trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java	2009-07-08 09:03:28 UTC (rev 521)
+++ trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -1,6 +1,8 @@
 package org.infinispan.loaders.decorators;
 
 import org.infinispan.config.AbstractNamedCacheConfigurationBean;
+import org.infinispan.config.ConfigurationAttribute;
+import org.infinispan.config.ConfigurationElement;
 
 /**
  * Configuration for the async cache loader
@@ -8,6 +10,7 @@
  * @author Manik Surtani
  * @since 4.0
  */
+ at ConfigurationElement(name="async", parent="loader")
 public class AsyncStoreConfig extends AbstractNamedCacheConfigurationBean {
    boolean enabled;
    int batchSize = 100;
@@ -19,6 +22,9 @@
       return enabled;
    }
 
+   @ConfigurationAttribute(name = "enabled", 
+            containingElement = "async",
+            description="TODO")
    public void setEnabled(boolean enabled) {
       testImmutability("enabled");
       this.enabled = enabled;
@@ -28,6 +34,9 @@
       return batchSize;
    }
 
+   @ConfigurationAttribute(name = "batchSize", 
+            containingElement = "async",
+            description="TODO")
    public void setBatchSize(int batchSize) {
       testImmutability("batchSize");
       this.batchSize = batchSize;
@@ -55,6 +64,10 @@
       return threadPoolSize;
    }
 
+   
+   @ConfigurationAttribute(name = "threadPoolSize", 
+            containingElement = "async",
+            description="TODO")
    public void setThreadPoolSize(int threadPoolSize) {
       testImmutability("threadPoolSize");
       this.threadPoolSize = threadPoolSize;

Added: trunk/core/src/main/java/org/infinispan/util/ClassFinder.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/ClassFinder.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/util/ClassFinder.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,133 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.util;
+
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.infinispan.util.Util;
+
+/**
+ * Find infinispan classes utility
+ * 
+ */
+public class ClassFinder {
+
+   public static List<Class<?>> withAnnotationPresent(List<Class<?>> classes, Class<? extends Annotation> c) {
+      List<Class<?>> clazzes = new ArrayList<Class<?>>();
+      for (Class<?> clazz : classes) {
+         if (clazz.isAnnotationPresent(c)) {
+            clazzes.add(clazz);
+         }
+      }
+      return clazzes;
+   }
+
+   public static List<Class<?>> isAssignableFrom(List<Class<?>> classes, Class<?> clazz) {
+      List<Class<?>> clazzes = new ArrayList<Class<?>>();
+      for (Class<?> c : classes) {
+         if (clazz.isAssignableFrom(c)) {
+            clazzes.add(c);
+         }
+      }
+      return clazzes;
+   }
+
+   public static List<Class<?>> withAnnotationPresent(Class<? extends Annotation> ann) throws Exception {
+      return withAnnotationPresent(infinispanClasses(), ann);
+   }
+
+   public static List<Class<?>> isAssignableFrom(Class<?> clazz) throws Exception {
+      return isAssignableFrom(infinispanClasses(), clazz);
+   }
+   
+   public static List<Class<?>> infinispanClasses() throws Exception {
+      List<File> files = new ArrayList<File>();
+      String javaClassPath = System.getProperty("java.class.path");
+
+      // either infinispan jar or a directory of output classes contains infinispan classes
+      for (String path : javaClassPath.split(File.pathSeparator)) {
+         if ((path.contains("infinispan") && path.endsWith("jar")) || !path.endsWith("jar")) {
+            files.add(new File(path));
+         }
+      }
+      if (files.isEmpty())
+         return Collections.emptyList();
+      else if (files.size() == 1)
+         return findClassesOnPath(files.get(0));
+      else {
+         Set<Class<?>> classFiles = new HashSet<Class<?>>();
+         for (File file : files) {
+            classFiles.addAll(findClassesOnPath(file));
+         }
+         return new ArrayList<Class<?>>(classFiles);
+      }
+   }
+
+   private static List<Class<?>> findClassesOnPath(File path) throws Exception {
+      List<Class<?>> classes = new ArrayList<Class<?>>();
+      if (path.isDirectory()) {
+         List<File> classFiles = new ArrayList<File>();
+         dir(classFiles, path);
+         for (File cf : classFiles) {
+            Class<?> claz = Util.loadClass(toClassName(cf.getAbsolutePath().toString()));
+            classes.add(claz);
+         }
+      } else {
+         if (path.isFile() && path.getName().endsWith("jar") && path.canRead()) {
+            JarFile jar = new JarFile(path);
+            Enumeration<JarEntry> en = jar.entries();
+            while (en.hasMoreElements()) {
+               JarEntry entry = en.nextElement();
+               if (entry.getName().endsWith("class")) {
+                  Class<?> claz = Util.loadClass(toClassName(entry.getName()));
+                  classes.add(claz);
+               }
+            }
+         }
+      }
+      return classes;
+   }
+
+   private static void dir(List<File> files, File dir) {
+      File[] entries = dir.listFiles();
+      for (File entry : entries) {
+         if (entry.isDirectory()) {
+            dir(files, entry);
+         } else if (entry.getName().endsWith("class")) {
+            files.add(entry);
+         }
+      }
+   }
+
+   private static String toClassName(String fileName) {
+      return fileName.substring(fileName.lastIndexOf("org"), fileName.length() - 6).replaceAll(File.separator, ".");
+   }
+}
\ No newline at end of file

Added: trunk/core/src/test/java/org/infinispan/config/parsing/AutomatedXmlFileParsingTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/config/parsing/AutomatedXmlFileParsingTest.java	                        (rev 0)
+++ trunk/core/src/test/java/org/infinispan/config/parsing/AutomatedXmlFileParsingTest.java	2009-07-08 13:08:14 UTC (rev 522)
@@ -0,0 +1,189 @@
+package org.infinispan.config.parsing;
+
+import org.infinispan.config.CacheLoaderManagerConfig;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.GlobalConfiguration;
+import org.infinispan.distribution.DefaultConsistentHash;
+import org.infinispan.loaders.file.FileCacheStoreConfig;
+import org.infinispan.util.concurrent.IsolationLevel;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.util.Map;
+
+ at Test(groups = "unit", testName = "config.parsing.XmlFileParsingTest")
+public class AutomatedXmlFileParsingTest {
+
+   public void testNamedCacheFile() throws IOException {
+      AutomatedXmlConfigurationParserImpl parser = new AutomatedXmlConfigurationParserImpl("configs/named-cache-test.xml");
+
+      GlobalConfiguration gc = parser.parseGlobalConfiguration();
+
+      assert gc.getAsyncListenerExecutorFactoryClass().equals("org.infinispan.executors.DefaultExecutorFactory");
+      assert gc.getAsyncListenerExecutorProperties().getProperty("maxThreads").equals("5");
+      assert gc.getAsyncListenerExecutorProperties().getProperty("threadNamePrefix").equals("AsyncListenerThread");
+
+      assert gc.getAsyncTransportExecutorFactoryClass().equals("org.infinispan.executors.DefaultExecutorFactory");
+      assert gc.getAsyncTransportExecutorProperties().getProperty("maxThreads").equals("25");
+      assert gc.getAsyncTransportExecutorProperties().getProperty("threadNamePrefix").equals("AsyncSerializationThread");
+
+      assert gc.getEvictionScheduledExecutorFactoryClass().equals("org.infinispan.executors.DefaultScheduledExecutorFactory");
+      assert gc.getEvictionScheduledExecutorProperties().getProperty("threadNamePrefix").equals("EvictionThread");
+
+      assert gc.getReplicationQueueScheduledExecutorFactoryClass().equals("org.infinispan.executors.DefaultScheduledExecutorFactory");
+      assert gc.getReplicationQueueScheduledExecutorProperties().getProperty("threadNamePrefix").equals("ReplicationQueueThread");
+
+      assert gc.getTransportClass().equals("org.infinispan.remoting.transport.jgroups.JGroupsTransport");
+      assert gc.getTransportProperties().isEmpty();
+
+      assert gc.getMarshallerClass().equals("org.infinispan.marshall.VersionAwareMarshaller");
+      assert gc.getMarshallVersionString().equals("1.0");
+
+      Configuration defaultConfiguration = parser.parseDefaultConfiguration();
+
+      assert defaultConfiguration.getLockAcquisitionTimeout() == 1000;
+      assert defaultConfiguration.getConcurrencyLevel() == 100;
+      assert defaultConfiguration.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+
+      Map<String, Configuration> namedCaches = parser.parseNamedConfigurations();
+
+      Configuration c = namedCaches.get("transactional");
+
+      assert c.getTransactionManagerLookupClass().equals("org.infinispan.transaction.lookup.GenericTransactionManagerLookup");
+
+      c = namedCaches.get("syncRepl");
+
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_SYNC;
+      assert !c.isFetchInMemoryState();
+      assert c.getSyncReplTimeout() == 15000;
+
+      c = namedCaches.get("asyncRepl");
+
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_ASYNC;
+      assert !c.isUseReplQueue();
+      assert !c.isUseAsyncMarshalling();
+      assert !c.isFetchInMemoryState();
+
+      c = namedCaches.get("asyncReplQueue");
+
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_ASYNC;
+      assert c.isUseReplQueue();
+      assert c.isUseAsyncMarshalling();
+      assert !c.isFetchInMemoryState();
+
+      c = namedCaches.get("txSyncRepl");
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_SYNC;
+      assert !c.isFetchInMemoryState();
+      assert c.getSyncReplTimeout() == 15000;
+
+      c = namedCaches.get("overriding");
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.LOCAL;
+      assert c.getLockAcquisitionTimeout() == 20000;
+      assert c.getConcurrencyLevel() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
+      assert !c.isUseLazyDeserialization();
+
+      c = namedCaches.get("lazyDeserialization");
+      assert c.isUseLazyDeserialization();
+
+      c = namedCaches.get("withLoader");
+      CacheLoaderManagerConfig loaderManagerConfig = c.getCacheLoaderManagerConfig();
+      assert loaderManagerConfig.getCacheLoaderConfigs().size() == 1;
+      FileCacheStoreConfig csConf = (FileCacheStoreConfig) loaderManagerConfig.getFirstCacheLoaderConfig();
+      assert csConf.getCacheLoaderClassName().equals("org.infinispan.loaders.file.FileCacheStore");
+      assert csConf.isFetchPersistentState();
+      assert csConf.isIgnoreModifications();
+      assert csConf.isPurgeOnStartup();
+      assert csConf.getLocation().equals("/tmp/FileCacheStore-Location");
+
+      c = namedCaches.get("withouthJmxEnabled");
+      assert !c.isExposeJmxStatistics();
+      assert !gc.isExposeGlobalJmxStatistics();
+      assert gc.isAllowDuplicateDomains();
+      assert gc.getJmxDomain().equals("funky_domain");
+      assert gc.getMBeanServerLookup().equals("org.infinispan.jmx.PerThreadMBeanServerLookup");
+
+      c = namedCaches.get("dist");
+      assert c.getCacheMode() == Configuration.CacheMode.DIST_SYNC;
+      assert c.getL1Lifespan() == 600000;
+      assert c.getRehashWaitTime() == 120000;
+      assert c.getConsistentHashClass().equals(DefaultConsistentHash.class.getName());
+      assert c.getNumOwners() == 3;
+      assert c.isL1CacheEnabled();
+   }
+
+   public void testConfigurationMerging() throws IOException {
+      AutomatedXmlConfigurationParserImpl parser = new AutomatedXmlConfigurationParserImpl("configs/named-cache-test.xml");
+      Configuration defaultCfg = parser.parseDefaultConfiguration();
+      Map<String, Configuration> namedCaches = parser.parseNamedConfigurations();
+
+      Configuration c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("transactional"));
+
+      assert c.getCacheMode() == Configuration.CacheMode.LOCAL;
+      assert c.getTransactionManagerLookupClass().equals("org.infinispan.transaction.lookup.GenericTransactionManagerLookup");
+      assert c.getLockAcquisitionTimeout() == 1000;
+      assert c.getConcurrencyLevel() == 100;
+      assert c.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+
+      c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("syncRepl"));
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_SYNC;
+      assert !c.isFetchInMemoryState();
+      assert c.getSyncReplTimeout() == 15000;
+      assert c.getLockAcquisitionTimeout() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+      assert c.getConcurrencyLevel() == 100;
+
+      c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("asyncRepl"));
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_ASYNC;
+      assert !c.isUseReplQueue();
+      assert !c.isUseAsyncMarshalling();
+      assert !c.isFetchInMemoryState();
+      assert c.getLockAcquisitionTimeout() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+      assert c.getConcurrencyLevel() == 100;
+
+      c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("asyncReplQueue"));
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_ASYNC;
+      assert c.isUseReplQueue();
+      assert c.getReplQueueInterval() == 1234;
+      assert c.getReplQueueMaxElements() == 100;
+      assert c.isUseAsyncMarshalling();
+      assert !c.isFetchInMemoryState();
+      assert c.getLockAcquisitionTimeout() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+      assert c.getConcurrencyLevel() == 100;
+
+      c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("txSyncRepl"));
+      assert c.getTransactionManagerLookupClass() ==null;
+      assert c.getCacheMode() == Configuration.CacheMode.REPL_SYNC;
+      assert !c.isFetchInMemoryState();
+      assert c.getSyncReplTimeout() == 15000;
+      assert c.getLockAcquisitionTimeout() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.READ_COMMITTED;
+      assert c.getConcurrencyLevel() == 100;
+
+      c = defaultCfg.clone();
+      c.applyOverrides(namedCaches.get("overriding"));
+
+      assert c.getTransactionManagerLookupClass() == null;
+      assert c.getCacheMode() == Configuration.CacheMode.LOCAL;
+      assert c.getLockAcquisitionTimeout() == 20000;
+      assert c.getConcurrencyLevel() == 1000;
+      assert c.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
+   }
+}
\ No newline at end of file




More information about the infinispan-commits mailing list