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

infinispan-commits at lists.jboss.org infinispan-commits at lists.jboss.org
Mon Sep 14 00:45:32 EDT 2009


Author: vblagojevic at jboss.com
Date: 2009-09-14 00:45:32 -0400 (Mon, 14 Sep 2009)
New Revision: 809

Added:
   trunk/core/src/main/java/org/infinispan/config/OverrideConfigurationVisitor.java
Modified:
   trunk/core/src/main/java/org/infinispan/config/AbstractConfigurationBean.java
   trunk/core/src/main/java/org/infinispan/config/AbstractNamedCacheConfigurationBean.java
   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/loaders/AbstractCacheStoreConfig.java
   trunk/core/src/main/java/org/infinispan/loaders/CacheStoreConfig.java
   trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java
   trunk/core/src/main/java/org/infinispan/loaders/decorators/SingletonStoreConfig.java
   trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
   trunk/core/src/test/java/org/infinispan/loaders/decorators/SingletonStoreTest.java
Log:
implement Configuration#applyOverrides and Configuration#inject using visitor pattern

Modified: trunk/core/src/main/java/org/infinispan/config/AbstractConfigurationBean.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/AbstractConfigurationBean.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/config/AbstractConfigurationBean.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -21,33 +21,26 @@
  */
 package org.infinispan.config;
 
-import org.infinispan.CacheException;
-import org.infinispan.factories.scopes.Scope;
-import org.infinispan.factories.scopes.Scopes;
-import org.infinispan.util.ReflectionUtil;
-import org.infinispan.util.TypedProperties;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Properties;
 
+import org.infinispan.factories.scopes.Scope;
+import org.infinispan.factories.scopes.Scopes;
+import org.infinispan.util.TypedProperties;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
 /**
  * Base superclass of Cache configuration classes that expose some properties that can be changed after the cache is
  * started.
  *
  * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
- * @see #testImmutability(String)
+ * @author Vladimir Blagojevic
  * @since 4.0
  */
 @Scope(Scopes.NAMED_CACHE)
@@ -58,8 +51,7 @@
    private boolean accessible;
    protected List<String> overriddenConfigurationElements = new LinkedList<String>();
 
-   protected AbstractConfigurationBean() {
-   }
+   protected AbstractConfigurationBean() {}
    
 
    /**
@@ -124,87 +116,9 @@
       overriddenConfigurationElements.add(fieldName);
    }
 
-   public void applyOverrides(AbstractConfigurationBean overrides) {
-      //does this component have overridden fields?
-      for (String overridenField : overrides.overriddenConfigurationElements) {
-         try {
-            ReflectionUtil.setValue(this, overridenField, ReflectionUtil.getValue(overrides,overridenField));
-         } catch (Exception e1) {
-            throw new CacheException("Could not apply value for field " + overridenField
-                     + " from instance " + overrides + " on instance " + this, e1);
-         }
-      }
-
-      // then recurse into field of this component...
-      List<Field> fields = ReflectionUtil.getFields(overrides.getClass(),AbstractConfigurationBean.class);
-      for (Field field : fields) {
-         if (AbstractConfigurationBean.class.isAssignableFrom(field.getType())) {
-            AbstractConfigurationBean fieldValueOverrides = null;
-            AbstractConfigurationBean fieldValueThis = null;
-            try {
-               field.setAccessible(true);
-               fieldValueOverrides = (AbstractConfigurationBean) field.get(overrides);
-               fieldValueThis = (AbstractConfigurationBean) field.get(this);
-               if (fieldValueThis == null && fieldValueOverrides != null){
-                  field.set(this, fieldValueOverrides);
-               }
-               else if(fieldValueOverrides != null && fieldValueThis!=null){
-                  fieldValueThis.applyOverrides(fieldValueOverrides);
-               }
-            } catch (IllegalAccessException e) {
-               String s = "Could not apply override for field " + field + " in class " + overrides;
-               log.error(s, e);
-               throw new CacheException(s, e);
-            }
-         }
-      }
-
-      //and don't forget to recurse into collections of components...
-      fields = ReflectionUtil.getFields(overrides.getClass(), Collection.class);
-      for (Field field : fields) {
-         Type genericType = field.getGenericType();
-         if (genericType instanceof ParameterizedType) {
-            ParameterizedType aType = (ParameterizedType) genericType;
-            Type[] fieldArgTypes = aType.getActualTypeArguments();
-            for (Type fieldArgType : fieldArgTypes) {
-               Class<?> fieldArgClass = (Class<?>) fieldArgType;
-               if (!(fieldArgClass.isPrimitive() || fieldArgClass.equals(String.class))) {
-                  try {
-                     field.setAccessible(true);
-                     Collection<Object> c = (Collection<Object>) field.get(this);
-                     Collection<Object> c2 = (Collection<Object>) field.get(overrides);
-                     if (c.isEmpty() && !c2.isEmpty()) {
-                        c.addAll(c2);
-                     } else if (!c.isEmpty() && !c2.isEmpty()) {
-                        Iterator<?> i = c.iterator();
-                        Iterator<?> i2 = c2.iterator();
-                        for (; i.hasNext() && i2.hasNext();) {
-                           Object nextThis = i.next();
-                           Object nextOverrides = i2.next();
-                           if (AbstractConfigurationBean.class.isAssignableFrom(nextThis.getClass())
-                                    && AbstractConfigurationBean.class.isAssignableFrom(nextOverrides.getClass())) {
-                              ((AbstractConfigurationBean) nextThis).applyOverrides((AbstractConfigurationBean) nextOverrides);
-                           }
-                        }
-                        while (i2.hasNext()) {
-                           c.add(i2.next());
-                        }
-                     }
-                  } catch (IllegalAccessException e) {
-                     String s = "Could not apply override for field " + field + " in class " + overrides.getClass();
-                     log.error(s, e);
-                     throw new CacheException(s, e);
-                  }
-               }
-            }
-         }
-      }
-   }
-
    @Override
    public CloneableConfigurationComponent clone() throws CloneNotSupportedException {
       AbstractConfigurationBean c = (AbstractConfigurationBean) super.clone();
-//      c.setCache(null);
       return c;
    }
 }

Modified: trunk/core/src/main/java/org/infinispan/config/AbstractNamedCacheConfigurationBean.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/AbstractNamedCacheConfigurationBean.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/config/AbstractNamedCacheConfigurationBean.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -5,78 +5,24 @@
 import org.infinispan.factories.scopes.Scope;
 import org.infinispan.factories.scopes.Scopes;
 import org.infinispan.lifecycle.ComponentStatus;
-import org.infinispan.util.ReflectionUtil;
-import org.infinispan.CacheException;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.List;
-
 /**
- * Adds named cache specific features to the {@link org.infinispan.config.AbstractConfigurationBean}.
- *
+ * Adds named cache specific features to the {@link org.infinispan.config.AbstractConfigurationBean}
+ * .
+ * 
  * @author Manik Surtani
  * @author Galder Zamarreño
+ * @author Vladimir Blagojevic
  * @since 4.0
  */
 @Scope(Scopes.NAMED_CACHE)
 public abstract class AbstractNamedCacheConfigurationBean extends AbstractConfigurationBean {
 
    protected ComponentRegistry cr;
-   
+
    @Inject
    public void inject(ComponentRegistry cr) {
       this.cr = cr;
-      
-      // then recurse into field of this component...
-      List<Field> fields = ReflectionUtil.getFields(this.getClass(),AbstractNamedCacheConfigurationBean.class);
-      for (Field field : fields) {         
-         AbstractNamedCacheConfigurationBean fieldValueThis = null;
-            try {
-               field.setAccessible(true);               
-               fieldValueThis = (AbstractNamedCacheConfigurationBean) field.get(this);
-               if(fieldValueThis!=null){
-                  fieldValueThis.inject(cr);
-               }
-            } catch (Exception e) {
-               String s = "Could not inject for field " + field + " in class " + fieldValueThis;
-               log.error(s, e);
-               throw new CacheException(s, e);
-            }
-      }
-      
-      //and don't forget to recurse into collections of components...
-      fields = ReflectionUtil.getFields(this.getClass(), Collection.class);
-      for (Field field : fields) {
-         Type genericType = field.getGenericType();
-         if (genericType instanceof ParameterizedType) {
-            ParameterizedType aType = (ParameterizedType) genericType;
-            Type[] fieldArgTypes = aType.getActualTypeArguments();
-            for (Type fieldArgType : fieldArgTypes) {
-               Class<?> fieldArgClass = (Class<?>) fieldArgType;
-               if (!(fieldArgClass.isPrimitive() || fieldArgClass.equals(String.class))) {
-                  try {
-                     field.setAccessible(true);
-                     Collection<Object> c = (Collection<Object>) field.get(this);
-                     for (Object nextThis : c) {
-                        if (AbstractNamedCacheConfigurationBean.class.isAssignableFrom(nextThis.getClass())) {
-                           ((AbstractNamedCacheConfigurationBean) nextThis).inject(cr);
-                        } else {
-                           //collection does not contain AbstractNamedCacheConfigurationBean, skip altogether
-                           break;
-                        }
-                     }
-                  } catch (Exception e) {
-                     String errorMsg = "Could not inject for field " + field + " in class " + field;
-                     log.error(errorMsg,e);
-                     throw new CacheException(errorMsg, e);
-                  }
-               }
-            }
-         }
-      }
    }
 
    protected boolean hasComponentStarted() {
@@ -85,9 +31,19 @@
 
    @Override
    public AbstractNamedCacheConfigurationBean clone() throws CloneNotSupportedException {
-      AbstractNamedCacheConfigurationBean dolly = (AbstractNamedCacheConfigurationBean) super.clone();
-      if (cr != null) dolly.cr = (ComponentRegistry) cr.clone(); 
+      AbstractNamedCacheConfigurationBean dolly = (AbstractNamedCacheConfigurationBean) super
+               .clone();
+      if (cr != null)
+         dolly.cr = (ComponentRegistry) cr.clone();
       return dolly;
    }
 
+   class InjectComponentRegistryVisitor extends AbstractConfigurationBeanVisitor {
+
+      public void defaultVisit(AbstractConfigurationBean c) {
+         if (c instanceof AbstractNamedCacheConfigurationBean) {
+            ((AbstractNamedCacheConfigurationBean) c).cr = cr;
+         }
+      }
+   }
 }

Modified: trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/config/CacheLoaderManagerConfig.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -33,72 +33,84 @@
 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#addCacheLoaderConfig}
+ * 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#addCacheLoaderConfig}
  * 
  * <p>
- * Note that class CacheLoaderManagerConfig contains JAXB annotations. These annotations determine how XML
- * configuration files are read into instances of configuration class hierarchy as well as they
- * provide meta data for configuration file XML schema generation. Please modify these annotations
- * and Java element types they annotate with utmost understanding and care.
+ * Note that class CacheLoaderManagerConfig contains JAXB annotations. These annotations determine
+ * how XML configuration files are read into instances of configuration class hierarchy as well as
+ * they provide meta data for configuration file XML schema generation. Please modify these
+ * annotations and Java element types they annotate with utmost understanding and care.
  * 
  * @configRef name="loaders",desc="Holds the configuration of the cache loader chain."
- *
+ * 
  * @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
  * @author Brian Stansberry
- * @author Vladimir Blagojevic 
+ * @author Vladimir Blagojevic
  * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @since 4.0
  */
- at XmlAccessorType(XmlAccessType.FIELD)
+ at XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
 public class CacheLoaderManagerConfig extends AbstractNamedCacheConfigurationBean {
+   
    private static final long serialVersionUID = 2210349340378984424L;
 
-   /** 
-    * @configRef desc="If true, activates entries that have been passivated to a store by loading them into memory 
-    * as well as writes evicted entries back to the store" 
+   /**
+    * @configRef desc="If true, activates entries that have been passivated to a store by loading
+    *            them into memory as well as writes evicted entries back to the store"
     * */
-   @XmlAttribute
    protected Boolean passivation = false;
-   
-   /** 
+
+   /**
     * @configRef desc= "If true, performs a preload on the cache loader"
     * */
-   @XmlAttribute
    protected Boolean preload = false;
-   
-   /** 
-    * @configRef desc="If true, the node that makes a modification is the only one who writes it to the 
-    * store using the relevant cache loader." 
+
+   /**
+    * @configRef desc="If true, the node that makes a modification is the only one who writes it to
+    *            the store using the relevant cache loader."
     * */
-   @XmlAttribute
    protected Boolean shared = false;
-  
-   @XmlElement(name="loader")
+
    protected List<CacheLoaderConfig> cacheLoaderConfigs = new LinkedList<CacheLoaderConfig>();
 
+   public Boolean isPreload() {
+      return preload;
+   }
 
-
-   
-   public void setPreload(boolean preload) {
+   @XmlAttribute
+   public void setPreload(Boolean preload) {
       testImmutability("preload");
       this.preload = preload;
    }
 
-   public void setPassivation(boolean passivation) {
+   @XmlAttribute
+   public void setPassivation(Boolean passivation) {
       testImmutability("passivation");
       this.passivation = passivation;
    }
 
-   public boolean isPassivation() {
+   public Boolean isPassivation() {
       return passivation;
    }
 
+   @XmlAttribute
+   public void setShared(Boolean shared) {
+      testImmutability("shared");
+      this.shared = shared;
+   }
+
+   public Boolean isShared() {
+      return shared;
+   }
+
    public void addCacheLoaderConfig(CacheLoaderConfig clc) {
       testImmutability("cacheLoaderConfigs");
       cacheLoaderConfigs.add(clc);
    }
 
+   @XmlElement(name = "loader")
    public List<CacheLoaderConfig> getCacheLoaderConfigs() {
       return cacheLoaderConfigs;
    }
@@ -109,10 +121,24 @@
    }
 
    public CacheLoaderConfig getFirstCacheLoaderConfig() {
-      if (cacheLoaderConfigs.size() == 0) return null;
+      if (cacheLoaderConfigs.size() == 0)
+         return null;
       return cacheLoaderConfigs.get(0);
    }
 
+   /**
+    * 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 instanceof CacheStoreConfig)
+            if (((CacheStoreConfig) iclc).isFetchPersistentState())
+               return true;
+      }
+      return false;
+   }
+
    public boolean useChainingCacheLoader() {
       return !isPassivation() && cacheLoaderConfigs.size() > 1;
    }
@@ -125,15 +151,6 @@
                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)
@@ -141,14 +158,13 @@
 
       if (obj instanceof CacheLoaderManagerConfig) {
          CacheLoaderManagerConfig other = (CacheLoaderManagerConfig) obj;
-         return (this.passivation.equals(other.passivation))
-               && (this.shared.equals(other.shared))
-               && Util.safeEquals(this.preload, other.preload)
-               && Util.safeEquals(this.cacheLoaderConfigs, other.cacheLoaderConfigs);
+         return (this.passivation.equals(other.passivation)) && (this.shared.equals(other.shared))
+                  && Util.safeEquals(this.preload, other.preload)
+                  && Util.safeEquals(this.cacheLoaderConfigs, other.cacheLoaderConfigs);
       }
       return false;
    }
-       
+
    public void accept(ConfigurationBeanVisitor v) {
       for (CacheLoaderConfig clc : cacheLoaderConfigs) {
          clc.accept(v);
@@ -166,7 +182,6 @@
       return result;
    }
 
-
    @Override
    public CacheLoaderManagerConfig clone() throws CloneNotSupportedException {
       CacheLoaderManagerConfig clone = (CacheLoaderManagerConfig) super.clone();
@@ -179,19 +194,4 @@
       }
       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 instanceof CacheStoreConfig)
-            if (((CacheStoreConfig) iclc).isFetchPersistentState()) return true;
-      }
-      return false;
-   }
-
-   public boolean isPreload() {
-      return preload;
-   }
 }

Modified: trunk/core/src/main/java/org/infinispan/config/Configuration.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/Configuration.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/config/Configuration.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -23,6 +23,7 @@
 
 import org.infinispan.distribution.DefaultConsistentHash;
 import org.infinispan.eviction.EvictionStrategy;
+import org.infinispan.factories.ComponentRegistry;
 import org.infinispan.factories.annotations.Inject;
 import org.infinispan.factories.annotations.NonVolatile;
 import org.infinispan.factories.annotations.Start;
@@ -112,13 +113,13 @@
    private ClusteringType clustering = new ClusteringType();
    
    @XmlElement
-   private BooleanAttributeType jmxStatistics = new BooleanAttributeType();
+   private BooleanAttributeType jmxStatistics = new BooleanAttributeType("jmxStatistics");
    
    @XmlElement
-   private BooleanAttributeType lazyDeserialization = new BooleanAttributeType();
+   private BooleanAttributeType lazyDeserialization = new BooleanAttributeType("lazyDeserialization");
    
    @XmlElement
-   private BooleanAttributeType invocationBatching = new BooleanAttributeType();
+   private BooleanAttributeType invocationBatching = new BooleanAttributeType("invocationBatching");
    
    @XmlElement
    private DeadlockDetectionType deadlockDetection = new DeadlockDetectionType();
@@ -138,6 +139,19 @@
             break;
       }
    }
+   
+   public void applyOverrides(Configuration overrides) {
+      OverrideConfigurationVisitor v1 =new OverrideConfigurationVisitor();
+      this.accept(v1);
+      OverrideConfigurationVisitor v2 =new OverrideConfigurationVisitor();
+      overrides.accept(v2);
+      v1.override(v2);      
+   }
+   
+   public void inject(ComponentRegistry cr) {
+      super.inject(cr);
+      this.accept(new InjectComponentRegistryVisitor());
+   }
 
    // ------------------------------------------------------------------------------------------------------------
    //   SETTERS - MAKE SURE ALL SETTERS PERFORM testImmutability()!!!
@@ -866,7 +880,7 @@
     * @configRef name="clustering",desc="Defines clustering characteristics of the cache."
     */
    @XmlJavaTypeAdapter(ClusteringTypeAdapter.class)
-   @XmlAccessorType(XmlAccessType.FIELD)
+   @XmlAccessorType(XmlAccessType.PROPERTY)
    @XmlType(propOrder={})
    public static class ClusteringType extends AbstractNamedCacheConfigurationBean {
       
@@ -1463,6 +1477,9 @@
     */
    @XmlAccessorType(XmlAccessType.PROPERTY)
    public static class BooleanAttributeType  extends AbstractNamedCacheConfigurationBean {
+      
+      @XmlTransient
+      protected final String fieldName;
      
       /** The serialVersionUID */
       private static final long serialVersionUID = 2296863404153834686L;
@@ -1470,6 +1487,19 @@
       /** @configRef desc="Toggle switch" */
       protected Boolean enabled = false;
       
+      
+      public BooleanAttributeType() {
+         fieldName= "undefined";
+      }
+
+      public BooleanAttributeType(String fieldName) {
+         this.fieldName = fieldName;
+      }
+            
+      public String getFieldName() {
+         return fieldName;
+      }
+
       @XmlAttribute
       public void setEnabled(Boolean enabled) {
          testImmutability("enabled");

Added: trunk/core/src/main/java/org/infinispan/config/OverrideConfigurationVisitor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/OverrideConfigurationVisitor.java	                        (rev 0)
+++ trunk/core/src/main/java/org/infinispan/config/OverrideConfigurationVisitor.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -0,0 +1,205 @@
+/*
+ * 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;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.infinispan.CacheException;
+import org.infinispan.config.Configuration.AsyncType;
+import org.infinispan.config.Configuration.BooleanAttributeType;
+import org.infinispan.config.Configuration.ClusteringType;
+import org.infinispan.config.Configuration.CustomInterceptorsType;
+import org.infinispan.config.Configuration.DeadlockDetectionType;
+import org.infinispan.config.Configuration.EvictionType;
+import org.infinispan.config.Configuration.ExpirationType;
+import org.infinispan.config.Configuration.HashType;
+import org.infinispan.config.Configuration.L1Type;
+import org.infinispan.config.Configuration.LockingType;
+import org.infinispan.config.Configuration.StateRetrievalType;
+import org.infinispan.config.Configuration.SyncType;
+import org.infinispan.config.Configuration.TransactionType;
+import org.infinispan.config.Configuration.UnsafeType;
+import org.infinispan.loaders.AbstractCacheStoreConfig;
+import org.infinispan.loaders.CacheLoaderConfig;
+import org.infinispan.util.ReflectionUtil;
+
+/**
+ * OverrideConfigurationVisitor breaks down fields of Configuration object to individual components
+ * and then compares them for field updates.
+ * 
+ * @author Vladimir Blagojevic
+ * @since 4.0
+ */
+public class OverrideConfigurationVisitor extends AbstractConfigurationBeanVisitor {
+
+   AsyncType asyncType = null;
+   CacheLoaderConfig cacheLoaderConfig = null;
+   CacheLoaderManagerConfig cacheLoaderManagerConfig = null;
+   ClusteringType clusteringType = null;
+   Map <String,BooleanAttributeType> bats = new HashMap<String,BooleanAttributeType>();
+
+   CustomInterceptorsType customInterceptorsType = null;
+   DeadlockDetectionType deadlockDetectionType = null;
+   EvictionType evictionType = null;
+   ExpirationType expirationType = null;
+   HashType hashType = null;
+   L1Type l1Type = null;
+   LockingType lockingType = null;
+   StateRetrievalType stateRetrievalType = null;
+   SyncType syncType = null;
+   TransactionType transactionType = null;
+   UnsafeType unsafeType = null;
+
+   public void override(OverrideConfigurationVisitor override) {
+      
+      //special handling for BooleanAttributeType
+      Set<Entry<String, BooleanAttributeType>> entrySet = override.bats.entrySet();      
+      for (Entry<String, BooleanAttributeType> entry : entrySet) {
+         BooleanAttributeType attributeType = bats.get(entry.getKey());
+         if(attributeType != null) {
+            attributeType.setEnabled(entry.getValue().enabled);
+         }
+      }
+      
+      //special handling for cache loader manager
+      overrideFields(cacheLoaderManagerConfig, override.cacheLoaderManagerConfig);
+      CacheLoaderManagerConfig config = override.cacheLoaderManagerConfig;
+      List<CacheLoaderConfig> cll2 = config.getCacheLoaderConfigs();
+      List<CacheLoaderConfig> cll1 = cacheLoaderManagerConfig.getCacheLoaderConfigs();
+
+      if (cll1.isEmpty() && !cll2.isEmpty()) {
+         cll1.addAll(cll2);
+      } else if (!cll1.isEmpty() && !cll2.isEmpty()) {
+         Iterator<CacheLoaderConfig> i1 = cll1.iterator();
+         Iterator<CacheLoaderConfig> i2 = cll2.iterator();
+         for (; i1.hasNext() && i2.hasNext();) {
+            CacheLoaderConfig l1 = i1.next();
+            CacheLoaderConfig l2 = i2.next();
+            if (l1.getCacheLoaderClassName().equals(l2.getCacheLoaderClassName())) {
+               overrideFields((AbstractConfigurationBean) l1, (AbstractConfigurationBean) l2);
+               if(l1 instanceof AbstractCacheStoreConfig && l2 instanceof AbstractCacheStoreConfig) {
+                  overrideFields(((AbstractCacheStoreConfig) l1).getSingletonStoreConfig(),
+                           ((AbstractCacheStoreConfig) l2).getSingletonStoreConfig());
+                  overrideFields(((AbstractCacheStoreConfig) l1).getAsyncStoreConfig(),
+                           ((AbstractCacheStoreConfig) l2).getAsyncStoreConfig());
+               }
+            }
+         }
+         while (i2.hasNext()) {
+            cll1.add(i2.next());
+         }
+      }
+      
+      //everything else...
+      overrideFields(asyncType, override.asyncType);
+      overrideFields(clusteringType, override.clusteringType);
+      overrideFields(deadlockDetectionType, override.deadlockDetectionType);
+      overrideFields(evictionType, override.evictionType);
+      overrideFields(expirationType, override.expirationType);
+      overrideFields(hashType, override.hashType);
+      overrideFields(l1Type, override.l1Type);
+      overrideFields(lockingType, override.lockingType);
+      overrideFields(stateRetrievalType, override.stateRetrievalType);
+      overrideFields(syncType, override.syncType);
+      overrideFields(transactionType, override.transactionType);
+      overrideFields(unsafeType, override.unsafeType);
+   }
+
+   private void overrideFields(AbstractConfigurationBean bean, AbstractConfigurationBean overrides) {
+      if (overrides != null && bean != null) {
+         // does this component have overridden fields?
+         for (String overridenField : overrides.overriddenConfigurationElements) {
+            try {
+               ReflectionUtil.setValue(bean, overridenField, ReflectionUtil.getValue(overrides,overridenField));
+            } catch (Exception e1) {
+               throw new CacheException("Could not apply value for field " + overridenField
+                        + " from instance " + overrides + " on instance " + this, e1);
+            }
+         }
+      } 
+   }
+
+   public void visitAsyncType(AsyncType bean) {
+      asyncType = bean;
+   }
+   
+   public void visitBooleanAttributeType(BooleanAttributeType bat) {
+      bats.put(bat.getFieldName(), bat);
+   }
+
+   public void visitCacheLoaderManagerConfig(CacheLoaderManagerConfig bean) {
+      cacheLoaderManagerConfig = bean;
+   }
+
+   public void visitClusteringType(ClusteringType bean) {
+      clusteringType = bean;
+   }
+
+   public void visitCustomInterceptorsType(CustomInterceptorsType bean) {
+      customInterceptorsType = bean;
+   }
+
+   public void visitDeadlockDetectionType(DeadlockDetectionType bean) {
+      deadlockDetectionType = bean;
+   }
+
+   public void visitEvictionType(EvictionType bean) {
+      evictionType = bean;
+   }
+
+   public void visitExpirationType(ExpirationType bean) {
+      expirationType = bean;
+   }
+
+   public void visitHashType(HashType bean) {
+      hashType = bean;
+   }
+
+   public void visitL1Type(L1Type bean) {
+      l1Type = bean;
+   }
+
+   public void visitLockingType(LockingType bean) {
+      lockingType = bean;
+   }
+
+   public void visitStateRetrievalType(StateRetrievalType bean) {
+      stateRetrievalType = bean;
+   }
+
+   public void visitSyncType(SyncType bean) {
+      syncType = bean;
+   }
+
+   public void visitTransactionType(TransactionType bean) {
+      transactionType = bean;
+   }
+
+   public void visitUnsafeType(UnsafeType bean) {
+      unsafeType = bean;
+   }
+}

Modified: trunk/core/src/main/java/org/infinispan/loaders/AbstractCacheStoreConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/AbstractCacheStoreConfig.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/loaders/AbstractCacheStoreConfig.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -7,8 +7,8 @@
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.*;
 import javax.xml.bind.annotation.XmlType;
 
 /**
@@ -29,80 +29,81 @@
  * @configRef name="loader",desc="Responsible for loading/storing cache data from/to an external source." 
  *
  * @author Mircea.Markus at jboss.com
+ * @author Vladimir Blagojevic
  * @since 4.0
  */
- at XmlAccessorType(XmlAccessType.FIELD)
- at XmlType(propOrder={"singletonStore","async"})
+ at XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
+ at XmlType(propOrder= {"singletonStoreConfig", "asyncStoreConfig"})
 public class AbstractCacheStoreConfig extends AbstractCacheLoaderConfig implements CacheStoreConfig {
    
    /** 
     * @configRef desc="If true, any operation that modifies the cache store (remove, clear, store...etc) won't be applied to it"
     * */
-   @XmlAttribute
+   
    protected Boolean ignoreModifications = false;
    
    /**
     *  @configRef desc="If true, fetch persistent state on state transfer"
     *  */
-   @XmlAttribute
    protected Boolean fetchPersistentState = false;
    
    /**
     *  @configRef desc="If true, purge node state on startup"
     *  */
-   @XmlAttribute
+   
    protected Boolean purgeOnStartup = false;
    
    /**
     *  @configRef desc="If true, CacheStore#purgeExpired() call will be done synchronously"
     *  */
-   @XmlAttribute
+   
    protected Boolean purgeSynchronously = false;
    
-   @XmlElement
    protected SingletonStoreConfig singletonStore = new SingletonStoreConfig();
    
-   @XmlElement
    protected AsyncStoreConfig async = new AsyncStoreConfig();
 
-   
-
-   public boolean isPurgeSynchronously() {
+   @XmlAttribute
+   public Boolean isPurgeSynchronously() {
       return purgeSynchronously;
    }
 
-   public void setPurgeSynchronously(boolean purgeSynchronously) {
+   public void setPurgeSynchronously(Boolean purgeSynchronously) {
       testImmutability("purgeSynchronously");
       this.purgeSynchronously = purgeSynchronously;
    }
 
-   public boolean isPurgeOnStartup() {
-      return purgeOnStartup;
-   }
-
-   public boolean isFetchPersistentState() {
+   @XmlAttribute
+   public Boolean isFetchPersistentState() {
       return fetchPersistentState;
    }
 
-   public void setFetchPersistentState(boolean fetchPersistentState) {
+   public void setFetchPersistentState(Boolean fetchPersistentState) {
       testImmutability("fetchPersistentState");
       this.fetchPersistentState = fetchPersistentState;
    }
 
-   public void setIgnoreModifications(boolean ignoreModifications) {
+   public void setIgnoreModifications(Boolean ignoreModifications) {
       testImmutability("ignoreModifications");
       this.ignoreModifications = ignoreModifications;
    }
 
-   public boolean isIgnoreModifications() {
+   @XmlAttribute
+   public Boolean isIgnoreModifications() {
       return ignoreModifications;
    }
+   
+   @XmlAttribute
+   public Boolean isPurgeOnStartup() {
+      return purgeOnStartup;
+   }
 
-   public void setPurgeOnStartup(boolean purgeOnStartup) {
+   public void setPurgeOnStartup(Boolean purgeOnStartup) {
       testImmutability("purgeOnStartup");
       this.purgeOnStartup = purgeOnStartup;
    }
 
+   @XmlElement(name="singletonStore")
    public SingletonStoreConfig getSingletonStoreConfig() {
       return singletonStore;
    }
@@ -112,6 +113,7 @@
       this.singletonStore = singletonStoreConfig;
    }
 
+   @XmlElement(name="async")
    public AsyncStoreConfig getAsyncStoreConfig() {
       return async;
    }

Modified: trunk/core/src/main/java/org/infinispan/loaders/CacheStoreConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/CacheStoreConfig.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/loaders/CacheStoreConfig.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -7,20 +7,21 @@
  * Defines config elements for all CacheStoreConfigs.
  *
  * @author Mircea.Markus at jboss.com
+ * @author Vladimir Blagojevic
  */
 public interface CacheStoreConfig extends CacheLoaderConfig, Cloneable {
 
-   boolean isPurgeOnStartup();
+   Boolean isPurgeOnStartup();
 
-   boolean isFetchPersistentState();
+   Boolean isFetchPersistentState();
 
-   void setFetchPersistentState(boolean fetchPersistentState);
+   void setFetchPersistentState(Boolean fetchPersistentState);
 
-   void setIgnoreModifications(boolean ignoreModifications);
+   void setIgnoreModifications(Boolean ignoreModifications);
 
-   boolean isIgnoreModifications();
+   Boolean isIgnoreModifications();
 
-   void setPurgeOnStartup(boolean purgeOnStartup);
+   void setPurgeOnStartup(Boolean purgeOnStartup);
 
    SingletonStoreConfig getSingletonStoreConfig();
 
@@ -30,7 +31,7 @@
 
    void setAsyncStoreConfig(AsyncStoreConfig asyncStoreConfig);
 
-   public boolean isPurgeSynchronously();
+   public Boolean isPurgeSynchronously();
 
-   public void setPurgeSynchronously(boolean purgeSynchronously);
+   public void setPurgeSynchronously(Boolean purgeSynchronously);
 }

Modified: trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/loaders/decorators/AsyncStoreConfig.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -23,51 +23,51 @@
  * @author Vladimir Blagojevic
  * @since 4.0
  */
- at XmlAccessorType(XmlAccessType.FIELD)
+ at XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
 public class AsyncStoreConfig extends AbstractNamedCacheConfigurationBean {
    
    /** 
     * @configRef desc="If true, modifications are stored in the cache store asynchronously."  
     * */
-   @XmlAttribute
    protected Boolean enabled = false;
   
    /** 
     * @configRef desc="Size of the thread pool whose threads are responsible for applying the modifications."
     *  */
-   @XmlAttribute
    protected Integer threadPoolSize = 1;
    
    /** 
     * @configRef desc="Lock timeout for access to map containing latest state."
     * */
    @Dynamic
-   @XmlAttribute
    protected Long mapLockTimeout = 5000L;
 
-   public boolean isEnabled() {
+   @XmlAttribute
+   public Boolean isEnabled() {
       return enabled;
    }
    
-   public void setEnabled(boolean enabled) {
+   public void setEnabled(Boolean enabled) {
       testImmutability("enabled");
       this.enabled = enabled;
    }
 
-   public int getThreadPoolSize() {
+   @XmlAttribute
+   public Integer getThreadPoolSize() {
       return threadPoolSize;
    }
 
-   public void setThreadPoolSize(int threadPoolSize) {
+   public void setThreadPoolSize(Integer threadPoolSize) {
       testImmutability("threadPoolSize");
       this.threadPoolSize = threadPoolSize;
    }
 
-   public long getMapLockTimeout() {
+   @XmlAttribute
+   public Long getMapLockTimeout() {
       return mapLockTimeout;
    }
 
-   public void setMapLockTimeout(long stateLockTimeout) {
+   public void setMapLockTimeout(Long stateLockTimeout) {
       testImmutability("mapLockTimeout");
       this.mapLockTimeout = stateLockTimeout;
    }   

Modified: trunk/core/src/main/java/org/infinispan/loaders/decorators/SingletonStoreConfig.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/loaders/decorators/SingletonStoreConfig.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/main/java/org/infinispan/loaders/decorators/SingletonStoreConfig.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -25,7 +25,7 @@
  * @author Vladimir Blagojevic
  * @since 4.0
  */
- at XmlAccessorType(XmlAccessType.FIELD)
+ at XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
 public class SingletonStoreConfig extends AbstractNamedCacheConfigurationBean {
 
    private static final long serialVersionUID = 824251894176131850L;
@@ -33,46 +33,46 @@
    /**
     *  @configRef desc="If true, the relevant cache store is turned into singleton store"
     *  */
-   @XmlAttribute
    protected Boolean enabled = false;
    
    /**
     *  @configRef desc="If true and the node becomes the coordinator, the in-memory state transfer 
     *  to the underlying cache store is initiated"
     *  */
-   @XmlAttribute
    protected Boolean pushStateWhenCoordinator = true;
    
    /**
     *  @configRef desc="If pushStateWhenCoordinator is true, the in-memory state transfer to cache store timeout"
     *  */
-   @XmlAttribute
    protected Long pushStateTimeout = 10000L;
 
-   public boolean isSingletonStoreEnabled() {
+   @XmlAttribute(name="enabled")
+   public Boolean isSingletonStoreEnabled() {
       return enabled;
    }
    
-   public void setSingletonStoreEnabled(boolean singletonStoreEnabled) {
+   public void setSingletonStoreEnabled(Boolean singletonStoreEnabled) {
       testImmutability("enabled");
       this.enabled = singletonStoreEnabled;
    }
 
 
-   public boolean isPushStateWhenCoordinator() {
+   @XmlAttribute
+   public Boolean isPushStateWhenCoordinator() {
       return pushStateWhenCoordinator;
    }
 
-   public void setPushStateWhenCoordinator(boolean pushStateWhenCoordinator) {
+   public void setPushStateWhenCoordinator(Boolean pushStateWhenCoordinator) {
       testImmutability("pushStateWhenCoordinator");
       this.pushStateWhenCoordinator = pushStateWhenCoordinator;
    }
 
-   public long getPushStateTimeout() {
+   @XmlAttribute
+   public Long getPushStateTimeout() {
       return pushStateTimeout;
    }
 
-   public void setPushStateTimeout(long pushStateTimeout) {
+   public void setPushStateTimeout(Long pushStateTimeout) {
       testImmutability("pushStateTimeout");
       this.pushStateTimeout = pushStateTimeout;
    }

Modified: trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -259,5 +259,30 @@
       assert c.getLockAcquisitionTimeout() == 20000;
       assert c.getConcurrencyLevel() == 1000;
       assert c.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
+      
+      c = defaultCfg.clone();
+      Configuration configurationWL = namedCaches.get("withLoader");
+      configurationWL.getCacheLoaderManagerConfig().setShared(true);
+      FileCacheStoreConfig clc = (FileCacheStoreConfig)configurationWL.getCacheLoaderManagerConfig().getFirstCacheLoaderConfig();
+      clc.getSingletonStoreConfig().setPushStateTimeout(254L);
+      clc.getAsyncStoreConfig().setThreadPoolSize(7);
+      
+      c.applyOverrides(configurationWL);     
+      CacheLoaderManagerConfig loaderManagerConfig = c.getCacheLoaderManagerConfig();
+      assert loaderManagerConfig.isPreload();
+      assert !loaderManagerConfig.isPassivation();
+      assert loaderManagerConfig.isShared();
+      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");
+      assert csConf.getSingletonStoreConfig().getPushStateTimeout() == 254L;
+      assert csConf.getSingletonStoreConfig().isPushStateWhenCoordinator() == true;
+      assert csConf.getAsyncStoreConfig().getThreadPoolSize() == 7;
+      assert csConf.getAsyncStoreConfig().getMapLockTimeout() == 15000;
+      assert csConf.getAsyncStoreConfig().isEnabled();
    }
 }
\ No newline at end of file

Modified: trunk/core/src/test/java/org/infinispan/loaders/decorators/SingletonStoreTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/decorators/SingletonStoreTest.java	2009-09-11 14:08:33 UTC (rev 808)
+++ trunk/core/src/test/java/org/infinispan/loaders/decorators/SingletonStoreTest.java	2009-09-14 04:45:32 UTC (rev 809)
@@ -232,7 +232,7 @@
    public void testPushStateTimedOut() throws Throwable {
       final CountDownLatch pushStateCanFinish = new CountDownLatch(1);
       SingletonStoreConfig ssdc = new SingletonStoreConfig();
-      ssdc.setPushStateTimeout(100);
+      ssdc.setPushStateTimeout(100L);
       final TestingSingletonStore mscl = new TestingSingletonStore(pushStateCanFinish, null, ssdc);
 
       Future f = Executors.newSingleThreadExecutor().submit(createActiveStatusChanger(mscl));



More information about the infinispan-commits mailing list