[jbosscache-commits] JBoss Cache SVN: r5323 - in core/trunk/src: main/java/org/jboss/cache/marshall and 1 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Thu Feb 7 10:03:42 EST 2008


Author: manik.surtani at jboss.com
Date: 2008-02-07 10:03:42 -0500 (Thu, 07 Feb 2008)
New Revision: 5323

Added:
   core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingJDBCTest.java
Modified:
   core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java
   core/trunk/src/main/java/org/jboss/cache/loader/FileCacheLoader.java
   core/trunk/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderConfig.java
   core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
   core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingTest.java
Log:
JBCACHE-1287 -  CacheLoader load operations cannot deserialize types not visible to cache

Modified: core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java	2008-02-07 14:14:03 UTC (rev 5322)
+++ core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -12,6 +12,7 @@
 import org.jboss.cache.CacheSPI;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.Modification;
+import org.jboss.cache.Region;
 import org.jboss.cache.RegionManager;
 import org.jboss.cache.buddyreplication.BuddyManager;
 import org.jboss.cache.marshall.Marshaller;
@@ -173,6 +174,69 @@
       this.regionManager = regionManager;
    }
 
+   protected void regionAwareMarshall(Fqn fqn, Object toMarshall) throws Exception
+   {
+      Region r = regionManager == null ? null : regionManager.getRegion(fqn, Region.Type.MARSHALLING, false);
+      ClassLoader originalClassLoader = null;
+      boolean needToResetLoader = false;
+      Thread current = null;
+
+      if (r != null)
+      {
+         // set the region's class loader as the thread's context classloader
+         needToResetLoader = true;
+         current = Thread.currentThread();
+         originalClassLoader = current.getContextClassLoader();
+         current.setContextClassLoader(r.getClassLoader());
+      }
+
+      try
+      {
+         doMarshall(fqn, toMarshall);
+      }
+      finally
+      {
+         if (needToResetLoader) current.setContextClassLoader(originalClassLoader);
+      }
+   }
+
+   protected Object regionAwareUnmarshall(Fqn fqn, Object toUnmarshall) throws Exception
+   {
+      Region r = regionManager == null ? null : regionManager.getRegion(fqn, Region.Type.MARSHALLING, false);
+      ClassLoader originalClassLoader = null;
+      boolean needToResetLoader = false;
+      Thread current = null;
+
+      if (r != null)
+      {
+         // set the region's class loader as the thread's context classloader
+         needToResetLoader = true;
+         current = Thread.currentThread();
+         originalClassLoader = current.getContextClassLoader();
+         current.setContextClassLoader(r.getClassLoader());
+      }
+
+      try
+      {
+         return doUnmarshall(fqn, toUnmarshall);
+      }
+      finally
+      {
+         if (needToResetLoader) current.setContextClassLoader(originalClassLoader);
+      }
+   }
+
+   protected void doMarshall(Fqn fqn, Object toMarshall) throws Exception
+   {
+      throw new RuntimeException("Should be overridden");
+   }
+
+   protected Object doUnmarshall(Fqn fqn, Object toUnmarshall) throws Exception
+   {
+      throw new RuntimeException("Should be overridden");
+   }
+
+
    /**
     * Do a preorder traversal: visit the node first, then the node's children
     *

Modified: core/trunk/src/main/java/org/jboss/cache/loader/FileCacheLoader.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/FileCacheLoader.java	2008-02-07 14:14:03 UTC (rev 5322)
+++ core/trunk/src/main/java/org/jboss/cache/loader/FileCacheLoader.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -422,7 +422,8 @@
       Map m = null;
       try
       {
-         m = (Map) unmarshall(child);
+         //m = (Map) unmarshall(child);
+         m = (Map) regionAwareUnmarshall(fqn, child);
       }
       catch (FileNotFoundException fnfe)
       {
@@ -434,6 +435,13 @@
 
    protected void storeAttributes(Fqn fqn, Map attrs) throws Exception
    {
+      regionAwareMarshall(fqn, attrs);
+   }
+
+   @Override
+   protected void doMarshall(Fqn fqn, Object toMarshall) throws Exception
+   {
+      Map attrs = (Map) toMarshall;
       File f = getDirectory(fqn, true);
       File child = new File(f, DATA);
       if (!child.exists())
@@ -451,10 +459,23 @@
             throw new IOException("Unable to create file: " + child);
          }
       }
+      FileOutputStream fileOut = new FileOutputStream(child);
+      ObjectOutputStream output = new ObjectOutputStream(fileOut);
+      getMarshaller().objectToObjectStream(attrs, output);
+      output.close();
+   }
 
-      marshall(attrs, child);
+   @Override
+   protected Object doUnmarshall(Fqn fqn, Object fromFile) throws Exception
+   {
+      FileInputStream fileIn = new FileInputStream((File) fromFile);
+      ObjectInputStream input = new MarshalledValueInputStream(fileIn);
+      Object unmarshalledObj = getMarshaller().objectFromObjectStream(input);
+      input.close();
+      return unmarshalledObj;
    }
 
+
    protected boolean isCharacterPortableLocation(String fileAbsolutePath)
    {
       Matcher matcher = PATH_PATTERN.matcher(fileAbsolutePath);
@@ -498,21 +519,4 @@
 
       return true;
    }
-
-   protected Object unmarshall(File from) throws Exception
-   {
-      FileInputStream fileIn = new FileInputStream(from);
-      ObjectInputStream input = new MarshalledValueInputStream(fileIn);
-      Object unmarshalledObj = getMarshaller().objectFromObjectStream(input);
-      input.close();
-      return unmarshalledObj;
-   }
-
-   protected void marshall(Object obj, File to) throws Exception
-   {
-      FileOutputStream fileOut = new FileOutputStream(to);
-      ObjectOutputStream output = new ObjectOutputStream(fileOut);
-      getMarshaller().objectToObjectStream(obj, output);
-      output.close();
-   }
 }

Modified: core/trunk/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderConfig.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderConfig.java	2008-02-07 14:14:03 UTC (rev 5322)
+++ core/trunk/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderConfig.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -15,60 +15,65 @@
 public class JDBCCacheLoaderConfig extends AdjListJDBCCacheLoaderConfig
 {
 
-    private static final long serialVersionUID = -8371846151643130271L;
+   private static final long serialVersionUID = -8371846151643130271L;
 
-    private static final Log log = LogFactory.getLog(JDBCCacheLoaderConfig.class);
+   private static final Log log = LogFactory.getLog(JDBCCacheLoaderConfig.class);
 
-    private String deleteNode;
-    private String recursiveChildren;
-    private String nodeCountSql;
+   private String deleteNode;
+   private String recursiveChildren;
+   private String nodeCountSql;
 
 
-    public JDBCCacheLoaderConfig(IndividualCacheLoaderConfig base)
-    {
+   public JDBCCacheLoaderConfig(IndividualCacheLoaderConfig base)
+   {
       super(base);
       setClassName(JDBCCacheLoader.class.getName());
-    }
+   }
 
+   public JDBCCacheLoaderConfig()
+   {
+      setClassName(JDBCCacheLoader.class.getName());
+   }
 
-    public void setProperties(Properties props)
-    {
-        super.setProperties(props);
-        String sqlConcat = props.getProperty("cache.jdbc.sql-concat");
-        if (sqlConcat == null) {
-            log.info("Missiing JDBCCacheLoader config 'cache.jdbc.sql-concat', using default value:'concat(1,2)'");
-            sqlConcat = "concat(1,2)";
-        }
-        String startingWith = sqlConcat.replace('1', '?').replace("2", "'%'"); //concat(?, '%')
-        String appendSepparator = sqlConcat.replace("1", fqnColumn).replace("2", "'/'"); //concat(fqnColumn, '/')
-        deleteNode = "delete from " + table + " where " + appendSepparator + " like " + startingWith;
-        recursiveChildren = "select " + fqnColumn + "," + nodeColumn + " from " + table + " where " + appendSepparator + " like " + startingWith;
-        nodeCountSql = "select count(*) from " + table;
-    }
+   public void setProperties(Properties props)
+   {
+      super.setProperties(props);
+      String sqlConcat = props.getProperty("cache.jdbc.sql-concat");
+      if (sqlConcat == null)
+      {
+         log.info("Missiing JDBCCacheLoader config 'cache.jdbc.sql-concat', using default value:'concat(1,2)'");
+         sqlConcat = "concat(1,2)";
+      }
+      String startingWith = sqlConcat.replace('1', '?').replace("2", "'%'"); //concat(?, '%')
+      String appendSepparator = sqlConcat.replace("1", fqnColumn).replace("2", "'/'"); //concat(fqnColumn, '/')
+      deleteNode = "delete from " + table + " where " + appendSepparator + " like " + startingWith;
+      recursiveChildren = "select " + fqnColumn + "," + nodeColumn + " from " + table + " where " + appendSepparator + " like " + startingWith;
+      nodeCountSql = "select count(*) from " + table;
+   }
 
 
-    /**
-     * Returns the sql string for removing a node and all its children.
-     */
-    public String getDeleteNodeSql()
-    {
-        return deleteNode;
-    }
+   /**
+    * Returns the sql string for removing a node and all its children.
+    */
+   public String getDeleteNodeSql()
+   {
+      return deleteNode;
+   }
 
-    /**
-     * Returns an sql that will return a node and all its children.
-     */
-    public String getRecursiveChildrenSql()
-    {
-        return recursiveChildren;
-    }
+   /**
+    * Returns an sql that will return a node and all its children.
+    */
+   public String getRecursiveChildrenSql()
+   {
+      return recursiveChildren;
+   }
 
 
-    /**
-     * Returns an sql that will count all the persisted node.
-     */
-    public String getNodeCountSql()
-    {
-        return nodeCountSql;
-    }
+   /**
+    * Returns an sql that will count all the persisted node.
+    */
+   public String getNodeCountSql()
+   {
+      return nodeCountSql;
+   }
 }

Modified: core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java	2008-02-07 14:14:03 UTC (rev 5322)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -529,12 +529,13 @@
          ClassLoader old = currentThread.getContextClassLoader();
          try
          {
-            currentThread.setContextClassLoader(loader);
+            // only do this if we haven't already set a context class loader elsewhere.
+            if (old == null) currentThread.setContextClassLoader(loader);
             return unmarshallObject(in, refMap);
          }
          finally
          {
-            currentThread.setContextClassLoader(old);
+            if (old == null) currentThread.setContextClassLoader(null);
          }
       }
    }

Copied: core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingJDBCTest.java (from rev 5322, core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingTest.java)
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingJDBCTest.java	                        (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingJDBCTest.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -0,0 +1,153 @@
+package org.jboss.cache.marshall;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Region;
+import org.jboss.cache.config.CacheLoaderConfig;
+import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.EvictionConfig;
+import org.jboss.cache.config.EvictionRegionConfig;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.eviction.LRUPolicy;
+import org.jboss.cache.loader.JDBCCacheLoaderConfig;
+import org.jboss.cache.misc.TestingUtil;
+import static org.testng.AssertJUnit.assertEquals;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Tests marshalling/unmarshalling during cache loader operations involving types
+ * not visible to the cache's default classloader.
+ *
+ * @author <a href="mailto:brian.stansberry at jboss.org">Brian Stansberry</a>
+ * @since 2.1.0
+ */
+ at Test(groups = "functional")
+public class CacheLoaderMarshallingJDBCTest extends RegionBasedMarshallingTestBase
+{
+   private static final String className = "org.jboss.cache.marshall.MyUUID";
+
+   private Cache<Object, Object> cache;
+   private Fqn fqn = Fqn.fromString("/a");
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      originalClassLoader = Thread.currentThread().getContextClassLoader();
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown()
+   {
+      resetContextClassLoader();
+      TestingUtil.killCaches(cache);
+   }
+
+   @Override
+   protected ClassLoader getClassLoader()
+   {
+      String[] includesClasses = {className};
+      String[] excludesClasses = {};
+      ClassLoader cl = Thread.currentThread().getContextClassLoader();
+      return new SelectedClassnameClassLoader(includesClasses, excludesClasses, cl);
+   }
+
+   public void testCacheLoaderMarshalling() throws Exception
+   {
+      cacheLoaderMarshallingTest(false);
+   }
+
+   public void testCacheLoaderRegionBasedMarshalling() throws Exception
+   {
+      cacheLoaderMarshallingTest(true);
+   }
+
+   private void cacheLoaderMarshallingTest(boolean useRegionBased) throws Exception
+   {
+      cache = createCache(useRegionBased);
+      cache.start();
+
+      FooClassLoader loader = new FooClassLoader(originalClassLoader);
+
+      if (useRegionBased)
+      {
+         Region r = cache.getRegion(Fqn.ROOT, true);
+         r.registerContextClassLoader(loader);
+         r.activate();
+      }
+
+      Class clazz = loader.loadFoo();
+      Object obj = clazz.newInstance();
+
+      Thread.currentThread().setContextClassLoader(loader);
+      cache.put(fqn, "key", obj);
+
+      this.resetContextClassLoader();
+      cache.evict(fqn);
+
+      Thread.currentThread().setContextClassLoader(loader);
+      assertEquals(obj, cache.get(fqn, "key"));
+   }
+
+   private Cache createCache(boolean useRegionBased) throws Exception
+   {
+      Properties prop = getProperties();
+
+      // ensure cleanup after each test
+      prop.setProperty("cache.jdbc.table.drop", "true");
+
+      Cache cache = new DefaultCacheFactory<Object, Object>().createCache(false);
+      Configuration config = cache.getConfiguration();
+      config.setUseRegionBasedMarshalling(useRegionBased);
+      config.setInactiveOnStartup(useRegionBased);
+
+      EvictionConfig ec = new EvictionConfig();
+      ec.setDefaultEvictionPolicyClass(LRUPolicy.class.getName());
+      ec.setWakeupIntervalSeconds(1000);  // a long time; really disabled
+      EvictionRegionConfig erc = new EvictionRegionConfig();
+      erc.setRegionFqn(Fqn.ROOT);
+      erc.setRegionName("_default_");
+      LRUConfiguration epc = new LRUConfiguration();
+      epc.setMaxNodes(1000);
+      epc.setTimeToLiveSeconds(1000);
+      erc.setEvictionPolicyConfig(epc);
+      List<EvictionRegionConfig> ercs = new ArrayList<EvictionRegionConfig>();
+      ercs.add(erc);
+      ec.setEvictionRegionConfigs(ercs);
+      config.setEvictionConfig(ec);
+
+      CacheLoaderConfig clc = new CacheLoaderConfig();
+      clc.setPassivation(true);
+      clc.setShared(false);
+      JDBCCacheLoaderConfig jdbc_clc = new JDBCCacheLoaderConfig();
+      jdbc_clc.setProperties(prop);
+
+      clc.setIndividualCacheLoaderConfigs(Collections.<IndividualCacheLoaderConfig>singletonList(jdbc_clc));
+      config.setCacheLoaderConfig(clc);
+
+      return cache;
+   }
+
+   private Properties getProperties() throws Exception
+   {
+      Properties properties = new Properties();
+      try
+      {
+         properties.load(this.getClass().getClassLoader().getResourceAsStream("cache-jdbc.properties"));
+         return properties;
+      }
+      catch (Exception e)
+      {
+         throw new Exception("Error loading jdbc properties ", e);
+      }
+   }
+
+}
\ No newline at end of file

Modified: core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingTest.java	2008-02-07 14:14:03 UTC (rev 5322)
+++ core/trunk/src/test/java/org/jboss/cache/marshall/CacheLoaderMarshallingTest.java	2008-02-07 15:03:42 UTC (rev 5323)
@@ -1,50 +1,49 @@
 package org.jboss.cache.marshall;
 
-import static org.testng.AssertJUnit.assertEquals;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
 import org.jboss.cache.Cache;
-import org.jboss.cache.CacheSPI;
 import org.jboss.cache.DefaultCacheFactory;
 import org.jboss.cache.Fqn;
 import org.jboss.cache.Region;
 import org.jboss.cache.config.CacheLoaderConfig;
+import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
 import org.jboss.cache.config.Configuration;
 import org.jboss.cache.config.EvictionConfig;
 import org.jboss.cache.config.EvictionRegionConfig;
-import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
 import org.jboss.cache.eviction.LRUConfiguration;
 import org.jboss.cache.eviction.LRUPolicy;
 import org.jboss.cache.loader.FileCacheLoaderConfig;
 import org.jboss.cache.misc.TestingUtil;
+import static org.testng.AssertJUnit.assertEquals;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
- * Tests marshalling/unmarshalling during cache loader operations involving types 
+ * Tests marshalling/unmarshalling during cache loader operations involving types
  * not visible to the cache's default classloader.
  *
  * @author <a href="mailto:brian.stansberry at jboss.org">Brian Stansberry</a>
  * @since 2.1.0
  */
- at Test(groups = {"functional", "jgroups"})
+ at Test(groups = "functional")
 public class CacheLoaderMarshallingTest extends RegionBasedMarshallingTestBase
 {
    private static final String tmpDir = System.getProperty("java.io.tmpdir") + File.separatorChar + "CacheLoaderMarshallingTest";
-   
+
    private static final String className = "org.jboss.cache.marshall.MyUUID";
-   
+
    private Cache<Object, Object> cache;
    private Fqn fqn = Fqn.fromString("/a");
 
    @BeforeMethod(alwaysRun = true)
    protected void setUp() throws Exception
    {
-      originalClassLoader = Thread.currentThread().getContextClassLoader();      
+      originalClassLoader = Thread.currentThread().getContextClassLoader();
    }
 
    @AfterMethod(alwaysRun = true)
@@ -52,7 +51,7 @@
    {
       resetContextClassLoader();
       TestingUtil.killCaches(cache);
-      
+
       File f = new File(tmpDir);
       if (f.exists())
          if (!f.delete())
@@ -67,51 +66,51 @@
       ClassLoader cl = Thread.currentThread().getContextClassLoader();
       return new SelectedClassnameClassLoader(includesClasses, excludesClasses, cl);
    }
-   
+
    public void testCacheLoaderMarshalling() throws Exception
    {
       cacheLoaderMarshallingTest(false);
    }
-   
+
    public void testCacheLoaderRegionBasedMarshalling() throws Exception
    {
       cacheLoaderMarshallingTest(true);
    }
-   
+
    private void cacheLoaderMarshallingTest(boolean useRegionBased) throws Exception
    {
       cache = createCache(useRegionBased);
       cache.start();
-      
+
       FooClassLoader loader = new FooClassLoader(originalClassLoader);
-      
+
       if (useRegionBased)
       {
          Region r = cache.getRegion(Fqn.ROOT, true);
          r.registerContextClassLoader(loader);
          r.activate();
       }
-      
+
       Class clazz = loader.loadFoo();
       Object obj = clazz.newInstance();
-      
+
       Thread.currentThread().setContextClassLoader(loader);
       cache.put(fqn, "key", obj);
-      
+
       this.resetContextClassLoader();
       cache.evict(fqn);
-      
+
       Thread.currentThread().setContextClassLoader(loader);
       assertEquals(obj, cache.get(fqn, "key"));
    }
-   
+
    private Cache createCache(boolean useRegionBased)
    {
-      Cache cache = (CacheSPI<Object, Object>) new DefaultCacheFactory().createCache(false);
+      Cache cache = new DefaultCacheFactory<Object, Object>().createCache(false);
       Configuration config = cache.getConfiguration();
       config.setUseRegionBasedMarshalling(useRegionBased);
       config.setInactiveOnStartup(useRegionBased);
-      
+
       EvictionConfig ec = new EvictionConfig();
       ec.setDefaultEvictionPolicyClass(LRUPolicy.class.getName());
       ec.setWakeupIntervalSeconds(1000);  // a long time; really disabled
@@ -126,17 +125,16 @@
       ercs.add(erc);
       ec.setEvictionRegionConfigs(ercs);
       config.setEvictionConfig(ec);
-      
+
       CacheLoaderConfig clc = new CacheLoaderConfig();
       clc.setPassivation(true);
       clc.setShared(false);
       FileCacheLoaderConfig fclc = new FileCacheLoaderConfig();
       fclc.setLocation(tmpDir);
-      List<IndividualCacheLoaderConfig> clcs = new ArrayList<IndividualCacheLoaderConfig>();
-      clcs.add(fclc);
-      clc.setIndividualCacheLoaderConfigs(clcs);
+
+      clc.setIndividualCacheLoaderConfigs(Collections.<IndividualCacheLoaderConfig>singletonList(fclc));
       config.setCacheLoaderConfig(clc);
-      
+
       return cache;
    }
 




More information about the jbosscache-commits mailing list