[jbosscache-commits] JBoss Cache SVN: r4494 - in pojo/trunk/src: main/java/org/jboss/cache/pojo/memory and 2 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Thu Sep 20 19:36:35 EDT 2007


Author: jason.greene at jboss.com
Date: 2007-09-20 19:36:35 -0400 (Thu, 20 Sep 2007)
New Revision: 4494

Added:
   pojo/trunk/src/main/java/org/jboss/cache/pojo/util/Instantiator.java
   pojo/trunk/src/main/java/org/jboss/cache/pojo/util/PrivilegedCode.java
   pojo/trunk/src/test/java/org/jboss/cache/pojo/NoZeroArgConstructorTest.java
Modified:
   pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
   pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CachedType.java
   pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/FieldPersistentReference.java
   pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/MethodPersistentReference.java
Log:
PCACHE-3 Add support for objects with no-arg constructors
PCACHE-4 Use privileged actions


Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	2007-09-20 19:01:31 UTC (rev 4493)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -26,6 +26,8 @@
 import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
 import org.jboss.cache.pojo.memory.FieldPersistentReference;
 import org.jboss.cache.pojo.util.AopUtil;
+import org.jboss.cache.pojo.util.Instantiator;
+import org.objenesis.ObjenesisStd;
 
 /**
  * Handling the advised pojo operations. No consideration of object graph here.
@@ -49,20 +51,13 @@
       util_ = util;
    }
 
-   public Object get(Fqn fqn, Class clazz, PojoInstance pojoInstance)
+   public Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance)
          throws CacheException
    {
       CachedType type = pCache_.getCachedType(clazz);
-      Object obj = null;
-      try
-      {
-         obj = clazz.newInstance();
-         // TODO Need to populate the object from the cache as well.
-      }
-      catch (Exception e)
-      {
-    	  throw new CacheException("failed creating instance of " + clazz.getName(), e);
-      }
+      Object obj =Instantiator.newInstance(clazz);
+
+      // TODO Need to populate the object from the cache as well.
       // Insert interceptor at runtime
       InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
       CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
@@ -71,7 +66,7 @@
       return obj;
    }
 
-   void put(Fqn fqn, Fqn referencingFqn, Object obj) throws CacheException
+   void put(Fqn<?> fqn, Fqn<?> referencingFqn, Object obj) throws CacheException
    {
       CachedType type = pCache_.getCachedType(obj.getClass());
       // We have a clean slate then.
@@ -155,7 +150,7 @@
       }
    }
 
-   Object remove(Fqn fqn, Object result, Class clazz) throws CacheException
+   Object remove(Fqn<?> fqn, Object result, Class<?> clazz) throws CacheException
    {
       CachedType type = pCache_.getCachedType(clazz);
       InstanceAdvisor advisor = ((Advised) result)._getInstanceAdvisor();

Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CachedType.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CachedType.java	2007-09-20 19:01:31 UTC (rev 4493)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CachedType.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -18,6 +18,7 @@
 import org.jboss.aop.joinpoint.FieldInvocation;
 import org.jboss.cache.pojo.memory.FieldPersistentReference;
 import org.jboss.cache.pojo.memory.PersistentReference;
+import org.jboss.cache.pojo.util.PrivilegedCode;
 
 /**
  * Represent a cached object type, e.g., whether it is <b>primitive</b> or not.
@@ -82,7 +83,7 @@
 
    private static boolean isImmediate(Class clazz)
    {
-	   // Treat enums as a simple type since they serialize to a simple string
+      // Treat enums as a simple type since they serialize to a simple string
       return immediates.contains(clazz) || Enum.class.isAssignableFrom(clazz);
    }
 
@@ -210,7 +211,7 @@
          Field f = classFields[i];
          if (isNonReplicatable(f)) continue;
 
-         f.setAccessible(true);
+         PrivilegedCode.setAccessible(f);
 
          FieldPersistentReference persistentRef = new FieldPersistentReference(f, PersistentReference.REFERENCE_SOFT);
 

Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/FieldPersistentReference.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/FieldPersistentReference.java	2007-09-20 19:01:31 UTC (rev 4493)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/FieldPersistentReference.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -24,6 +24,8 @@
 
 import java.lang.reflect.Field;
 
+import org.jboss.cache.pojo.util.PrivilegedCode;
+
 /**
  * Creates a persistentReference for Fields
  *
@@ -48,7 +50,7 @@
       if ((returnValue = internalGet()) != null) return returnValue;
 
       Field field = getMappedClass().getDeclaredField(name);
-      field.setAccessible(true);
+      PrivilegedCode.setAccessible(field);
       buildReference(field);
       return field;
    }

Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/MethodPersistentReference.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/MethodPersistentReference.java	2007-09-20 19:01:31 UTC (rev 4493)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/memory/MethodPersistentReference.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -24,6 +24,8 @@
 
 import java.lang.reflect.Method;
 
+import org.jboss.cache.pojo.util.PrivilegedCode;
+
 /**
  * A reference to a field.
  * In case the reference is released, the reference will be reconstructed
@@ -50,7 +52,7 @@
       if ((returnValue = internalGet()) != null) return returnValue;
 
       Method aMethod = getMappedClass().getDeclaredMethod(name, getArguments());
-      aMethod.setAccessible(true);
+      PrivilegedCode.setAccessible(aMethod);
       buildReference(aMethod);
       return aMethod;
    }

Added: pojo/trunk/src/main/java/org/jboss/cache/pojo/util/Instantiator.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/util/Instantiator.java	                        (rev 0)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/util/Instantiator.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -0,0 +1,94 @@
+package org.jboss.cache.pojo.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.jboss.cache.CacheException;
+
+public class Instantiator
+{
+   private static abstract class Allocator
+   {
+      public Object allocate(Class<?> c) throws Exception
+      {
+         Constructor<?> constructor = c.getDeclaredConstructor();
+         PrivilegedCode.setAccessible(constructor);
+         return constructor.newInstance();
+      }
+   }
+
+   private static final Allocator allocator;
+
+   static
+   {
+      // Currently only Sun and Mac JVMs are suported
+      Allocator a = createUnsafeAllocator();
+      allocator = a != null ? a : createDefaultAllocator();
+   }
+
+
+   public static Object newInstance(Class<?> c) throws CacheException
+   {
+      try
+      {
+         return allocator.allocate(c);
+      }
+      catch (Exception e)
+      {
+         throw new CacheException("failed creating instance of " + c.getName(), e);
+      }
+   }
+
+   private static Allocator createUnsafeAllocator()
+   {
+      Allocator allocator = null;
+      try
+      {
+         final Class<?> clazz = Class.forName("sun.misc.Unsafe");
+         final Field field = clazz.getDeclaredField("theUnsafe");
+         PrivilegedCode.setAccessible(field);
+         final Object object = field.get(null);
+         final Method method = clazz.getMethod("allocateInstance", Class.class);
+
+         allocator = new Allocator()
+         {
+            public Object allocate(Class<?> c) throws Exception
+            {
+               try
+               {
+                  return super.allocate(c);
+               }
+               catch (Exception e)
+               {
+               }
+               return method.invoke(object, c);
+            }
+         };
+      }
+      catch (Exception e)
+      {
+      }
+
+      return allocator;
+   }
+
+   private static Allocator createDefaultAllocator()
+   {
+      return new Allocator()
+      {
+
+         public Object allocate(Class<?> c) throws Exception
+         {
+            try
+            {
+               return super.allocate(c);
+            }
+            catch (Exception e)
+            {
+               throw new IllegalArgumentException("A noarg constructor is required on this JVM", e);
+            }
+         }
+      };
+   }
+}

Added: pojo/trunk/src/main/java/org/jboss/cache/pojo/util/PrivilegedCode.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/util/PrivilegedCode.java	                        (rev 0)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/util/PrivilegedCode.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -0,0 +1,28 @@
+package org.jboss.cache.pojo.util;
+
+import java.lang.reflect.AccessibleObject;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Performs privileged actions
+ *
+ * @author Jason T. Greene
+ */
+public class PrivilegedCode
+{
+   public static void setAccessible(final AccessibleObject object)
+   {
+      if (object.isAccessible())
+         return;
+
+      AccessController.doPrivileged(new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            object.setAccessible(true);
+            return null;
+         }
+      });
+   }
+}

Added: pojo/trunk/src/test/java/org/jboss/cache/pojo/NoZeroArgConstructorTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/NoZeroArgConstructorTest.java	                        (rev 0)
+++ pojo/trunk/src/test/java/org/jboss/cache/pojo/NoZeroArgConstructorTest.java	2007-09-20 23:36:35 UTC (rev 4494)
@@ -0,0 +1,100 @@
+package org.jboss.cache.pojo;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
+import org.jboss.cache.pojo.annotation.Replicable;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+/**
+ * Verifies that objects can be constructed without a public zero-arg constructor.
+ *
+ * @author Jason T. Greene
+ */
+ at Test(groups = {"functional"})
+public class NoZeroArgConstructorTest
+{
+   Log log = LogFactory.getLog(NoZeroArgConstructorTest.class);
+   PojoCache cache, cache1;
+
+   @BeforeTest(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log.info("setUp() ....");
+      boolean toStart = false;
+      cache = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache.start();
+      cache1 = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache1.start();
+   }
+
+   @AfterTest(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache.stop();
+      cache1.stop();
+   }
+
+   @Replicable
+   public static class PrivateConstructor
+   {
+      private int x;
+      private PrivateConstructor()
+      {
+      }
+
+      public void setX(int x)
+      {
+         this.x = x;
+      }
+
+      public int getX()
+      {
+         return x;
+      }
+   }
+
+   @Replicable
+   public static class TwoArgConstructor
+   {
+      private int x;
+      public TwoArgConstructor(double one, int two)
+      {
+      }
+
+      public void setX(int x)
+      {
+         this.x = x;
+      }
+
+      public int getX()
+      {
+         return x;
+      }
+   }
+
+   public void testPrivateConstructor()
+   {
+      PrivateConstructor priv = new PrivateConstructor();
+      priv.setX(5);
+      cache.attach("/foo/private", priv);
+      PrivateConstructor priv2 = (PrivateConstructor) cache1.find("/foo/private");
+      AssertJUnit.assertNotNull("Object not found", priv2);
+      AssertJUnit.assertEquals(priv.getX(),  priv2.getX());
+   }
+
+   public void testTwoArgConstructor()
+   {
+      TwoArgConstructor cons = new TwoArgConstructor(1.0, 1);
+      cons.setX(5);
+      cache.attach("/foo/twoarg", cons);
+      TwoArgConstructor cons2 = (TwoArgConstructor) cache1.find("/foo/twoarg");
+      AssertJUnit.assertNotNull("Object not found", cons2);
+      AssertJUnit.assertEquals(cons.getX(),  cons2.getX());
+   }
+
+}
\ No newline at end of file




More information about the jbosscache-commits mailing list