You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2010/09/01 02:01:35 UTC

svn commit: r991400 - /tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java

Author: hlship
Date: Wed Sep  1 00:01:35 2010
New Revision: 991400

URL: http://svn.apache.org/viewvc?rev=991400&view=rev
Log:
TAP5-1188: Refactor to use Javassist class loading objects

Modified:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java?rev=991400&r1=991399&r2=991400&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java Wed Sep  1 00:01:35 2010
@@ -19,43 +19,46 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.ProtectionDomain;
+
+import javassist.CannotCompileException;
+import javassist.ClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.Loader;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+import javassist.Translator;
 
 import org.apache.tapestry5.ioc.Invokable;
 import org.apache.tapestry5.ioc.ObjectCreator;
 import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.internal.services.ClassFactoryClassPool;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.ioc.services.ClassFabUtils;
 import org.apache.tapestry5.services.UpdateListener;
 import org.slf4j.Logger;
 
-public abstract class AbstractReloadableObjectCreator implements ObjectCreator, UpdateListener
+@SuppressWarnings("all")
+public abstract class AbstractReloadableObjectCreator implements ObjectCreator, UpdateListener, Translator
 {
+    private final ProtectionDomain domain = getClass().getProtectionDomain();
 
-    private class ReloadingClassLoader extends ClassLoader
+    private class XLoader extends Loader
     {
-        private ReloadingClassLoader(ClassLoader parent)
+        public XLoader(ClassLoader parent, ClassPool pool)
         {
-            super(parent);
+            super(parent, pool);
         }
 
         @Override
-        public Class<?> loadClass(String name) throws ClassNotFoundException
+        protected Class findClass(String name) throws ClassNotFoundException
         {
-            if (isReloadingClass(name))
-            {
-                byte[] classData = readClassData(name);
-
-                return defineClass(name, classData, 0, classData.length);
-            }
+            if (shouldLoadClassNamed(name))
+                return super.findClass(name);
 
-            return super.loadClass(name);
-        }
-
-        private boolean isReloadingClass(String name)
-        {
-            // This class loader exists to reload the implementation class and any inner classes of the
-            // implementation class.
-            return name.equals(implementationClassName) || name.startsWith(implementationClassName + "$");
+            return null; // Force delegation to parent class loader
         }
     }
 
@@ -142,17 +145,33 @@ public abstract class AbstractReloadable
         if (logger.isDebugEnabled())
             logger.debug(String.format("%s class %s.", firstTime ? "Loading" : "Reloading", implementationClassName));
 
-        ClassLoader reloadingClassLoader = new ReloadingClassLoader(baseClassLoader);
+        ClassFactoryClassPool pool = new ClassFactoryClassPool(baseClassLoader);
+
+        // For TAPESTRY-2561, we're introducing a class loader between the parent (i.e., the
+        // context class loader), and the component class loader, to try and prevent the deadlocks
+        // that we've been seeing.
+
+        ClassLoader threadDeadlockBuffer = new URLClassLoader(new URL[0], baseClassLoader);
+
+        Loader loader = new XLoader(threadDeadlockBuffer, pool);
+
+        ClassPath path = new LoaderClassPath(loader);
+
+        pool.appendClassPath(path);
 
         try
         {
-            Class result = reloadingClassLoader.loadClass(implementationClassName);
+            loader.addTranslator(pool, this);
+
+            CtClass implCtClass = pool.get(implementationClassName);
+
+            Class result = pool.toClass(implCtClass, loader, domain);
 
             firstTime = false;
 
             return result;
         }
-        catch (ClassNotFoundException ex)
+        catch (Throwable ex)
         {
             throw new RuntimeException(String.format("Unable to %s class %s: %s", firstTime ? "load" : "reload",
                     implementationClassName, InternalUtils.toMessage(ex)), ex);
@@ -227,4 +246,20 @@ public abstract class AbstractReloadable
     {
         return lastModifiedTimestamp;
     }
+
+    private boolean shouldLoadClassNamed(String name)
+    {
+        return name.equals(implementationClassName) || name.startsWith(implementationClassName + "$");
+    }
+
+    public void onLoad(ClassPool pool, String className) throws NotFoundException, CannotCompileException
+    {
+
+    }
+
+    public void start(ClassPool pool) throws NotFoundException, CannotCompileException
+    {
+
+    }
+
 }