Permalink
Browse files

Merge jboss-proxy with invocation-api to get jboss-invocation

  • Loading branch information...
2 parents 4bf4431 + 5514ca2 commit f048768663759052890e212a2c3e9222006c36fc @dmlloyd dmlloyd committed Jan 22, 2011
Showing with 1,795 additions and 10 deletions.
  1. +4 −0 .gitignore
  2. +38 −10 pom.xml
  3. +151 −0 src/main/java/org/jboss/invocation/proxy/AbstractClassFactory.java
  4. +112 −0 src/main/java/org/jboss/invocation/proxy/AbstractProxyFactory.java
  5. +264 −0 src/main/java/org/jboss/invocation/proxy/AbstractSubclassFactory.java
  6. +38 −0 src/main/java/org/jboss/invocation/proxy/ConstructorBodyCreator.java
  7. +53 −0 src/main/java/org/jboss/invocation/proxy/DefaultConstructorBodyCreator.java
  8. +63 −0 src/main/java/org/jboss/invocation/proxy/DefaultMethodBodyCreator.java
  9. +76 −0 src/main/java/org/jboss/invocation/proxy/DefaultSerializableProxy.java
  10. +38 −0 src/main/java/org/jboss/invocation/proxy/MethodBodyCreator.java
  11. +371 −0 src/main/java/org/jboss/invocation/proxy/ProxyFactory.java
  12. +42 −0 src/main/java/org/jboss/invocation/proxy/ProxyInstance.java
  13. +51 −0 src/main/java/org/jboss/invocation/proxy/SerializableProxy.java
  14. +45 −0 ...est/java/org/jboss/invocation/proxy/test/abstractsubclassfactory/AbstractSubclassFactoryTest.java
  15. +49 −0 src/test/java/org/jboss/invocation/proxy/test/abstractsubclassfactory/SimpleClassFactory.java
  16. +36 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/ConstructedGuardClass.java
  17. +39 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/ConstructedGuardTest.java
  18. +39 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleClass.java
  19. +41 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleDispatcher.java
  20. +44 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleProxyFactoryTest.java
  21. +34 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/serialization/SerializableClass.java
  22. +43 −0 .../org/jboss/invocation/proxy/test/proxyfactory/serialization/SerializableInvocationDispatcher.java
  23. +124 −0 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/serialization/SerializationTest.java
View
4 .gitignore
@@ -1,3 +1,7 @@
/.idea
*.iml
target
+.prject
+.project
+.settings
+.classpath
View
48 pom.xml
@@ -33,15 +33,21 @@
<modelVersion>4.0.0</modelVersion>
<!-- Artifact Information -->
- <groupId>org.jboss</groupId>
- <artifactId>invocation-api</artifactId>
+ <groupId>org.jboss.invocation</groupId>
+ <artifactId>jboss-invocation</artifactId>
<version>1.0.0.CR1-SNAPSHOT</version>
<name>Invocation API</name>
<description>Invocation Application Programming Interface</description>
<packaging>jar</packaging>
<!-- Properties -->
<properties>
+ <classwriter.version>1.0-SNAPSHOT</classwriter.version>
+ <javax.interceptor.version>1.0.0.Final</javax.interceptor.version>
+ <jboss.marshalling.version>1.3.0.CR8</jboss.marshalling.version>
+ <jboss.logging.version>3.0.0.Beta4</jboss.logging.version>
+ <jboss.logging.tools.version>1.0.0.Beta2</jboss.logging.tools.version>
+ <junit.version>4.8.2</junit.version>
</properties>
<!-- Build Information -->
@@ -53,33 +59,55 @@
<plugin>
<artifactId>maven-source-plugin</artifactId>
</plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkMode>once</forkMode>
+ <argLine>-XX:-FailOverToOldVerifier -Xverify:all</argLine>
+ </configuration>
+ </plugin>
</plugins>
</build>
<!-- Dependencies -->
<dependencies>
<dependency>
- <groupId>org.jboss.marshalling</groupId>
- <artifactId>jboss-marshalling</artifactId>
- <version>1.3.0.CR8</version>
+ <groupId>org.jboss.spec.javax.interceptor</groupId>
+ <artifactId>jboss-interceptors-api_1.1_spec</artifactId>
+ <version>${javax.interceptor.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.jboss.spec.javax.interceptor</groupId>
- <artifactId>jboss-interceptors-api_1.1_spec</artifactId>
- <version>1.0.0.Final</version>
+ <groupId>org.jboss.marshalling</groupId>
+ <artifactId>jboss-marshalling</artifactId>
+ <version>${jboss.marshalling.version}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
- <version>3.0.0.Beta4</version>
+ <version>${jboss.logging.version}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-tools</artifactId>
- <version>1.0.0.Beta2</version>
+ <version>${jboss.logging.tools.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.classwriter</groupId>
+ <artifactId>classwriter</artifactId>
+ <version>${classwriter.version}</version>
+ <type>jar</type>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
View
151 src/main/java/org/jboss/invocation/proxy/AbstractClassFactory.java
@@ -0,0 +1,151 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.security.ProtectionDomain;
+
+import org.jboss.classfilewriter.ClassFile;
+
+/**
+ * Base class for all class factories.
+ * <p>
+ * Sub classes should override {@link #generateClass()} to perform the actual class generation. The class will only be generated
+ * once at most
+ *
+ * @author Stuart Douglas
+ *
+ */
+public abstract class AbstractClassFactory<T> {
+
+ /**
+ * The name of the generated class
+ */
+ private final String className;
+
+ /**
+ * superclass of the generated class
+ */
+ private final Class<T> superClass;
+
+ /**
+ * The class loader that is used to load the class
+ */
+ private final ClassLoader classLoader;
+
+ /**
+ * The ProtectionDomain that the generated class will be definied in
+ */
+ private final ProtectionDomain protectionDomain;
+
+ /**
+ * The class object for the generated class
+ */
+ private volatile Class<? extends T> generatedClass;
+
+ /**
+ * The class file that is used to generate the class.
+ * <p>
+ * Note that this object is not thread safe, so care should be taken by subclasses to ensure that no more than one thread
+ * accesses this at once. In normal use this should not be an issue, as {@link #defineClass()} will only be called once by a
+ * single thread.
+ * <p>
+ * This is set to null after the class is generated
+ */
+ protected ClassFile classFile;
+
+ public AbstractClassFactory(String className, Class<T> superClass, ClassLoader classLoader,
+ ProtectionDomain protectionDomain) {
+ this.className = className;
+ this.superClass = superClass;
+ this.classLoader = classLoader;
+ this.protectionDomain = protectionDomain;
+ this.classFile = new ClassFile(className, superClass.getName());
+ }
+
+ public AbstractClassFactory(String className, Class<T> superClass, ClassLoader classLoader) {
+ this(className, superClass, classLoader, null);
+ }
+
+ public AbstractClassFactory(String className, Class<T> superClass) {
+ this(className, superClass, superClass.getClassLoader(), null);
+ }
+
+ protected abstract void generateClass();
+
+ /**
+ * Cleans up any resources left over from generating the class. Implementors should ensure they call super.cleanup();
+ */
+ protected abstract void cleanup();
+
+ /**
+ * Returns the {@link Class} object for the generated class, creating it if it does not exist
+ *
+ */
+ public Class<? extends T> defineClass() {
+ if (generatedClass == null) {
+ synchronized (this) {
+ if (generatedClass == null) {
+ generateClass();
+ if (protectionDomain == null) {
+ generatedClass = (Class<? extends T>)classFile.define(classLoader);
+ } else {
+ generatedClass = (Class<? extends T>)classFile.define(classLoader, protectionDomain);
+ }
+ cleanup();
+ classFile = null;
+ }
+ }
+ }
+ return generatedClass;
+ }
+
+ /**
+ * Creates a new instance of the generated class by invoking the default constructor.
+ * <p>
+ * If the generated class has not been defined it will be created
+ *
+ */
+ public T newInstance() throws InstantiationException, IllegalAccessException {
+ return defineClass().newInstance();
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getSuperClassName() {
+ return superClass.getName();
+ }
+
+ public Class<T> getSuperClass() {
+ return superClass;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public ProtectionDomain getProtectionDomain() {
+ return protectionDomain;
+ }
+}
View
112 src/main/java/org/jboss/invocation/proxy/AbstractProxyFactory.java
@@ -0,0 +1,112 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.classfilewriter.AccessFlag;
+import org.jboss.classfilewriter.ClassMethod;
+import org.jboss.classfilewriter.code.CodeAttribute;
+import org.jboss.invocation.MethodIdentifier;
+
+public abstract class AbstractProxyFactory<T> extends AbstractSubclassFactory<T> {
+
+ private static final String METHOD_IDENTIFIER_FIELD_PREFIX = "METHOD$$IDENTIFIER";
+
+ private static final String METHID_IDENTIFIER_FIELD_DESCRIPTOR = "Lorg/jboss/invocation/MethodIdentifier;";
+
+ private final Map<Method, String> methodIdentifiers = new HashMap<Method, String>();
+
+ private int identifierCount = 0;
+
+ private ClassMethod staticConstructor;
+
+ public AbstractProxyFactory(String className, Class<T> superClass, ClassLoader classLoader) {
+ super(className, superClass, classLoader);
+ staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
+ }
+
+ public AbstractProxyFactory(String className, Class<T> superClass, ClassLoader classLoader,
+ ProtectionDomain protectionDomain) {
+ super(className, superClass, classLoader, protectionDomain);
+ staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
+ }
+
+ public AbstractProxyFactory(String className, Class<T> superClass) {
+ super(className, superClass);
+ staticConstructor = classFile.addMethod(AccessFlag.of(AccessFlag.PUBLIC, AccessFlag.STATIC), "<clinit>", "V");
+ }
+
+ /**
+ * This method must be called by subclasses after they have finished generating the class
+ */
+ protected void finalizeStaticConstructor() {
+ staticConstructor.getCodeAttribute().returnInstruction();
+ }
+
+ @Override
+ protected void cleanup() {
+ staticConstructor = null;
+ super.cleanup();
+ }
+
+ /**
+ * Writes the bytecode to load an instance of MethodIdentifier for the given method onto the stack.
+ * <p>
+ * If loadMethodIdentifier has not already been called for the given identifier then a static field to hold the identifier
+ * is added to the class, and code is added to the static constructor to initalize the field to the correct MethodIdentifier
+ *
+ */
+ protected void loadMethodIdentifier(Method methodToLoad, ClassMethod method) {
+ if (!methodIdentifiers.containsKey(methodToLoad)) {
+ int identifierNo = identifierCount++;
+ String fieldName = METHOD_IDENTIFIER_FIELD_PREFIX + identifierNo;
+ classFile.addField(AccessFlag.PRIVATE | AccessFlag.STATIC, fieldName, MethodIdentifier.class);
+ methodIdentifiers.put(methodToLoad, fieldName);
+ // we need to create the method identifier in the static constructor
+ CodeAttribute ca = staticConstructor.getCodeAttribute();
+ //push the method return type onto the stack
+ ca.ldc(methodToLoad.getReturnType().getName());
+ // push the method name onto the stack
+ ca.ldc(methodToLoad.getName());
+ Class<?>[] parameters = methodToLoad.getParameterTypes();
+ // now we need a new array
+ ca.iconst(parameters.length);
+ ca.anewarray(String.class.getName());
+ for (int i = 0; i < parameters.length; ++i) {
+ ca.dup(); //dup the array
+ ca.iconst(i); //the array index to store it
+ ca.ldc(parameters[i].getName());
+ ca.aastore();
+ }
+ ca.invokestatic(MethodIdentifier.class.getName(), "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Lorg/jboss/invocation/MethodIdentifier;");
+ ca.putstatic(getClassName(), fieldName, METHID_IDENTIFIER_FIELD_DESCRIPTOR);
+ }
+ String fieldName = methodIdentifiers.get(methodToLoad);
+ method.getCodeAttribute().getstatic(getClassName(), fieldName, METHID_IDENTIFIER_FIELD_DESCRIPTOR);
+ }
+
+}
View
264 src/main/java/org/jboss/invocation/proxy/AbstractSubclassFactory.java
@@ -0,0 +1,264 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.jboss.classfilewriter.ClassMethod;
+import org.jboss.invocation.MethodIdentifier;
+
+/**
+ * Class factory for classes that override superclass methods.
+ * <p>
+ * This class extends {@link AbstractClassFactory} by adding convenience methods to override methods on the superclass.
+ *
+ * @author Stuart Douglas
+ *
+ */
+public abstract class AbstractSubclassFactory<T> extends AbstractClassFactory<T> {
+
+ public AbstractSubclassFactory(String className, Class<T> superClass, ClassLoader classLoader,
+ ProtectionDomain protectionDomain) {
+ super(className, superClass, classLoader, protectionDomain);
+ }
+
+ public AbstractSubclassFactory(String className, Class<T> superClass, ClassLoader classLoader) {
+ super(className, superClass, classLoader);
+ }
+
+ public AbstractSubclassFactory(String className, Class<T> superClass) {
+ super(className, superClass);
+ }
+
+ /**
+ * Tracks methods that have already been overridden
+ */
+ private final Set<MethodIdentifier> overriddenMethods = new HashSet<MethodIdentifier>();
+
+ /**
+ * Methods that should not be overridden by default
+ */
+ private static final Set<MethodIdentifier> SKIP_BY_DEFAULT;
+
+ static {
+ HashSet<MethodIdentifier> skip = new HashSet<MethodIdentifier>();
+ skip.add(MethodIdentifier.EQUALS);
+ skip.add(MethodIdentifier.FINALIZE);
+ skip.add(MethodIdentifier.HASH_CODE);
+ skip.add(MethodIdentifier.TO_STRING);
+ SKIP_BY_DEFAULT = Collections.unmodifiableSet(skip);
+ }
+
+ /**
+ * Creates a new method on the generated class that overrides the given methods, unless a method with the same signiture has
+ * already been overridden
+ *
+ * @param method The method to override
+ * @param identifier The identifier of the method to override
+ * @param creator The {@link MethodBodyCreator} used to create the method body
+ */
+ protected void overrideMethod(Method method, MethodIdentifier identifier, MethodBodyCreator creator) {
+ if (!overriddenMethods.contains(identifier)) {
+ overriddenMethods.add(identifier);
+ creator.overrideMethod(classFile.addMethod(method), method);
+ }
+ }
+
+ /**
+ * Creates a new method on the generated class that overrides the given methods, unless a method with the same signiture has
+ * already been overridden
+ *
+ * @param method The method to override
+ * @param identifier The identifier of the method to override
+ * @param creator The {@link MethodBodyCreator} used to create the method body
+ */
+ protected void overrideMethod(ClassMethod method, MethodIdentifier identifier, MethodBodyCreator creator) {
+ if (!overriddenMethods.contains(identifier)) {
+ overriddenMethods.add(identifier);
+ creator.overrideMethod(method, null);
+ }
+ }
+
+ /**
+ * overrides all public methods on the superclass. The default {@link MethodBodyCreator} is used to generate the class body
+ */
+ protected void overridePublicMethods(boolean includeEquals, boolean includeHashcode, boolean includeToString) {
+ overridePublicMethods(getDefaultMethodOverride(), includeEquals, includeHashcode, includeToString);
+ }
+
+ @Override
+ protected void cleanup() {
+ overriddenMethods.clear();
+ }
+
+ /**
+ * overrides all public methods on the superclass. The given {@link MethodBodyCreator} is used to generate the class body
+ */
+ protected void overridePublicMethods(MethodBodyCreator override, boolean includeEquals, boolean includeHashcode,
+ boolean includeToString) {
+ for (Method method : getSuperClass().getMethods()) {
+ MethodIdentifier identifier = MethodIdentifier.getIdentifierForMethod(method);
+ if (Modifier.isFinal(method.getModifiers())) {
+ continue;
+ }
+ if (!SKIP_BY_DEFAULT.contains(identifier)) {
+ overrideMethod(method, identifier, override);
+ }
+ }
+ }
+
+ /**
+ * Calls {@link #overrideAllMethods(MethodBodyCreator)} with the default {@link MethodBodyCreator}
+ *
+ */
+ protected void overrideAllMethods() {
+ overrideAllMethods(getDefaultMethodOverride());
+ }
+
+ /**
+ * Overrides all methods on the superclass with the exception of <code>equals(Object)</code>, <code>hashCode()</code>,
+ * <code>toString()</code> and <code>finalize()</code>. The given {@link MethodBodyCreator} is used to generate the class
+ * body.
+ * <p>
+ * Note that private methods are not actually overridden, and if the sub-class is loaded by a different ClassLoader to the
+ * parent class then neither will package-private methods. These methods will still be present on the new class however, and
+ * can be accessed via reflection
+ *
+ */
+ protected void overrideAllMethods(MethodBodyCreator override) {
+ Class<?> currentClass = getSuperClass();
+ while (currentClass != null) {
+ for (Method method : getSuperClass().getDeclaredMethods()) {
+ // do not override static or private methods
+ if (Modifier.isStatic(method.getModifiers()) || Modifier.isPrivate(method.getModifiers())) {
+ continue;
+ }
+ MethodIdentifier identifier = MethodIdentifier.getIdentifierForMethod(method);
+ // don't attempt to override final methods
+ if (Modifier.isFinal(method.getModifiers())) {
+ continue;
+ }
+ if (!SKIP_BY_DEFAULT.contains(identifier)) {
+ overrideMethod(method, identifier, override);
+ }
+ }
+ currentClass = currentClass.getSuperclass();
+ }
+ }
+
+ /**
+ * Override the equals method using the given {@link MethodBodyCreator}
+ */
+ protected void overrideEquals(MethodBodyCreator creator) {
+ Method equals = null;
+ try {
+ equals = getSuperClass().getMethod("equals", Object.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ creator.overrideMethod(classFile.addMethod(equals), equals);
+ }
+
+ /**
+ * Override the hashCode method using the given {@link MethodBodyCreator}
+ */
+ protected void overrideHashcode(MethodBodyCreator creator) {
+ Method hashCode = null;
+ try {
+ hashCode = getSuperClass().getMethod("hashCode");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ creator.overrideMethod(classFile.addMethod(hashCode), hashCode);
+ }
+
+ /**
+ * Override the toString method using the given {@link MethodBodyCreator}
+ */
+ protected void overrideToString(MethodBodyCreator creator) {
+ Method toString = null;
+ try {
+ toString = getSuperClass().getMethod("toString");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ creator.overrideMethod(classFile.addMethod(toString), toString);
+ }
+
+ /**
+ * Adds an interface to the generated subclass, using the default {@link MethodBodyCreator} to generate the method bodies
+ */
+ protected void addInterface(Class<?> interfaceClass) {
+ addInterface(getDefaultMethodOverride(), interfaceClass);
+ }
+
+ /**
+ * Adds an interface to the generated subclass, using the given {@link MethodBodyCreator} to generate the method bodies
+ */
+ protected void addInterface(MethodBodyCreator override, Class<?> interfaceClass) {
+ classFile.addInterface(interfaceClass.getName());
+ for (Method method : interfaceClass.getMethods()) {
+ override.overrideMethod(classFile.addMethod(method), method);
+ }
+ }
+
+ /**
+ * Adds a constructor for every non-private constructor present on the superclass. The constrcutor bodies are generated with
+ * the default {@link ConstructorBodyCreator}
+ */
+ protected void createConstructorDelegates() {
+ createConstructorDelegates(getDefaultConstructorOverride());
+ }
+
+ /**
+ * Adds constructors that delegate the the superclass constructor for all non-private constructors present on the superclass
+ */
+ protected void createConstructorDelegates(ConstructorBodyCreator creator) {
+ for (Constructor<?> constructor : getSuperClass().getDeclaredConstructors()) {
+ if (!Modifier.isPrivate(constructor.getModifiers())) {
+ creator.overrideConstructor(classFile.addConstructor(constructor), constructor);
+ }
+ }
+ }
+
+ /**
+ * returns the default {@link MethodBodyCreator} to use when creating overridden methods
+ */
+ public MethodBodyCreator getDefaultMethodOverride() {
+ return DefaultMethodBodyCreator.INSTANCE;
+ }
+
+ /**
+ * returns the default {@link ConstructorBodyCreator} to use then creating overridden subclasses
+ */
+ public ConstructorBodyCreator getDefaultConstructorOverride() {
+ return DefaultConstructorBodyCreator.INSTANCE;
+ }
+
+}
View
38 src/main/java/org/jboss/invocation/proxy/ConstructorBodyCreator.java
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Constructor;
+
+import org.jboss.classfilewriter.ClassMethod;
+
+/**
+ * A class that can generate a overriden version of a constructor
+ *
+ * @author Stuart Douglas
+ *
+ */
+public interface ConstructorBodyCreator {
+
+ public void overrideConstructor(ClassMethod method, Constructor<?> constructor);
+}
View
53 src/main/java/org/jboss/invocation/proxy/DefaultConstructorBodyCreator.java
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Constructor;
+
+import org.jboss.classfilewriter.ClassMethod;
+import org.jboss.classfilewriter.code.CodeAttribute;
+
+/**
+ * Constructor override that simply delegates to super()
+ *
+ * @author Stuart Douglas
+ *
+ */
+public class DefaultConstructorBodyCreator implements ConstructorBodyCreator {
+
+ public static final DefaultConstructorBodyCreator INSTANCE = new DefaultConstructorBodyCreator();
+
+ private DefaultConstructorBodyCreator() {
+
+ }
+
+ @Override
+ public void overrideConstructor(ClassMethod method, Constructor<?> constructor) {
+ CodeAttribute ca = method.getCodeAttribute();
+ ca.aload(0);
+ ca.loadMethodParameters();
+ ca.invokespecial(constructor);
+ ca.returnInstruction();
+ }
+
+}
View
63 src/main/java/org/jboss/invocation/proxy/DefaultMethodBodyCreator.java
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Method;
+
+import org.jboss.classfilewriter.ClassMethod;
+import org.jboss.classfilewriter.code.CodeAttribute;
+
+/**
+ * A {@link MethodBodyCreator} that simply returns 0 or null depending on the methods return type
+ *
+ * @author Stuart Douglas
+ *
+ */
+public class DefaultMethodBodyCreator implements MethodBodyCreator {
+
+ public static final DefaultMethodBodyCreator INSTANCE = new DefaultMethodBodyCreator();
+
+ private DefaultMethodBodyCreator() {
+ }
+
+ @Override
+ public void overrideMethod(ClassMethod method, Method superclassMethod) {
+ CodeAttribute ca = method.getCodeAttribute();
+ Class<?> returnType = superclassMethod.getReturnType();
+ if (!returnType.isPrimitive()) {
+ ca.aconstNull();
+ } else if (returnType == double.class) {
+ ca.dconst(0);
+ } else if (returnType == float.class) {
+ ca.fconst(0);
+ } else if (returnType == long.class) {
+ ca.lconst(0);
+ } else if (returnType == void.class) {
+ // do nothing
+ } else {
+ ca.iconst(0);
+ }
+ ca.returnInstruction();
+ }
+
+}
View
76 src/main/java/org/jboss/invocation/proxy/DefaultSerializableProxy.java
@@ -0,0 +1,76 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.io.ObjectStreamException;
+import java.security.PrivilegedAction;
+
+import org.jboss.invocation.InvocationDispatcher;
+
+/**
+ * Serialized representation of a proxy.
+ *
+ * @author Stuart Douglas
+ *
+ */
+public class DefaultSerializableProxy implements SerializableProxy {
+
+ private InvocationDispatcher dispatcher;
+ private String proxyClassName;
+
+ public void setProxyInstance(ProxyInstance proxy) {
+ this.proxyClassName = proxy.getClass().getName();
+ this.dispatcher = proxy._getProxyInvocationDispatcher();
+ }
+
+ protected Object readResolve() throws ObjectStreamException {
+ try {
+ Class<?> proxyClass = getProxyClass();
+ ProxyInstance instance = (ProxyInstance) proxyClass.newInstance();
+ instance._setProxyInvocationDispatcher(dispatcher);
+ return instance;
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected Class<?> getProxyClass() throws ClassNotFoundException {
+ ClassLoader classLoader = getProxyClassLoader();
+ return Class.forName(proxyClassName, false, classLoader);
+ }
+
+ protected ClassLoader getProxyClassLoader() {
+ return new PrivilegedAction<ClassLoader>() {
+
+ @Override
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }.run();
+ }
+
+}
View
38 src/main/java/org/jboss/invocation/proxy/MethodBodyCreator.java
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.lang.reflect.Method;
+
+import org.jboss.classfilewriter.ClassMethod;
+
+/**
+ * A class that can generate a overriden version of a method
+ *
+ * @author Stuart Douglas
+ *
+ */
+public interface MethodBodyCreator {
+
+ public void overrideMethod(ClassMethod method, Method superclassMethod);
+}
View
371 src/main/java/org/jboss/invocation/proxy/ProxyFactory.java
@@ -0,0 +1,371 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.io.ObjectStreamException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jboss.classfilewriter.AccessFlag;
+import org.jboss.classfilewriter.ClassMethod;
+import org.jboss.classfilewriter.code.BranchEnd;
+import org.jboss.classfilewriter.code.CodeAttribute;
+import org.jboss.classfilewriter.util.Boxing;
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationDispatcher;
+import org.jboss.invocation.InvocationReply;
+import org.jboss.invocation.MethodIdentifier;
+
+/**
+ * Proxy Factory that generates proxis that delegate all calls to an {@link InvocationDispatcher}.
+ * <p>
+ * Typical usage looks like:
+ * <p>
+ *
+ * <pre>
+ * ProxyFactory&lt;SimpleClass&gt; proxyFactory = new ProxyFactory&lt;SimpleClass&gt;(SimpleClass.class);
+ * SimpleClass instance = proxyFactory.newInstance(new SimpleDispatcher());
+ * </pre>
+ *
+ * </p>
+ * This will create a proxy for SimpleClass, and return a new instance that handles invocations using the InvocationDispatcher
+ * SimpleDispatcher.
+ * <p>
+ * Invocations on these proxies are very efficient, as no reflection is involved.
+ *
+ * @author Stuart Douglas
+ *
+ * @param <T>
+ */
+public class ProxyFactory<T> extends AbstractProxyFactory<T> {
+
+ /**
+ * Overrides superclass methods and forwards calls to the dispatcher
+ *
+ * @author Stuart Douglas
+ *
+ */
+ protected class ProxyMethodBodyCreator implements MethodBodyCreator {
+
+ // we simply want to load the corresponding identifier
+ // and then forward it to the dispatcher
+ @Override
+ public void overrideMethod(ClassMethod method, Method superclassMethod) {
+ CodeAttribute ca = method.getCodeAttribute();
+ // first we need to check the constructed field
+ ca.aload(0);
+ ca.getfield(getClassName(), CONSTRUCTED_GUARD, "Z");
+ // if the object has not been constructed yet invoke the superclass version of the method
+ BranchEnd end = ca.ifne();
+ ca.aload(0);
+ ca.loadMethodParameters();
+ ca.invokespecial(getSuperClassName(), method.getName(), method.getDescriptor());
+ ca.returnInstruction();
+ // normal invocation path begins here
+ ca.branchEnd(end);
+ ca.aload(0);
+ ca.getfield(getClassName(), INVOCATION_DISPATCHER_FIELD, InvocationDispatcher.class);
+ // now we have the dispatcher on the stack, we need to build an invocation
+ ca.newInstruction(Invocation.class.getName());
+ ca.dup();
+ // the constructor we are using is Invocation(final Class<?> declaringClass, final MethodIdentifier
+ // methodIdentifier, final Object... args)
+ ca.loadClass(superclassMethod.getDeclaringClass().getName());
+ loadMethodIdentifier(superclassMethod, method);
+ // now we need to stick the parameters into an array, boxing if nessesary
+ String[] params = method.getParameters();
+ ca.iconst(params.length);
+ ca.anewarray("java/lang/Object");
+ int loadPosition = 1;
+ for (int i = 0; i < params.length; ++i) {
+ ca.dup();
+ ca.iconst(i);
+ String type = params[i];
+ if (type.length() == 1) { // primitive
+ char typeChar = type.charAt(0);
+ switch (typeChar) {
+ case 'I':
+ ca.iload(loadPosition);
+ Boxing.boxInt(ca);
+ break;
+ case 'S':
+ ca.iload(loadPosition);
+ Boxing.boxShort(ca);
+ break;
+ case 'B':
+ ca.iload(loadPosition);
+ Boxing.boxByte(ca);
+ break;
+ case 'Z':
+ ca.iload(loadPosition);
+ Boxing.boxBoolean(ca);
+ break;
+ case 'C':
+ ca.iload(loadPosition);
+ Boxing.boxChar(ca);
+ break;
+ case 'D':
+ ca.dload(loadPosition);
+ Boxing.boxDouble(ca);
+ loadPosition++;
+ break;
+ case 'J':
+ ca.lload(loadPosition);
+ Boxing.boxLong(ca);
+ loadPosition++;
+ break;
+ case 'F':
+ ca.fload(loadPosition);
+ Boxing.boxFloat(ca);
+ break;
+ default:
+ throw new RuntimeException("Unkown primitive type descriptor: " + typeChar);
+ }
+ } else {
+ ca.aload(loadPosition);
+ }
+ ca.aastore();
+ loadPosition++;
+ }
+ ca.invokespecial(Invocation.class.getName(), "<init>",
+ "(Ljava/lang/Class;Lorg/jboss/invocation/MethodIdentifier;[Ljava/lang/Object;)V");
+ // now we have the invocation on top of the stack, with the dispatcher below it
+ ca.invokeinterface(InvocationDispatcher.class.getName(), "dispatch",
+ "(Lorg/jboss/invocation/Invocation;)Lorg/jboss/invocation/InvocationReply;");
+ ca.invokevirtual(InvocationReply.class.getName(), "getReply", "()Ljava/lang/Object;");
+ if (superclassMethod.getReturnType() != void.class) {
+ if (superclassMethod.getReturnType().isPrimitive()) {
+ Boxing.unbox(ca, method.getReturnType());
+ } else {
+ ca.checkcast(superclassMethod.getReturnType().getName());
+ }
+ }
+ ca.returnInstruction();
+ }
+ }
+
+ /**
+ * Implements the methods from the {@link ProxyInstance} interface
+ *
+ * @author Stuart Douglas
+ *
+ */
+ protected class ProxyInstanceMethodBodyCreator implements MethodBodyCreator {
+
+ @Override
+ public void overrideMethod(ClassMethod method, Method superclassMethod) {
+ CodeAttribute ca = method.getCodeAttribute();
+ if (method.getName().equals("_getProxyInvocationDispatcher")) {
+ ca.aload(0);
+ ca.getfield(getClassName(), INVOCATION_DISPATCHER_FIELD, InvocationDispatcher.class);
+ ca.returnInstruction();
+ } else if (method.getName().equals("_setProxyInvocationDispatcher")) {
+ ca.aload(0);
+ ca.aload(1);
+ ca.putfield(getClassName(), INVOCATION_DISPATCHER_FIELD, InvocationDispatcher.class);
+ ca.returnInstruction();
+ } else {
+ throw new RuntimeException("Unkown method on interface " + ProxyInstance.class);
+ }
+ }
+ }
+
+ /**
+ * Generates a proxy constructor that delegates to super(), and then sets the constructed flag to true.
+ *
+ * @author Stuart Douglas
+ *
+ */
+ protected class ProxyConstructorBodyCreator implements ConstructorBodyCreator {
+
+ @Override
+ public void overrideConstructor(ClassMethod method, Constructor<?> constructor) {
+ CodeAttribute ca = method.getCodeAttribute();
+ ca.aload(0);
+ ca.iconst(0);
+ ca.putfield(getClassName(), CONSTRUCTED_GUARD, "Z");
+ ca.aload(0);
+ ca.loadMethodParameters();
+ ca.invokespecial(constructor);
+ ca.aload(0);
+ ca.iconst(1);
+ ca.putfield(getClassName(), CONSTRUCTED_GUARD, "Z");
+ ca.returnInstruction();
+ }
+ }
+
+ /**
+ * Generates the writereplace method if advanced serialization is enabled
+ *
+ * @author Stuart Douglas
+ *
+ */
+ protected class WriteReplaceBodyCreator implements MethodBodyCreator {
+
+ @Override
+ public void overrideMethod(ClassMethod method, Method superclassMethod) {
+ // superClassMethod will be null
+ CodeAttribute ca = method.getCodeAttribute();
+ ca.newInstruction(serializableProxyClass.getName());
+ ca.dup();
+ ca.invokespecial(serializableProxyClass.getName(), "<init>", "()V");
+ ca.dup();
+ ca.aload(0);
+ ca.invokeinterface(SerializableProxy.class.getName(), "setProxyInstance", "(Lorg/jboss/proxy/ProxyInstance;)V");
+ ca.returnInstruction();
+ }
+ }
+
+ /**
+ * Name of the field that holds the generated dispatcher on the generated proxy
+ */
+ public static final String INVOCATION_DISPATCHER_FIELD = "invocation$$dispatcher";
+
+ /**
+ * atomic integer used to generate proxy names
+ */
+ private static final AtomicInteger nameCount = new AtomicInteger();
+
+ /**
+ * this field on the generated class stores if the constructor has been completed yet. No methods will be delegated to the
+ * dispacher until the constructor has finished. This prevents virtual methods called from the constructor being delegated
+ * to a handler that is null.
+ */
+ private static final String CONSTRUCTED_GUARD = "proxy$$Constructor$$finished";
+
+ /**
+ * A list of additional interfaces that should be added to the proxy, and should have invocations delegated to the
+ * dispatcher
+ */
+ private final Class<?>[] additionalInterfaces;
+
+ /**
+ * The type of {@link SerializableProxy} to generate from the writeReplace method
+ */
+ private Class<? extends SerializableProxy> serializableProxyClass;
+
+ /**
+ *
+ * @param className the name of the generated proxy
+ * @param superClass the superclass of the generated proxy
+ * @param classLoader the classloader to load the proxy with
+ * @param protectionDomain the ProtectionDomain to define the class with
+ * @param additionalInterfaces Additional interfaces that should be implemented by the proxy class
+ */
+ public ProxyFactory(String className, Class<T> superClass, ClassLoader classLoader, ProtectionDomain protectionDomain,
+ Class<?>... additionalInterfaces) {
+ super(className, superClass, classLoader, protectionDomain);
+ this.additionalInterfaces = additionalInterfaces;
+ }
+
+ /**
+ *
+ * @param className the name of the generated proxy
+ * @param superClass the superclass of the generated proxy
+ * @param classLoader the classloader to load the proxy with
+ * @param additionalInterfaces Additional interfaces that should be implemented by the proxy class
+ */
+ public ProxyFactory(String className, Class<T> superClass, ClassLoader classLoader, Class<?>... additionalInterfaces) {
+ super(className, superClass, classLoader);
+ this.additionalInterfaces = additionalInterfaces;
+ }
+
+ /**
+ *
+ * @param className The name of the proxy class
+ * @param superClass The name of proxies superclass
+ * @param additionalInterfaces Additional interfaces that should be implemented by the proxy class
+ */
+ public ProxyFactory(String className, Class<T> superClass, Class<?>... additionalInterfaces) {
+ super(className, superClass);
+ this.additionalInterfaces = additionalInterfaces;
+ }
+
+ /**
+ * Create a ProxyFactory for the given superclass, using the default name and the classloader of the superClass
+ *
+ * @param superClass the superclass of the generated proxy
+ * @param additionalInterfaces Additional interfaces that should be implemented by the proxy class
+ */
+ public ProxyFactory(Class<T> superClass, Class<?>... additionalInterfaces) {
+ super(superClass.getName() + "$$Proxy" + nameCount.incrementAndGet(), superClass);
+ this.additionalInterfaces = additionalInterfaces;
+ }
+
+ /**
+ * Create a new proxy, initialising it with the given dispatcher
+ */
+ public T newInstance(InvocationDispatcher dispatcher) throws InstantiationException, IllegalAccessException {
+ T ret = newInstance();
+ ((ProxyInstance) ret)._setProxyInvocationDispatcher(dispatcher);
+ return ret;
+ }
+
+ @Override
+ protected void generateClass() {
+ classFile.addField(AccessFlag.PRIVATE, INVOCATION_DISPATCHER_FIELD, InvocationDispatcher.class);
+ classFile.addField(AccessFlag.PRIVATE, CONSTRUCTED_GUARD, "Z");
+ if (serializableProxyClass != null) {
+ createWriteReplace();
+ }
+ ProxyMethodBodyCreator creator = new ProxyMethodBodyCreator();
+ overrideAllMethods(creator);
+ for (Class<?> iface : additionalInterfaces) {
+ addInterface(creator, iface);
+ }
+ overrideToString(creator);
+ overrideEquals(creator);
+ overrideHashcode(creator);
+ addInterface(new ProxyInstanceMethodBodyCreator(), ProxyInstance.class);
+ createConstructorDelegates(new ProxyConstructorBodyCreator());
+ finalizeStaticConstructor();
+ }
+
+ private void createWriteReplace() {
+ MethodIdentifier identifier = MethodIdentifier.getIdentifier(Object.class, "writeReplace");
+ ClassMethod method = classFile.addMethod(AccessFlag.PROTECTED, "writeReplace", "Ljava/lang/Object;");
+ method.addCheckedExceptions(ObjectStreamException.class);
+ overrideMethod(method, identifier, new WriteReplaceBodyCreator());
+ }
+
+ /**
+ * Sets the {@link SerializableProxy} class to emit from the proxies writeReplace method. If this is set to null (the
+ * default) then no writeReplace method will be generated. The proxy may still be serializable, providing that the
+ * superclass and {@link InvocationDispatcher} are both serializable.
+ * <p>
+ *
+ * @see SerializableProxy
+ * @see DefaultSerializableProxy
+ * @param serializableProxyClass
+ * @throws IllegalStateException If the proxy class has already been generated
+ */
+ public void setSerializableProxyClass(Class<? extends SerializableProxy> serializableProxyClass) {
+ if (classFile == null) {
+ throw new IllegalStateException(
+ "Cannot set a ProxyFactories SerialiableProxyClass after the proxy has been created");
+ }
+ this.serializableProxyClass = serializableProxyClass;
+ }
+}
View
42 src/main/java/org/jboss/invocation/proxy/ProxyInstance.java
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import org.jboss.invocation.InvocationDispatcher;
+
+/**
+ * Class that is implemented by all proxy classes. Contains methods to get and set the {@link InvocationDispatcher}
+ * <p>
+ * The method names do not follow normal java naming conventions to minimise the chance of name collisions with methods on the
+ * proxy
+ *
+ * @author Stuart Douglas
+ *
+ */
+public interface ProxyInstance {
+
+ public void _setProxyInvocationDispatcher(InvocationDispatcher dispatcher);
+
+ public InvocationDispatcher _getProxyInvocationDispatcher();
+
+}
View
51 src/main/java/org/jboss/invocation/proxy/SerializableProxy.java
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.invocation.proxy;
+
+import java.io.Serializable;
+
+/**
+ * Serialized representation of a proxy. When a proxy that is using a {@link SerializableProxy} is serialized it is serialized
+ * via the following mechanism:
+ *
+ * <pre>
+ * Object writeReplace() throws ObjectStreamException {
+ * SerializableProxy proxy = serializableClass.newInstance();
+ * proxy.setProxyInstance(this);
+ * return proxy;
+ * }
+ * </pre>
+ * <p>
+ * Implementors of this interface should store any state that is required to re-create the proxy in this class's serialized
+ * form. Implementors also *MUST* implement an <code>Object readResolve() throws ObjectStreamException</code> method, the
+ * returns the de-serialized proxy.
+ *
+ * @see DefaultSerializableProxy
+ * @author Stuart Douglas
+ *
+ */
+public interface SerializableProxy extends Serializable {
+
+ public abstract void setProxyInstance(ProxyInstance proxy);
+
+}
View
45 .../org/jboss/invocation/proxy/test/abstractsubclassfactory/AbstractSubclassFactoryTest.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.abstractsubclassfactory;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public class AbstractSubclassFactoryTest {
+
+ @Test
+ public void simpleAbstractSubclassFactoryTest() throws InstantiationException, IllegalAccessException {
+ SimpleClassFactory<OverridenClass> factory = new SimpleClassFactory<OverridenClass>(getClass().getName() + "$$Test",
+ OverridenClass.class, getClass().getClassLoader());
+ OverridenClass instance = factory.newInstance();
+ Assert.assertEquals(0, instance.value());
+ }
+
+
+ public static class OverridenClass {
+ public int value() {
+ return 10;
+ }
+ }
+
+}
View
49 ...test/java/org/jboss/invocation/proxy/test/abstractsubclassfactory/SimpleClassFactory.java
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.abstractsubclassfactory;
+
+import java.security.ProtectionDomain;
+
+import org.jboss.invocation.proxy.AbstractSubclassFactory;
+
+public class SimpleClassFactory<T> extends AbstractSubclassFactory<T> {
+
+ public SimpleClassFactory(String className, Class<T> superClass, ClassLoader classLoader, ProtectionDomain protectionDomain) {
+ super(className, superClass, classLoader, protectionDomain);
+ }
+
+ public SimpleClassFactory(String className, Class<T> superClass, ClassLoader classLoader) {
+ super(className, superClass, classLoader);
+ }
+
+ public SimpleClassFactory(String className, Class<T> superClass) {
+ super(className, superClass);
+ }
+
+ // simply overrides public methods and constructors using the default method builder
+ @Override
+ protected void generateClass() {
+ overridePublicMethods(true, true, true);
+ createConstructorDelegates();
+ }
+
+}
View
36 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/ConstructedGuardClass.java
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory;
+
+public class ConstructedGuardClass {
+
+ public int count = 0;
+
+ public ConstructedGuardClass() {
+ virtualMethod();
+ }
+
+ public void virtualMethod() {
+ count++;
+ }
+
+}
View
39 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/ConstructedGuardTest.java
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory;
+
+import junit.framework.Assert;
+
+import org.jboss.invocation.proxy.ProxyFactory;
+import org.junit.Test;
+
+public class ConstructedGuardTest {
+
+ @Test
+ public void testConstructedGuard() throws InstantiationException, IllegalAccessException {
+ ProxyFactory<ConstructedGuardClass> proxyFactory = new ProxyFactory<ConstructedGuardClass>(ConstructedGuardClass.class);
+ // if there is no guard we will get a NPE here
+ // as the proxy attempts to delegate to a null method
+ ConstructedGuardClass instance = proxyFactory.newInstance();
+ Assert.assertEquals(1, instance.count);
+ }
+}
View
39 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleClass.java
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory;
+
+import org.jboss.invocation.Invocation;
+
+public class SimpleClass {
+
+ public SimpleClass() {
+
+ }
+
+ public Invocation method1() {
+ return null;
+ }
+
+ public Invocation method2(long v1, double v2, Object v3, int[] v4) {
+ return null;
+ }
+}
View
41 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleDispatcher.java
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory;
+
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationDispatcher;
+import org.jboss.invocation.InvocationException;
+import org.jboss.invocation.InvocationReply;
+
+public class SimpleDispatcher implements InvocationDispatcher {
+
+ public static boolean invoked = false;
+ public static Class<?> declaringClass;
+
+ @Override
+ public InvocationReply dispatch(Invocation invocation) throws InvocationException {
+ invoked = true;
+ declaringClass = invocation.getDeclaringClass();
+ return new InvocationReply(invocation);
+ }
+
+}
View
44 src/test/java/org/jboss/invocation/proxy/test/proxyfactory/SimpleProxyFactoryTest.java
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory;
+
+import junit.framework.Assert;
+
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.proxy.ProxyFactory;
+import org.jboss.invocation.proxy.ProxyInstance;
+import org.junit.Test;
+
+public class SimpleProxyFactoryTest {
+
+ @Test
+ public void testSimpleProxy() throws InstantiationException, IllegalAccessException {
+ ProxyFactory<SimpleClass> proxyFactory = new ProxyFactory<SimpleClass>(SimpleClass.class);
+ SimpleClass instance = proxyFactory.newInstance(new SimpleDispatcher());
+ ((ProxyInstance) instance)._setProxyInvocationDispatcher(new SimpleDispatcher());
+ Invocation invocation = instance.method1();
+ Assert.assertEquals("method1", invocation.getMethodIdentifier().getName());
+ Assert.assertEquals(0, invocation.getMethodIdentifier().getParameterTypes().length);
+ Assert.assertEquals(SimpleClass.class, SimpleDispatcher.declaringClass);
+ }
+
+}
View
34 ...st/java/org/jboss/invocation/proxy/test/proxyfactory/serialization/SerializableClass.java
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory.serialization;
+
+import java.io.Serializable;
+
+public class SerializableClass implements Serializable {
+
+ public int state;
+
+ public void invoke(int value) {
+
+ }
+
+}
View
43 ...ss/invocation/proxy/test/proxyfactory/serialization/SerializableInvocationDispatcher.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory.serialization;
+
+import java.io.Serializable;
+
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationDispatcher;
+import org.jboss.invocation.InvocationException;
+import org.jboss.invocation.InvocationReply;
+
+public class SerializableInvocationDispatcher implements InvocationDispatcher, Serializable {
+ private int state;
+
+ public int getState() {
+ return state;
+ }
+
+ @Override
+ public InvocationReply dispatch(Invocation invocation) throws InvocationException {
+ state = (Integer) invocation.getArgs()[0];
+ return new InvocationReply(null);
+ }
+}
View
124 ...st/java/org/jboss/invocation/proxy/test/proxyfactory/serialization/SerializationTest.java
@@ -0,0 +1,124 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.proxy.test.proxyfactory.serialization;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+
+import junit.framework.Assert;
+
+import org.jboss.invocation.proxy.DefaultSerializableProxy;
+import org.jboss.invocation.proxy.ProxyFactory;
+import org.jboss.invocation.proxy.ProxyInstance;
+import org.junit.Test;
+
+public class SerializationTest {
+
+ @Test
+ public void simpleSerializationTest() throws InstantiationException, IllegalAccessException, IOException,
+ ClassNotFoundException {
+ ProxyFactory<SerializableClass> proxyFactory = new ProxyFactory<SerializableClass>(SerializableClass.class);
+ SerializableInvocationDispatcher dispatcher = new SerializableInvocationDispatcher();
+ SerializableClass proxy = proxyFactory.newInstance(dispatcher);
+ proxy.invoke(10);
+ Assert.assertEquals(10, dispatcher.getState());
+ proxy.state = 100;
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ ObjectOutputStream outputStream = new ObjectOutputStream(bytes);
+ outputStream.writeObject(proxy);
+
+ ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()));
+ SerializableClass deserializedProxy = (SerializableClass) inputStream.readObject();
+ Assert.assertEquals(100, deserializedProxy.state);
+ Assert.assertEquals(10, ((SerializableInvocationDispatcher) ((ProxyInstance) deserializedProxy)
+ ._getProxyInvocationDispatcher()).getState());
+ }
+
+ @Test
+ public void defaultSerializableProxyTest() throws InstantiationException, IllegalAccessException, IOException,
+ ClassNotFoundException {
+ ProxyFactory<SerializableClass> proxyFactory = new ProxyFactory<SerializableClass>(SerializableClass.class);
+ proxyFactory.setSerializableProxyClass(DefaultSerializableProxy.class);
+ SerializableInvocationDispatcher dispatcher = new SerializableInvocationDispatcher();
+ SerializableClass proxy = proxyFactory.newInstance(dispatcher);
+ proxy.invoke(10);
+ Assert.assertEquals(10, dispatcher.getState());
+ proxy.state = 100;
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ ObjectOutputStream outputStream = new ObjectOutputStream(bytes);
+ outputStream.writeObject(proxy);
+
+ ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()));
+ SerializableClass deserializedProxy = (SerializableClass) inputStream.readObject();
+ Assert.assertEquals(0, deserializedProxy.state);
+ Assert.assertEquals(10, ((SerializableInvocationDispatcher) ((ProxyInstance) deserializedProxy)
+ ._getProxyInvocationDispatcher()).getState());
+ }
+
+ @Test
+ public void serializableProxyDifferentClassloadTest() throws InstantiationException, IllegalAccessException, IOException,
+ ClassNotFoundException {
+
+ ClassLoader classLoader = new ClassLoader(getClass().getClassLoader()) {
+ };
+
+ ProxyFactory<SerializableClass> proxyFactory = new ProxyFactory<SerializableClass>("org.jboss.proxy.test.SomeProxy",
+ SerializableClass.class, classLoader);
+ proxyFactory.setSerializableProxyClass(TestSerializableProxy.class);
+ SerializableInvocationDispatcher dispatcher = new SerializableInvocationDispatcher();
+ SerializableClass proxy = proxyFactory.newInstance(dispatcher);
+ Class<?> proxyClass = proxyFactory.defineClass();
+ proxy.invoke(10);
+ Assert.assertEquals(10, dispatcher.getState());
+ proxy.state = 100;
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ ObjectOutputStream outputStream = new ObjectOutputStream(bytes);
+ outputStream.writeObject(proxy);
+
+ ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()));
+ SerializableClass deserializedProxy = (SerializableClass) inputStream.readObject();
+ Assert.assertEquals(0, deserializedProxy.state);
+ Assert.assertEquals(10, ((SerializableInvocationDispatcher) ((ProxyInstance) deserializedProxy)
+ ._getProxyInvocationDispatcher()).getState());
+ Assert.assertNotSame(proxyFactory.defineClass(), deserializedProxy.getClass());
+ Assert.assertEquals(deserializedProxy.getClass().getClassLoader(), getClass().getClassLoader());
+ }
+
+ public static class TestSerializableProxy extends DefaultSerializableProxy {
+ @Override
+ protected Class<?> getProxyClass() throws ClassNotFoundException {
+ ProxyFactory<SerializableClass> proxyFactory = new ProxyFactory<SerializableClass>(
+ "org.jboss.proxy.test.SomeProxy", SerializableClass.class, getClass().getClassLoader());
+ return proxyFactory.defineClass();
+ }
+
+ @Override
+ protected Object readResolve() throws ObjectStreamException {
+ return super.readResolve();
+ }
+ }
+
+}

0 comments on commit f048768

Please sign in to comment.