You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2011/11/02 00:10:14 UTC
svn commit: r1196363 - in /tapestry/tapestry5/trunk:
tapestry-core/src/test/java/org/apache/tapestry5/internal/services/
tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/
tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ tapestry-ioc/src...
Author: hlship
Date: Tue Nov 1 23:10:13 2011
New Revision: 1196363
URL: http://svn.apache.org/viewvc?rev=1196363&view=rev
Log:
TAP5-1739: Remove use of Javassist for testing reloadable service implementations
Added:
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NoopClassLoaderDelegate.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ReloadTest.java
tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java?rev=1196363&r1=1196362&r2=1196363&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java Tue Nov 1 23:10:13 2011
@@ -178,41 +178,6 @@ public class PropertyConduitSourceImplTe
assertEquals(inner.getFirstName(), "Howard");
}
- /**
- * Or call this the "Hibernate" case; Hibernate creates sub-classes of
- * entity classes in its own class loader to do
- * all sorts of proxying. This trips up Javassist.
- */
- @Test
- public void handle_beans_from_unexpected_classloader() throws Exception
- {
- throw new Exception("test not yet re-implemented");
-
- /*
- // First, create something that looks like a Hibernate proxy.
-
- ClassFactory factory = new ClassFactoryImpl();
-
- Class clazz = SimpleBean.class;
-
- ClassFab cf = factory.newClass(clazz.getName() + "$$Proxy", clazz);
-
- cf.addInterface(Serializable.class);
-
- Class proxyClass = cf.createClass();
-
- SimpleBean simple = (SimpleBean) proxyClass.newInstance();
-
- assertTrue(simple instanceof Serializable);
-
- simple.setFirstName("Howard");
-
- PropertyConduit conduit = source.create(proxyClass, "firstName");
-
- assertEquals(conduit.get(simple), "Howard");
- */
- }
-
@Test
public void generics()
{
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java?rev=1196363&r1=1196362&r2=1196363&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java Tue Nov 1 23:10:13 2011
@@ -43,30 +43,6 @@ public final class ClassFabUtils
}
/**
- * Given a Class instance, convert the name into a path that can be used to locate
- * the underlying class file on the classpath.
- *
- * @since 5.2.0
- */
- public static String getPathForClass(Class clazz)
- {
- assert clazz != null;
-
- return getPathForClassNamed(clazz.getName());
- }
-
- /**
- * Given a fully qualified class name, converts to a path on the classpath.
- *
- * @since 5.2.0
- */
- public static String getPathForClassNamed(String className)
- {
- return className.replace('.', '/') + ".class";
- }
-
-
- /**
* Converts a URL with protocol "file" to a File instance.
*
* @since 5.2.0
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ReloadTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ReloadTest.java?rev=1196363&r1=1196362&r2=1196363&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ReloadTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ReloadTest.java Tue Nov 1 23:10:13 2011
@@ -1,4 +1,4 @@
-// Copyright 2010 The Apache Software Foundation
+// Copyright 2010, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,30 +14,23 @@
package org.apache.tapestry5.ioc;
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Modifier;
-import java.net.URL;
-import java.net.URLClassLoader;
-
-import javassist.CannotCompileException;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtConstructor;
-import javassist.CtMethod;
-import javassist.NotFoundException;
-
-import org.apache.tapestry5.ioc.services.ClassFabUtils;
+import com.example.*;
+import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.ioc.test.IOCTestCase;
import org.apache.tapestry5.services.UpdateListenerHub;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import com.example.Counter;
-import com.example.CounterImpl;
-import com.example.ReloadAwareModule;
-import com.example.ReloadModule;
-import com.example.ReloadableService;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import static org.apache.tapestry5.internal.plastic.asm.Opcodes.*;
/**
* Test the ability to perform live class reloading of a service implementation.
@@ -73,7 +66,7 @@ public class ReloadTest extends IOCTestC
System.out.println("Reload classes dir: " + classesURL);
classLoader = new URLClassLoader(new URL[]
- { classesURL }, Thread.currentThread().getContextClassLoader());
+ {classesURL}, Thread.currentThread().getContextClassLoader());
classFile = new File(classesDir, "com/example/ReloadableServiceImpl.class");
}
@@ -113,18 +106,27 @@ public class ReloadTest extends IOCTestC
@Test
public void reload_a_base_class() throws Exception
{
+ String baseClassInternalName = PlasticInternalUtils.toInternalName(BASE_CLASS);
+ String internalName = PlasticInternalUtils.toInternalName(CLASS);
+
createImplementationClass(BASE_CLASS, "initial from base");
- ClassPool pool = new ClassPool(null);
- pool.appendSystemPath();
- pool.appendClassPath(classesDir.getAbsolutePath());
+ ClassWriter cw = createClassWriter(internalName, baseClassInternalName, ACC_PUBLIC);
- CtClass ctClass = pool.makeClass(CLASS);
+ // Add default constructor
- ctClass.setSuperclass(pool.get(BASE_CLASS));
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, baseClassInternalName, "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
- ctClass.writeFile(classesDir.getAbsolutePath());
+ cw.visitEnd();
+
+ writeBytecode(cw, internalName);
Registry registry = createRegistry();
@@ -134,7 +136,7 @@ public class ReloadTest extends IOCTestC
assertEquals(reloadable.getStatus(), "initial from base");
- touch(new File(classesDir, ClassFabUtils.getPathForClassNamed(BASE_CLASS)));
+ touch(new File(pathForInternalName(baseClassInternalName)));
createImplementationClass(BASE_CLASS, "updated from base");
@@ -167,8 +169,7 @@ public class ReloadTest extends IOCTestC
{
reloadable.getStatus();
unreachable();
- }
- catch (RuntimeException ex)
+ } catch (RuntimeException ex)
{
assertMessageContains(ex, "Unable to reload", CLASS);
}
@@ -242,8 +243,7 @@ public class ReloadTest extends IOCTestC
reloadable.getStatus();
unreachable();
- }
- catch (Exception ex)
+ } catch (Exception ex)
{
assertEquals(ex.getMessage(),
"Service implementation class com.example.ReloadableServiceImpl does not have a suitable public constructor.");
@@ -257,46 +257,94 @@ public class ReloadTest extends IOCTestC
createImplementationClass(CLASS, status);
}
- private void createImplementationClass(String className, String status) throws NotFoundException,
- CannotCompileException, IOException
+ private void createImplementationClass(String className, String status) throws Exception
{
- ClassPool pool = new ClassPool(null);
+ String internalName = PlasticInternalUtils.toInternalName(className);
- pool.appendSystemPath();
+ ClassWriter cw = createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC);
- CtClass ctClass = pool.makeClass(className);
+ // Add default constructor
- ctClass.addInterface(pool.get(ReloadableService.class.getName()));
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
- CtMethod method = new CtMethod(pool.get("java.lang.String"), "getStatus", null, ctClass);
- method.setBody(String.format("return \"%s\";", status));
+ mv = cw.visitMethod(ACC_PUBLIC, "getStatus", "()Ljava/lang/String;", null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(status);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
- ctClass.addMethod(method);
+ cw.visitEnd();
- ctClass.writeFile(classesDir.getAbsolutePath());
+ writeBytecode(cw, internalName);
}
- private void createInvalidImplentationClass() throws Exception
+ private ClassWriter createClassWriter(String internalName, String baseClassInternalName, int classModifiers)
+ {
+ ClassWriter cw = new ClassWriter(0);
+
+ cw.visit(V1_5, classModifiers, internalName, null,
+ baseClassInternalName, new String[]{
+ PlasticInternalUtils.toInternalName(ReloadableService.class.getName())
+ });
+
+ return cw;
+ }
+
+ private void writeBytecode(ClassWriter cw, String internalName) throws Exception
+ {
+ byte[] bytecode = cw.toByteArray();
+
+ writeBytecode(bytecode, pathForInternalName(internalName));
+ }
+
+ private String pathForInternalName(String internalName)
+ {
+ return String.format("%s/%s.class",
+ classesDir.getAbsolutePath(),
+ internalName);
+ }
+
+ private void writeBytecode(byte[] bytecode, String path) throws Exception
{
- ClassPool pool = new ClassPool(null);
+ File file = new File(path);
+
+ file.getParentFile().mkdirs();
+
+ OutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
- pool.appendSystemPath();
+ stream.write(bytecode);
- CtClass ctClass = pool.makeClass(CLASS);
+ stream.close();
+ }
+
+ private void createInvalidImplentationClass() throws Exception
+ {
+ String internalName = PlasticInternalUtils.toInternalName(CLASS);
- ctClass.setModifiers(Modifier.ABSTRACT | Modifier.PUBLIC);
- ctClass.addInterface(pool.get(ReloadableService.class.getName()));
+ ClassWriter cw = createClassWriter(internalName, "java/lang/Object", ACC_PUBLIC);
- CtConstructor constructor = new CtConstructor(new CtClass[0], ctClass);
+ // Add default constructor
- constructor.setBody("return $0;");
+ MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "<init>", "()V", null, null);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
- constructor.setModifiers(Modifier.PROTECTED);
+ // Notice the class is abstract, so no implementation.
- ctClass.addConstructor(constructor);
+ cw.visitEnd();
- ctClass.writeFile(classesDir.getAbsolutePath());
+ writeBytecode(cw, internalName);
}
@Test
Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java?rev=1196363&r1=1196362&r2=1196363&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java Tue Nov 1 23:10:13 2011
@@ -14,7 +14,6 @@
package org.apache.tapestry5.ioc.internal;
-import org.apache.tapestry5.internal.plastic.ClassLoaderDelegate;
import org.apache.tapestry5.internal.plastic.PlasticClassLoader;
import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
@@ -668,7 +667,7 @@ public class DefaultModuleDefImplTest ex
ClassLoader loader = Thread.currentThread().getContextClassLoader();
- PlasticClassLoader plasticLoader = new PlasticClassLoader(loader, new NoopDelegate());
+ PlasticClassLoader plasticLoader = new PlasticClassLoader(loader, new NoopClassLoaderDelegate());
return plasticLoader.defineClassWithBytecode("EnhancedSyntheticMethodModule", bytecode);
}
@@ -677,16 +676,4 @@ public class DefaultModuleDefImplTest ex
// marker annotation are
// merged into the set specific to the service).
- private static class NoopDelegate implements ClassLoaderDelegate
- {
- public boolean shouldInterceptClassLoading(String className)
- {
- return false;
- }
-
- public Class<?> loadAndTransformClass(String className) throws ClassNotFoundException
- {
- return null;
- }
- }
}
Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NoopClassLoaderDelegate.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NoopClassLoaderDelegate.java?rev=1196363&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NoopClassLoaderDelegate.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NoopClassLoaderDelegate.java Tue Nov 1 23:10:13 2011
@@ -0,0 +1,30 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.internal.plastic.ClassLoaderDelegate;
+
+public class NoopClassLoaderDelegate implements ClassLoaderDelegate
+{
+ public boolean shouldInterceptClassLoading(String className)
+ {
+ return false;
+ }
+
+ public Class<?> loadAndTransformClass(String className) throws ClassNotFoundException
+ {
+ throw new IllegalStateException();
+ }
+}