[jboss-cvs] JBossAS SVN: r99279 - in projects/jboss-classpool/trunk/classpool/src: main/java/org/jboss/classpool/domain and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jan 12 07:53:33 EST 2010


Author: kabir.khan at jboss.com
Date: 2010-01-12 07:53:31 -0500 (Tue, 12 Jan 2010)
New Revision: 99279

Added:
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java
   projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java
   projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java
   projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java
Modified:
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java
   projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java
Log:
[JBREFLECT-92] Add caching to classpools and domains

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/AbstractParentDelegationStrategy.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -100,4 +100,9 @@
       }
       this.domain = domain;
    }
+
+   public int getParentModCount()
+   {
+      return parent.getModCount();
+   }
 }

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPool.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -162,7 +162,8 @@
             logger.trace(classname + " could not be found from " + this, e);
 
          throw e;
-}   }
+      }   
+   }
    
    @Override
    public CtClass get0(String classname, boolean useCache) throws NotFoundException

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/BaseClassPoolDomain.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -23,6 +23,7 @@
 
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -47,7 +48,11 @@
    private final ParentDelegationStrategy parentDelegationStrategy;
    
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
-
+   
+   private volatile int modCount;
+   
+   private volatile int parentModCount;
+   
    public BaseClassPoolDomain(String domainName, ClassPoolDomain parent, boolean parentFirst)
    {
       this(domainName, 
@@ -63,6 +68,7 @@
       this.domainName = domainName;
       this.parentDelegationStrategy = parentDelegationStrategy;
       parentDelegationStrategy.setDomain(this);
+      this.parentModCount = parentDelegationStrategy.getParentModCount();
       if (logger.isTraceEnabled()) logger.trace("Created " + this + " parentDelegationStrategy:" + parentDelegationStrategy);
    }
    
@@ -75,6 +81,8 @@
          {
             if (logger.isTraceEnabled()) logger.trace(this + " adding pool " + pool);
             delegatingPools.add(pool);
+            parentModCount = parentDelegationStrategy.getParentModCount();
+            modCount++;
          }
       }
       finally
@@ -89,7 +97,11 @@
       try
       {
          if (logger.isTraceEnabled()) logger.trace(this + " removing pool " + pool);
-         delegatingPools.remove(pool);
+         if (delegatingPools.remove(pool))
+         {
+            parentModCount = parentDelegationStrategy.getParentModCount();
+            modCount++;
+         }
       }
       finally
       {
@@ -97,9 +109,36 @@
       }
    }
 
+   public int getModCount()
+   {
+      //Check if the parent mod count has changed (pool was added/removed in parent)
+      System.out.println(domainName + " " + parentModCount + ":" + parentDelegationStrategy.getParentModCount());
+      if (parentModCount < parentDelegationStrategy.getParentModCount())
+      {
+         lockWrite();
+         try
+         {
+            int parentCount = parentDelegationStrategy.getParentModCount();
+            if (parentCount > parentModCount)
+            {
+               this.parentModCount = parentCount; 
+               return ++modCount;
+            }
+         }
+         finally
+         {
+            unlockWrite();
+         }
+      }
+      
+      return modCount;
+   }
+
+
    public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, boolean create)
    {
       boolean trace = logger.isTraceEnabled();
+      
       String resourceName = ClassLoaderUtils.getResourceName(classname);
       
       CtClass clazz = getCachedOrCreate(initiatingPool, classname, resourceName, create, trace);
@@ -108,6 +147,7 @@
       {
          clazz = getCachedOrCreateFromPoolParent(initiatingPool, classname, create, trace);
       }
+      
       return clazz;
    }
    
@@ -190,4 +230,5 @@
    {
       lock.writeLock().unlock();
    }
+
 }

Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCache.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,72 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.classpool.base;
+
+import javassist.CtClass;
+
+import org.jboss.util.CachePolicy;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class CtClassCache
+{
+   private final CachePolicy policy;
+   
+   private volatile int viewId;
+   
+   CtClassCache(CachePolicy policy)
+   {
+      this.policy = policy;
+   }
+   
+   public void put(String classname, CtClass clazz)
+   {
+      synchronized (policy)
+      {
+         //Something strange is going on with the policy, sometimes it says duplicate entries even when I test with a peek/get, so always remove the existing entry
+         policy.remove(classname);
+         policy.insert(classname, clazz);
+      }
+   }
+   
+   public CtClass get(String classname, int viewId)
+   {
+      if (viewId != this.viewId)
+      {
+         synchronized(policy)
+         {
+            invalidate();
+            if (viewId > this.viewId)
+               this.viewId = viewId;
+         }
+      }
+      return (CtClass)policy.get(classname);
+   }
+   
+   public void invalidate()
+   {
+      policy.flush();
+   }
+}

Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/CtClassCacheFactory.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,218 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.classpool.base;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Modifier;
+import java.util.Properties;
+
+import org.jboss.logging.Logger;
+import org.jboss.util.CachePolicy;
+import org.jboss.util.LRUCachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class CtClassCacheFactory
+{
+   private static final Logger log = Logger.getLogger(Logger.class);
+   
+   public static final String POLICY_CLASS = "org.jboss.classpool.policy";
+   
+   public static final String TIMED_POLICY_LIFETIME = "org.jboss.classpool.policy.lifetime";
+   
+   public static final String TIMED_POLICY_RESOLUTION = "org.jboss.classpool.policy.resolution";
+   
+   public static final String LRU_POLICY_MIN = "org.jboss.classpool.policy.min";
+   
+   public static final String LRU_POLICY_MAX = "org.jboss.classpool.policy.max";
+   
+   public static final int DEFAULT_TIMED_POLICY_LIFETIME = 200;
+   
+   public static final int DEFAULT_TIMED_POLICY_RESOLUTION = 3;
+   
+   public static final int DEFAULT_LRU_POLICY_MIN = 10;
+   
+   public static final int DEFAULT_LRU_POLICY_MAX = 100;
+   
+   private volatile Class<? extends CachePolicy> policyClass;
+   
+   private volatile int lifetime;
+   
+   private volatile int resolution;
+   
+   private volatile int min;
+   
+   private volatile int max;
+   
+   public static CtClassCacheFactory createFromProperties()
+   {
+      return createFromProperties(System.getProperties());
+   }
+   
+   public static CtClassCacheFactory createFromProperties(Properties properties)
+   {
+      CtClassCacheFactory initializer = new CtClassCacheFactory();
+      String policy = properties.getProperty(POLICY_CLASS, TimedCachePolicy.class.getName());
+      try
+      {
+         Class<?> clazz = Class.forName(policy);
+         if (CachePolicy.class.isAssignableFrom(clazz) == false)
+            throw new IllegalStateException(clazz + " is not an instance of " + CachePolicy.class.getName());
+         else
+            initializer.policyClass = (Class<? extends CachePolicy>)clazz;
+      }
+      catch(Exception e)
+      {
+         throw new IllegalStateException("Could not load policy class " + policy, e);
+      }
+
+      if (TimedCachePolicy.class.isAssignableFrom(initializer.policyClass))
+      {
+         initializer.lifetime = parsePropertyIntoInteger(properties, TIMED_POLICY_LIFETIME, DEFAULT_TIMED_POLICY_LIFETIME);
+         initializer.resolution = parsePropertyIntoInteger(properties, TIMED_POLICY_RESOLUTION, DEFAULT_TIMED_POLICY_RESOLUTION);
+         warnUnusedParameters(properties, initializer.policyClass, LRU_POLICY_MIN, LRU_POLICY_MAX);
+      }
+      else if (LRUCachePolicy.class.isAssignableFrom(initializer.policyClass))
+      {
+         initializer.min = parsePropertyIntoInteger(properties, LRU_POLICY_MIN, DEFAULT_LRU_POLICY_MIN);
+         initializer.max = parsePropertyIntoInteger(properties, LRU_POLICY_MAX, DEFAULT_LRU_POLICY_MAX);
+         warnUnusedParameters(properties, initializer.policyClass, TIMED_POLICY_LIFETIME, TIMED_POLICY_RESOLUTION);
+      }
+      else
+      {
+         try
+         {
+            Constructor<?> ctor = initializer.policyClass.getConstructor();
+            if (!Modifier.isPublic(ctor.getModifiers()))
+               throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " has a default constructor, but it is not public");
+         }
+         catch(NoSuchMethodException e)
+         {
+            throw new IllegalStateException("Unknown policy class " + initializer.policyClass.getName() + " does not have a default constructor");
+         }
+      }
+      return initializer;
+   }
+   
+   public CtClassCache createCache()
+   {
+      CachePolicy policy = null;
+      if (policyClass == TimedCachePolicy.class)
+         policy = new TimedCachePolicy(lifetime, true, resolution);
+      else if (policyClass == LRUCachePolicy.class)
+         policy = new LRUCachePolicy(min, max);
+      else
+      {
+         try
+         {
+            policy = policyClass.newInstance();
+         }
+         catch(Exception e)
+         {
+            throw new IllegalStateException("Could not instantiate " + policyClass.getName(), e);
+         }
+      }
+    
+      try
+      {
+         policy.create();
+         policy.start();
+      }
+      catch(Exception e)
+      {
+         throw new IllegalStateException("Error starting domain cache", e);
+      }
+      return new CtClassCache(policy);
+   }
+   
+   /**
+    * Get the policyClass
+    * @return the policyClass
+    */
+   public Class<? extends CachePolicy> getPolicyClass()
+   {
+      return policyClass;
+   }
+
+   /**
+    * Get the lifetime
+    * @return the lifetime
+    */
+   public int getLifetime()
+   {
+      return lifetime;
+   }
+
+   /**
+    * Get the resolution
+    * @return the resolution
+    */
+   public int getResolution()
+   {
+      return resolution;
+   }
+
+   /**
+    * Get the min
+    * @return the min
+    */
+   public int getMin()
+   {
+      return min;
+   }
+
+   /**
+    * Get the max
+    * @return the max
+    */
+   public int getMax()
+   {
+      return max;
+   }
+
+   private static int parsePropertyIntoInteger(Properties properties, String key, int defaultValue)
+   {
+      try
+      {
+         return Integer.valueOf(properties.getProperty(key, String.valueOf(defaultValue)));
+      }
+      catch(NumberFormatException e)
+      {
+         throw new IllegalStateException("The value " + properties.getProperty(key) + " for '" + key + "' is not a number");
+      }
+   }
+   
+   private static void warnUnusedParameters(Properties properties, Class<?> clazz, String...keys)
+   {
+      for (String key : keys)
+      {
+         if (properties.getProperty(key) != null)
+         {
+            log.warn("Ignoring unrecognized property " + key + " for policy class" + clazz);
+         }
+      }
+   }
+}

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/DefaultParentDelegationStrategy.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -52,4 +52,5 @@
       if (logger.isTraceEnabled()) logger.trace(this + " " + getDomain() + " isParentAfter " + isParentAfter);
       return isParentAfter;
    }
+
 }

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/ParentDelegationStrategy.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -41,4 +41,6 @@
    boolean isParentBefore(String classname);
 
    boolean isParentAfter(String classname);
+   
+   int getParentModCount();
 }

Added: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/base/SecurityActions.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,84 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.classpool.base;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+class SecurityActions
+{
+   Constructor<?> getConstructor(final Class<?> clazz, final Class<?>...parameterTypes) throws NoSuchMethodException
+   {
+      if (System.getSecurityManager() == null)
+         return clazz.getConstructor(parameterTypes);
+      
+      try
+      {
+         return AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>()
+         {
+   
+            public Constructor<?> run() throws Exception
+            {
+               return clazz.getConstructor(parameterTypes);
+            }
+         });
+      }
+      catch(PrivilegedActionException e)
+      {
+         if (e.getCause() instanceof NoSuchMethodException)
+            throw (NoSuchMethodException)e.getCause();
+         throw new RuntimeException(e.getCause());
+      }
+   }
+   
+   Object newInstance(final Class<?> clazz) throws Exception
+   {
+      if (System.getSecurityManager() == null)
+         return clazz.newInstance();
+      
+      try
+      {
+         return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+         {
+   
+            public Object run() throws Exception
+            {
+               return clazz.newInstance();
+            }
+         });
+      }
+      catch(PrivilegedActionException e)
+      {
+         if (e.getCause() instanceof Exception)
+            throw (Exception)e.getCause();
+         throw new RuntimeException(e.getCause());
+      }
+   }
+   
+}

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolDomain.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -37,4 +37,5 @@
    public void removeClassPool(DelegatingClassPool pool);
    public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, boolean create);
    public CtClass getCachedOrCreate(DelegatingClassPool initiatingPool, String classname, String resourceName, boolean create, boolean trace);
+   public int getModCount();
 }
\ No newline at end of file

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/domain/ClassPoolToClassPoolDomainAdapter.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -97,4 +97,9 @@
    {
       return "ClassPoolToDomainAdapter[" + System.identityHashCode(this) + " " + pool.toString() + "]";
    }
+
+   public int getModCount()
+   {
+      return 0;
+   }
 }

Modified: projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java	2010-01-12 09:25:34 UTC (rev 99278)
+++ projects/jboss-classpool/trunk/classpool/src/main/java/org/jboss/classpool/plugins/DelegatingClassPool.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -22,16 +22,18 @@
 package org.jboss.classpool.plugins;
 
 
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import javassist.scopedpool.ScopedClassPoolRepository;
+
 import org.jboss.classpool.base.BaseClassPool;
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.classpool.base.CtClassCache;
 import org.jboss.classpool.domain.AbstractClassPoolDomain;
 import org.jboss.classpool.domain.ClassPoolDomain;
 import org.jboss.classpool.helpers.ClassLoaderUtils;
 
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.NotFoundException;
-import javassist.scopedpool.ScopedClassPoolRepository;
-
 /**
  * Base class for classpools backed by a domain
  * 
@@ -44,6 +46,10 @@
    
    private volatile boolean closed;
    
+   private final CtClassCache cachedLookups;
+
+   private static final CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties();
+   
    public DelegatingClassPool(ClassPoolDomain domain, ClassLoader cl, ClassPool parent, ScopedClassPoolRepository repository)
    {
       super(cl, parent, repository);
@@ -58,6 +64,7 @@
       if (logger.isTraceEnabled()) logger.trace(this + " domain:" + this);
       this.domain = domain;
       this.domain.addClassPool(this);
+      cachedLookups = factory.createCache();
    }
 
    public CtClass loadLocally(String classname, String resourceName, boolean create)
@@ -85,8 +92,16 @@
     */
    @Override
    //TODO KABIR was synchronized - I don't see why apart from that the standard javassist.ClassPool implementation was synchronized?
-   public CtClass get0(String classname, boolean useCache) throws NotFoundException
+   public final CtClass get0(String classname, boolean useCache) throws NotFoundException
    {
+      //KABIR Made final just to make sure that cached lookups are only handled in one place. 
+      CtClass cachedLookup = cachedLookups.get(classname, domain.getModCount());
+      if (cachedLookup != null)
+      {
+         logger.trace(classname + " was found in the cache of " + this);
+         return cachedLookup;
+      }
+
       if (isGeneratedClass(classname))
       {
          return null;
@@ -101,6 +116,8 @@
          //https://jira.jboss.org/jira/browse/JBCL-92
          clazz = loadLocally(classname, ClassLoaderUtils.getResourceName(classname), true);
       }
+      
+      cachedLookups.put(classname, clazz);
       return clazz;
    }
    

Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/support/MockCachePolicy.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,111 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.test.classpool.support;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.util.CachePolicy;
+
+/**
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MockCachePolicy implements CachePolicy
+{
+   public static List<MockCachePolicy> policies = new ArrayList<MockCachePolicy>();
+   
+   Map<Object, Object> map = new HashMap<Object, Object>();
+   
+   List<Object> wasCachedClasses = new ArrayList<Object>();
+   
+   public MockCachePolicy()
+   {
+      policies.add(this);
+   }
+   
+   public void create() throws Exception
+   {
+   }
+
+   public void destroy()
+   {
+      map.clear();
+   }
+
+   public void flush()
+   {
+      map.clear();
+   }
+
+   public Object get(Object key)
+   {
+      Object o = map.get(key);
+      if (o != null)
+      {
+         wasCachedClasses.add(key);
+      }
+      return o;
+   }
+
+   public boolean wasCached(String clazz)
+   {
+      return wasCachedClasses.contains(clazz);
+   }
+   
+   public void clearWasCachedClassses()
+   {
+      wasCachedClasses.clear();
+   }
+   
+   public void insert(Object key, Object object)
+   {
+      map.put(key, object);
+   }
+
+   public Object peek(Object key)
+   {
+      return map.get(key);
+   }
+
+   public void remove(Object key)
+   {
+      map.remove(key);
+   }
+
+   public int size()
+   {
+      return map.size();
+   }
+
+   public void start() throws Exception
+   {
+   }
+
+   public void stop()
+   {
+   }
+
+}

Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/RealCtCacheTestCase.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,193 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.test.classpool.test;
+
+import static org.jboss.test.classpool.support.SupportArchives.JAR_A_URL;
+import static org.jboss.test.classpool.support.SupportArchives.JAR_B_URL;
+import static org.jboss.test.classpool.support.SupportClasses.CLASS_A;
+import static org.jboss.test.classpool.support.SupportClasses.CLASS_B;
+import javassist.ClassPool;
+import javassist.CtClass;
+
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.classpool.domain.ClassPoolDomain;
+import org.jboss.classpool.plugins.DelegatingClassPool;
+import org.jboss.test.classpool.support.MockCachePolicy;
+
+/**
+ * Don't add this test to DelegatingClassPoolTestSuite, it needs a fresh JVM to run properly
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class RealCtCacheTestCase extends ClassPoolTest
+{
+   public RealCtCacheTestCase(String name)
+   {
+      super(name);
+   }
+   
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      System.setProperty(CtClassCacheFactory.POLICY_CLASS, MockCachePolicy.class.getName());
+   }
+
+   public void testSimple() throws Exception
+   {
+      MockCachePolicy.policies.clear();
+      ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+      ClassPool pool = createDelegatingClassPool(parent, JAR_A_URL);
+      
+      assertEquals(1, MockCachePolicy.policies.size());
+      MockCachePolicy policy = MockCachePolicy.policies.get(0);
+      
+      CtClass clazzA1 = pool.get(CLASS_A);
+      assertFalse(policy.wasCached(CLASS_A));
+      
+      policy.clearWasCachedClassses();
+      CtClass clazzA2 = pool.get(CLASS_A);
+      assertTrue(policy.wasCached(CLASS_A));
+      
+      assertSame(clazzA1, clazzA2);
+   }
+   
+   public void testOneDomainLevel() throws Exception
+   {
+      MockCachePolicy.policies.clear();
+      ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+      ClassPool poolA = createDelegatingClassPool(parent, JAR_A_URL);
+
+      assertEquals(1, MockCachePolicy.policies.size());
+      MockCachePolicy policyA = MockCachePolicy.policies.get(0);
+
+      policyA.clearWasCachedClassses();
+      CtClass clazzAa = poolA.get(CLASS_A);
+      assertFalse(policyA.wasCached(CLASS_A));
+      clazzAa = poolA.get(CLASS_A);
+      assertTrue(policyA.wasCached(CLASS_A));
+      
+      ClassPool poolB = createDelegatingClassPool(parent, JAR_B_URL);
+      
+      assertEquals(2, MockCachePolicy.policies.size());
+      MockCachePolicy policyB = MockCachePolicy.policies.get(1);
+      
+      assertNotSame(policyA, policyB);
+
+      //Adding a pool should have removed Class A from pool A's cache
+      policyA.clearWasCachedClassses();
+      policyB.clearWasCachedClassses();
+      clazzAa = poolA.get(CLASS_A);
+      CtClass clazzBa = poolA.get(CLASS_B);
+      CtClass clazzAb = poolB.get(CLASS_A);
+      CtClass clazzBb = poolB.get(CLASS_B);
+      assertSame(clazzAa, clazzAb);
+      assertSame(clazzBa, clazzBb);
+      assertFalse(policyA.wasCached(CLASS_A));
+      assertFalse(policyA.wasCached(CLASS_B));
+      assertFalse(policyB.wasCached(CLASS_A));
+      assertFalse(policyB.wasCached(CLASS_B));
+
+      policyA.clearWasCachedClassses();
+      policyB.clearWasCachedClassses();
+      CtClass clazzAa1 = poolA.get(CLASS_A);
+      CtClass clazzBa1 = poolA.get(CLASS_B);
+      assertSame(clazzAa1, clazzAa);
+      assertSame(clazzBa1, clazzBa);
+      assertTrue(policyA.wasCached(CLASS_A));
+      assertTrue(policyA.wasCached(CLASS_B));
+      assertFalse(policyB.wasCached(CLASS_A));
+      assertFalse(policyB.wasCached(CLASS_B));
+
+      policyA.clearWasCachedClassses();
+      policyB.clearWasCachedClassses();
+      CtClass clazzAb1 = poolB.get(CLASS_A);
+      CtClass clazzBb1 = poolB.get(CLASS_B);
+      assertSame(clazzAb1, clazzAb);
+      assertSame(clazzBb1, clazzBb);
+      assertFalse(policyA.wasCached(CLASS_A));
+      assertFalse(policyA.wasCached(CLASS_B));
+      assertTrue(policyB.wasCached(CLASS_A));
+      assertTrue(policyB.wasCached(CLASS_B));
+
+      clazzAa1 = poolA.get(CLASS_A);
+      clazzBa1 = poolA.get(CLASS_B);
+      assertTrue(policyA.wasCached(CLASS_A));
+      assertTrue(policyA.wasCached(CLASS_B));
+      assertTrue(policyB.wasCached(CLASS_A));
+      assertTrue(policyB.wasCached(CLASS_B));
+
+      //Removing the pool should invalidate pool A's cache
+      ((DelegatingClassPool)poolB).close();
+      MockCachePolicy.policies.remove(1);
+      policyA.clearWasCachedClassses();
+      policyB.clearWasCachedClassses();
+      clazzAa1 = poolA.get(CLASS_A);
+      assertFalse(policyA.wasCached(CLASS_A));
+   }
+   
+   public void testParentDelegation() throws Exception
+   {
+      MockCachePolicy.policies.clear();
+      ClassPoolDomain parent = createClassPoolDomain("PARENT", null, true);
+      ClassPool parentA = createDelegatingClassPool(parent, JAR_A_URL);
+
+      assertEquals(1, MockCachePolicy.policies.size());
+      MockCachePolicy.policies.clear();
+      
+      ClassPoolDomain child = createClassPoolDomain("CHILD", parent, true);
+      ClassPool childB = createDelegatingClassPool(child, JAR_B_URL);
+
+      assertEquals(1, MockCachePolicy.policies.size());
+      MockCachePolicy childPolicyB = MockCachePolicy.policies.get(0);
+      
+      CtClass classA = childB.get(CLASS_A);
+      assertFalse(childPolicyB.wasCached(CLASS_A));
+      childPolicyB.clearWasCachedClassses();
+      CtClass classA1 = childB.get(CLASS_A);
+      assertSame(classA, classA1);
+      assertTrue(childPolicyB.wasCached(CLASS_A));
+      
+      //Adding a pool to the parent should invalidate the child cache
+      childPolicyB.clearWasCachedClassses();
+      ClassPool parentB = createDelegatingClassPool(parent, JAR_B_URL);
+      classA1 = childB.get(CLASS_A);
+      assertFalse(childPolicyB.wasCached(CLASS_A));
+      assertSame(classA, classA1);
+      childPolicyB.clearWasCachedClassses();
+      classA1 = childB.get(CLASS_A);
+      assertSame(classA, classA1);
+      assertTrue(childPolicyB.wasCached(CLASS_A));
+      
+      //Removing a pool from the parent should invalidate the child cache
+      childPolicyB.clearWasCachedClassses();
+      ((DelegatingClassPool)parentB).close();
+      classA1 = childB.get(CLASS_A);
+      assertFalse(childPolicyB.wasCached(CLASS_A));
+      assertSame(classA, classA1);
+      childPolicyB.clearWasCachedClassses();
+      classA1 = childB.get(CLASS_A);
+      assertSame(classA, classA1);
+      assertTrue(childPolicyB.wasCached(CLASS_A));
+   }
+}

Added: projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java
===================================================================
--- projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java	                        (rev 0)
+++ projects/jboss-classpool/trunk/classpool/src/test/java/org/jboss/test/classpool/test/SimpleCtCacheTestCase.java	2010-01-12 12:53:31 UTC (rev 99279)
@@ -0,0 +1,168 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, 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.jboss.test.classpool.test;
+
+import java.util.Properties;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+
+import org.jboss.classpool.base.CtClassCache;
+import org.jboss.classpool.base.CtClassCacheFactory;
+import org.jboss.util.LRUCachePolicy;
+import org.jboss.util.TimedCachePolicy;
+
+import junit.framework.TestCase;
+
+/**
+ * Don't add this test to DelegatingClassPoolTestSuite, it needs a fresh JVM to run properly
+ * 
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class SimpleCtCacheTestCase extends TestCase
+{
+   public void testDomainCacheFactoryDefaultCacheNoProperties()
+   {
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties();
+      assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+      assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_LIFETIME, factory.getLifetime());
+      assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_RESOLUTION, factory.getResolution());
+      assertEquals(0, factory.getMin());
+      assertEquals(0, factory.getMax());
+   }
+   
+   public void testDomainCacheFactoryTimedCacheNoProperties()
+   {
+      Properties properties = new Properties();
+      properties.put(CtClassCacheFactory.POLICY_CLASS, TimedCachePolicy.class.getName());
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+      assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+      assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_LIFETIME, factory.getLifetime());
+      assertEquals(CtClassCacheFactory.DEFAULT_TIMED_POLICY_RESOLUTION, factory.getResolution());
+      assertEquals(0, factory.getMin());
+      assertEquals(0, factory.getMax());
+   }
+   
+   public void testDomainCacheFactoryTimedCacheAndProperties()
+   {
+      Properties properties = new Properties();
+      properties.put(CtClassCacheFactory.POLICY_CLASS, TimedCachePolicy.class.getName());
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 12);
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 23);
+      setProperty(properties, CtClassCacheFactory.LRU_POLICY_MIN, 34);
+      setProperty(properties, CtClassCacheFactory.LRU_POLICY_MAX, 45);
+      
+      
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+      assertEquals(TimedCachePolicy.class, factory.getPolicyClass());
+      assertEquals(12, factory.getLifetime());
+      assertEquals(23, factory.getResolution());
+      assertEquals(0, factory.getMin());
+      assertEquals(0, factory.getMax());
+   }
+   
+   public void testDomainCacheFactoryLruCacheNoProperties()
+   {
+      Properties properties = new Properties();
+      properties.put(CtClassCacheFactory.POLICY_CLASS, LRUCachePolicy.class.getName());
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+      assertEquals(LRUCachePolicy.class, factory.getPolicyClass());
+      assertEquals(0, factory.getLifetime());
+      assertEquals(0, factory.getResolution());
+      assertEquals(CtClassCacheFactory.DEFAULT_LRU_POLICY_MIN, factory.getMin());
+      assertEquals(CtClassCacheFactory.DEFAULT_LRU_POLICY_MAX, factory.getMax());
+   }
+   
+   public void testDomainCacheFactoryLruCacheAndProperties()
+   {
+      Properties properties = new Properties();
+      properties.put(CtClassCacheFactory.POLICY_CLASS, LRUCachePolicy.class.getName());
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 12);
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 23);
+      setProperty(properties, CtClassCacheFactory.LRU_POLICY_MIN, 34);
+      setProperty(properties, CtClassCacheFactory.LRU_POLICY_MAX, 45);
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+
+      assertEquals(LRUCachePolicy.class, factory.getPolicyClass());
+      assertEquals(0, factory.getLifetime());
+      assertEquals(0, factory.getResolution());
+      assertEquals(34, factory.getMin());
+      assertEquals(45, factory.getMax());
+   }
+
+   public void testTimedDomainCache() throws Exception
+   {
+      Properties properties = new Properties();
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 1);
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 1);
+      
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+      CtClassCache cache = factory.createCache();
+      assertNotNull(cache);
+      
+      ClassPool defPool = ClassPool.getDefault();
+      CtClass clazz = defPool.get(String.class.getName());
+      
+      assertNull(cache.get(clazz.getName(), 0));
+      cache.put(clazz.getName(), clazz);
+      
+      assertNotNull(cache.get(clazz.getName(), 0));
+      
+      Thread.sleep(2000);
+
+      assertNull(cache.get(clazz.getName(), 0));
+      
+      cache.put(clazz.getName(), clazz);
+   }
+   
+   public void testCacheInvalidation() throws Exception
+   {
+      Properties properties = new Properties();
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_LIFETIME, 100);
+      setProperty(properties, CtClassCacheFactory.TIMED_POLICY_RESOLUTION, 10);
+      
+      CtClassCacheFactory factory = CtClassCacheFactory.createFromProperties(properties);
+      CtClassCache cache = factory.createCache();
+      assertNotNull(cache);
+      
+      ClassPool defPool = ClassPool.getDefault();
+      CtClass clazz = defPool.get(String.class.getName());
+      
+      assertNull(cache.get(clazz.getName(), 0));
+      cache.put(clazz.getName(), clazz);
+      assertNotNull(cache.get(clazz.getName(), 0));
+      
+      assertNull(cache.get(clazz.getName(), 1));
+      cache.put(clazz.getName(), clazz);
+      assertNotNull(cache.get(clazz.getName(), 1));
+   }
+   
+   private void setProperty(Properties properties, String key, int value)
+   {
+      properties.put(key, String.valueOf(value));
+      assertEquals(String.valueOf(value), properties.get(key));
+   }
+}




More information about the jboss-cvs-commits mailing list