OWB-1277 ensure we can proxy beans with a writeReplace method
git-svn-id: https://svn.apache.org/repos/asf/openwebbeans/trunk@1850347 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
index a14e8e1..061dba8 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
@@ -338,6 +338,11 @@
mv.visitEnd();
}
+ private boolean isIgnoredMethod(final Method delegatedMethod)
+ {
+ return "writeReplace".equals(delegatedMethod.getName());
+ }
+
/**
* Directly delegate all non intercepted nor decorated methods to the internal instance.
*
@@ -348,7 +353,7 @@
{
for (Method delegatedMethod : noninterceptedMethods)
{
- if (unproxyableMethod(delegatedMethod))
+ if (unproxyableMethod(delegatedMethod) || isIgnoredMethod(delegatedMethod))
{
continue;
}
@@ -422,6 +427,10 @@
{
return;
}
+ if (isIgnoredMethod(method))
+ {
+ return;
+ }
Class<?> returnType = method.getReturnType();
Class<?>[] parameterTypes = method.getParameterTypes();
diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
index 73e25a8..c652284 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
@@ -387,6 +387,11 @@
for (Method delegatedMethod : noninterceptedMethods)
{
+ if (isIgnoredMethod(delegatedMethod))
+ {
+ return;
+ }
+
String methodDescriptor = Type.getMethodDescriptor(delegatedMethod);
//X TODO handle generic exception types?
@@ -439,8 +444,18 @@
}
+ private boolean isIgnoredMethod(final Method delegatedMethod)
+ {
+ return "writeReplace".equals(delegatedMethod.getName());
+ }
+
private void generateDelegationMethod(ClassWriter cw, Method method, int methodIndex, Class<?> classToProxy, String proxyClassFileName)
{
+ if (isIgnoredMethod(method))
+ {
+ return;
+ }
+
Class<?> returnType = method.getReturnType();
Class<?>[] parameterTypes = method.getParameterTypes();
int modifiers = method.getModifiers();
diff --git a/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/NormalScopeProxyFactoryTest.java b/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/NormalScopeProxyFactoryTest.java
index 734575e..bba0dcf 100644
--- a/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/NormalScopeProxyFactoryTest.java
+++ b/webbeans-impl/src/test/java/org/apache/webbeans/test/interceptors/factory/NormalScopeProxyFactoryTest.java
@@ -21,27 +21,39 @@
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.component.WebBeansType;
import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.container.InjectableBeanManager;
+import org.apache.webbeans.context.ApplicationContext;
+import org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler;
import org.apache.webbeans.test.AbstractUnitTest;
import org.apache.webbeans.test.interceptors.factory.beans.ClassInterceptedClass;
import org.apache.webbeans.test.interceptors.factory.beans.SomeBaseClass;
import org.apache.webbeans.proxy.NormalScopeProxyFactory;
+import org.apache.webbeans.test.util.Serializations;
import org.junit.Assert;
import org.junit.Test;
import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.spi.Context;
+import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.Producer;
import javax.inject.Provider;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
import org.apache.webbeans.test.interceptors.factory.beans.PartialBeanClass;
import org.apache.webbeans.test.interceptors.factory.beans.PartialBeanInterface;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
/**
* Test for the {@link NormalScopeProxyFactory}
@@ -209,6 +221,30 @@
}
+ // ensure we don't get:
+ // java.lang.ClassFormatError: Duplicate method name "writeReplace" with signature
+ // "()Ljava.lang.Object;" in class file org/apache/webbeans/test/interceptors/factory/
+ // NormalScopeProxyFactoryTest$IHaveAWriteReplace$$OwbNormalScopeProxy0
+ @Test
+ public void writeReplaceIsIgnoredWhenPresentInDelegate() throws Exception
+ {
+ MapBackedProxyHandler.map = null;
+ final NormalScopeProxyFactory pf = new NormalScopeProxyFactory(new WebBeansContext());
+ final ClassLoader classLoader = new URLClassLoader(new URL[0]);
+ final Class<IHaveAWriteReplace> proxyClass = pf.createProxyClass(classLoader, IHaveAWriteReplace.class);
+ proxyClass.getDeclaredMethod("writeReplace"); // ensure it exists
+
+ MapBackedProxyHandler.map = new HashMap<>();
+ final IHaveAWriteReplace proxy = pf.createProxyInstance(proxyClass, new MapBackedProxyHandler());
+ assertNotNull(proxy);
+ MapBackedProxyHandler.map.put(IHaveAWriteReplace.class, proxy);
+
+ final Object deserialized = Serializations.deserialize(Serializations.serialize(proxy));
+ assertNotNull(deserialized);
+ assertSame(proxy, deserialized);
+ MapBackedProxyHandler.map = null;
+ }
+
@Test
public void testPartialBeanProxyCreation() throws Exception
{
@@ -287,6 +323,22 @@
Assert.assertEquals(Integer.valueOf(42), protectedUsage.getProtectedIntegerMeaningOfLife());
}
+ public static class SerializableProvider<T> implements Serializable, Provider<T>
+ {
+
+ private final T value;
+
+ private SerializableProvider(final T value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public T get()
+ {
+ return value;
+ }
+ }
public static class TestContextualInstanceProvider<T> implements Provider<T>
{
private T instance;
@@ -327,4 +379,43 @@
Assert.assertNotNull(subPackageInstance);
instance.getFloat();
}
+
+ public static class IHaveAWriteReplace implements Serializable
+ {
+ Object writeReplace()
+ {
+ return null;
+ }
+ }
+
+ private static class MapBackedProxyHandler extends NormalScopedBeanInterceptorHandler
+ {
+ // ensure it is not serialized otherwise we break out test
+ private static Map<Class<?>, Object> map;
+
+ private MapBackedProxyHandler()
+ {
+ super(new InjectableBeanManager(null) // used as a mock without a WBC
+ {
+
+ @Override
+ public Context getContext(final Class<? extends Annotation> scope)
+ {
+ return new ApplicationContext();
+ }
+
+ @Override
+ public <T> CreationalContext<T> createCreationalContext(final Contextual<T> contextual)
+ {
+ return null;
+ }
+ }, null);
+ }
+
+ @Override
+ protected Object readResolve() throws ObjectStreamException
+ {
+ return map.get(IHaveAWriteReplace.class);
+ }
+ }
}