Updated Branches: refs/heads/sandbox/WICKET-4744-WicketObjects-use-Java-Serialization-APIs [created] 629d59163
WICKET-4744 Investigate reworking WicketObjects#clone(Object|Model) methods to use ISerializer Rework WicketObjects#cloneObject() to use ISerializer. WicketObjects#cloneModel() has special logic to avoid cloning Component instances and it is not easy to be reworked Additionally improved the API by using type inference for the return types. Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/629d5916 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/629d5916 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/629d5916 Branch: refs/heads/sandbox/WICKET-4744-WicketObjects-use-Java-Serialization-APIs Commit: 629d591630a0e70e9e7d17a3ad87c223232f7762 Parents: aa84e95 Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Thu Jan 16 15:05:31 2014 +0200 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Thu Jan 16 15:05:31 2014 +0200 ---------------------------------------------------------------------- .../java/org/apache/wicket/Application.java | 2 +- .../wicket/core/util/lang/WicketObjects.java | 87 ++++---------------- .../html/TransparentWebMarkupContainerTest.java | 2 +- .../wicket/page/PageAccessSynchronizerTest.java | 2 +- .../wicket/util/lang/WicketObjectsTest.java | 6 +- .../apache/wicket/guice/GuiceInjectorTest.java | 2 +- .../wicket/proxy/LazyInitProxyFactoryTest.java | 33 +++++++- .../wicket/spring/SpringBeanLocatorTest.java | 24 +++++- 8 files changed, 73 insertions(+), 85 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-core/src/main/java/org/apache/wicket/Application.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/Application.java b/wicket-core/src/main/java/org/apache/wicket/Application.java index ff4b501..aae9d55b 100644 --- a/wicket-core/src/main/java/org/apache/wicket/Application.java +++ b/wicket-core/src/main/java/org/apache/wicket/Application.java @@ -570,7 +570,7 @@ public abstract class Application implements UnboundListener, IEventSink */ private void addInitializer(final String className) { - IInitializer initializer = (IInitializer)WicketObjects.newInstance(className); + IInitializer initializer = WicketObjects.newInstance(className); if (initializer != null) { initializers.add(initializer); http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-core/src/main/java/org/apache/wicket/core/util/lang/WicketObjects.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/WicketObjects.java b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/WicketObjects.java index bb7fa21..9065717 100644 --- a/wicket-core/src/main/java/org/apache/wicket/core/util/lang/WicketObjects.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/util/lang/WicketObjects.java @@ -127,7 +127,7 @@ public class WicketObjects } else { - serializer = new JavaSerializer("SerializingObjectSizeOfStrategy"); + serializer = new JavaSerializer(SerializingObjectSizeOfStrategy.class.getName()); } byte[] serialized = serializer.serialize(object); int size = -1; @@ -240,11 +240,15 @@ public class WicketObjects * serializable to be cloned. This method will not clone wicket Components, it will just reuse * those instances so that the complete component tree is not copied over only the model data. * + * <strong>Warning</strong>: this method uses Java Serialization APIs to be able to avoid cloning + * of {@link org.apache.wicket.Component} instances. If the application uses custom + * {@link org.apache.wicket.serialize.ISerializer} then most probably this method cannot be used. + * * @param object * The object to clone * @return A deep copy of the object */ - public static Object cloneModel(final Object object) + public static <T> T cloneModel(final T object) { if (object == null) { @@ -260,13 +264,9 @@ public class WicketObjects oos.writeObject(object); ObjectInputStream ois = new ReplaceObjectInputStream(new ByteArrayInputStream( out.toByteArray()), replacedObjects, object.getClass().getClassLoader()); - return ois.readObject(); - } - catch (ClassNotFoundException e) - { - throw new WicketRuntimeException("Internal error cloning object", e); + return (T) ois.readObject(); } - catch (IOException e) + catch (ClassNotFoundException | IOException e) { throw new WicketRuntimeException("Internal error cloning object", e); } @@ -290,7 +290,7 @@ public class WicketObjects * @return A deep copy of the object * @see #cloneModel(Object) */ - public static Object cloneObject(final Object object) + public static <T> T cloneObject(final T object) { if (object == null) { @@ -298,67 +298,10 @@ public class WicketObjects } else { - try - { - final ByteArrayOutputStream out = new ByteArrayOutputStream(256); - ObjectOutputStream oos = new ObjectOutputStream(out); - oos.writeObject(object); - ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( - out.toByteArray())) - { - // This override is required to resolve classes inside in different bundle, i.e. - // The classes can be resolved by OSGI classresolver implementation - @Override - protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, - ClassNotFoundException - { - String className = desc.getName(); - - try - { - return Class.forName(className, true, object.getClass() - .getClassLoader()); - } - catch (ClassNotFoundException ex1) - { - // ignore this exception. - log.debug("Class not found by using objects own classloader, trying the IClassResolver"); - } - - - Application application = Application.get(); - ApplicationSettings applicationSettings = application.getApplicationSettings(); - IClassResolver classResolver = applicationSettings.getClassResolver(); - - Class<?> candidate = null; - try - { - candidate = classResolver.resolveClass(className); - if (candidate == null) - { - candidate = super.resolveClass(desc); - } - } - catch (WicketRuntimeException ex) - { - if (ex.getCause() instanceof ClassNotFoundException) - { - throw (ClassNotFoundException)ex.getCause(); - } - } - return candidate; - } - }; - return ois.readObject(); - } - catch (ClassNotFoundException e) - { - throw new WicketRuntimeException("Internal error cloning object", e); - } - catch (IOException e) - { - throw new WicketRuntimeException("Internal error cloning object", e); - } + ISerializer serializer = Application.get().getFrameworkSettings().getSerializer(); + byte[] serialized = serializer.serialize(object); + Object deserialized = serializer.deserialize(serialized); + return (T) deserialized; } } @@ -370,14 +313,14 @@ public class WicketObjects * The full class name * @return The new object instance */ - public static Object newInstance(final String className) + public static <T> T newInstance(final String className) { if (!Strings.isEmpty(className)) { try { Class<?> c = WicketObjects.resolveClass(className); - return c.newInstance(); + return (T) c.newInstance(); } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java index 9ea081b..f1ac3b2 100644 --- a/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/TransparentWebMarkupContainerTest.java @@ -115,7 +115,7 @@ public class TransparentWebMarkupContainerTest extends WicketTestCase @Override public void touchPage(IManageablePage page) { - page = (IManageablePage)WicketObjects.cloneObject(page); + page = WicketObjects.cloneObject(page); super.touchPage(page); } }; http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java b/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java index b5cb403..20028af 100644 --- a/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/page/PageAccessSynchronizerTest.java @@ -298,7 +298,7 @@ public class PageAccessSynchronizerTest extends Assert // make sure we can serialize the synchronizer - final PageAccessSynchronizer sync2 = (PageAccessSynchronizer)WicketObjects.cloneObject(sync); + final PageAccessSynchronizer sync2 = WicketObjects.cloneObject(sync); assertTrue(sync != sync2); // make sure the clone does not retain locks by attempting to lock page locked by locker1 in http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-core/src/test/java/org/apache/wicket/util/lang/WicketObjectsTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/util/lang/WicketObjectsTest.java b/wicket-core/src/test/java/org/apache/wicket/util/lang/WicketObjectsTest.java index 0cd2082..d34b055 100644 --- a/wicket-core/src/test/java/org/apache/wicket/util/lang/WicketObjectsTest.java +++ b/wicket-core/src/test/java/org/apache/wicket/util/lang/WicketObjectsTest.java @@ -83,9 +83,9 @@ public class WicketObjectsTest extends WicketTestCase @Test public void componentClone() { - PropertyModel<String> pm = new PropertyModel<String>(new TextField<String>("test", - new Model<String>("test")), "modelObject"); - PropertyModel<String> pm2 = (PropertyModel<String>)WicketObjects.cloneModel(pm); + PropertyModel<String> pm = new PropertyModel<String>(new TextField<>("test", + Model.of("test")), "modelObject"); + PropertyModel<String> pm2 = WicketObjects.cloneModel(pm); assertTrue(pm.getObject() == pm2.getObject()); } http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java b/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java index 7ba0bb7..f9b4f36 100644 --- a/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java @@ -94,7 +94,7 @@ public class GuiceInjectorTest extends Assert doChecksForComponent(testComponent); // Serialize and deserialize the object, and check it still works. - TestComponentInterface clonedComponent = (TestComponentInterface)WicketObjects.cloneObject(testComponent); + TestComponentInterface clonedComponent = WicketObjects.cloneObject(testComponent); doChecksForComponent(clonedComponent); // Test injection of a class that does not extend Component http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java ---------------------------------------------------------------------- diff --git a/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java b/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java index 8231d49..1d7729d 100644 --- a/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java +++ b/wicket-ioc/src/test/java/org/apache/wicket/proxy/LazyInitProxyFactoryTest.java @@ -20,14 +20,19 @@ import static org.hamcrest.CoreMatchers.instanceOf; import java.lang.reflect.Proxy; +import org.apache.wicket.ThreadContext; import org.apache.wicket.core.util.lang.WicketObjects; +import org.apache.wicket.mock.MockApplication; +import org.apache.wicket.protocol.http.mock.MockServletContext; import org.apache.wicket.proxy.LazyInitProxyFactory.ProxyReplacement; import org.apache.wicket.proxy.util.ConcreteObject; import org.apache.wicket.proxy.util.IInterface; import org.apache.wicket.proxy.util.IObjectMethodTester; import org.apache.wicket.proxy.util.InterfaceObject; import org.apache.wicket.proxy.util.ObjectMethodTester; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; /** @@ -75,6 +80,26 @@ public class LazyInitProxyFactoryTest extends Assert } }; + private MockApplication application; + + @Before + public void before() + { + // the application is needed for WicketObjects#cloneObject() calls + application = new MockApplication(); + ThreadContext.setApplication(application); + application.setName(LazyInitProxyFactoryTest.class.getName()); + application.setServletContext(new MockServletContext(application, "/")); + application.initApplication(); + } + + @After + public void after() + { + application.internalDestroy(); + ThreadContext.detach(); + } + /** * Tests lazy init proxy to represent interfaces */ @@ -96,7 +121,7 @@ public class LazyInitProxyFactoryTest extends Assert assertEquals(proxy.getMessage(), "interface"); // test serialization - IInterface proxy2 = (IInterface)WicketObjects.cloneObject(proxy); + IInterface proxy2 = WicketObjects.cloneObject(proxy); assertTrue(proxy != proxy2); assertEquals(proxy2.getMessage(), "interface"); @@ -143,7 +168,7 @@ public class LazyInitProxyFactoryTest extends Assert assertEquals(proxy.getMessage(), "concrete"); // test serialization - ConcreteObject proxy2 = (ConcreteObject)WicketObjects.cloneObject(proxy); + ConcreteObject proxy2 = WicketObjects.cloneObject(proxy); assertTrue(proxy != proxy2); assertEquals(proxy2.getMessage(), "concrete"); @@ -179,8 +204,8 @@ public class LazyInitProxyFactoryTest extends Assert ProxyReplacement ser = new ProxyReplacement(ConcreteObject.class.getName(), concreteObjectLocator); - ConcreteObject proxy2 = (ConcreteObject)WicketObjects.cloneObject(ser); - assertEquals(proxy2.getMessage(), "concrete"); + Object proxy2 = WicketObjects.cloneObject(ser); + assertEquals(((ConcreteObject)proxy2).getMessage(), "concrete"); } /** http://git-wip-us.apache.org/repos/asf/wicket/blob/629d5916/wicket-spring/src/test/java/org/apache/wicket/spring/SpringBeanLocatorTest.java ---------------------------------------------------------------------- diff --git a/wicket-spring/src/test/java/org/apache/wicket/spring/SpringBeanLocatorTest.java b/wicket-spring/src/test/java/org/apache/wicket/spring/SpringBeanLocatorTest.java index 1f9109e..24200c9 100644 --- a/wicket-spring/src/test/java/org/apache/wicket/spring/SpringBeanLocatorTest.java +++ b/wicket-spring/src/test/java/org/apache/wicket/spring/SpringBeanLocatorTest.java @@ -16,9 +16,13 @@ */ package org.apache.wicket.spring; +import org.apache.wicket.ThreadContext; +import org.apache.wicket.mock.MockApplication; +import org.apache.wicket.protocol.http.mock.MockServletContext; import org.apache.wicket.spring.test.ApplicationContextMock; import org.apache.wicket.spring.test.SpringContextLocatorMock; import org.apache.wicket.core.util.lang.WicketObjects; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -35,6 +39,15 @@ public class SpringBeanLocatorTest extends Assert private ISpringContextLocator ctxLocator; + private MockApplication application; + + @After + public void after() + { + application.internalDestroy(); + ThreadContext.detach(); + } + /** * */ @@ -43,6 +56,13 @@ public class SpringBeanLocatorTest extends Assert { ctx = new ApplicationContextMock(); ctxLocator = new SpringContextLocatorMock(ctx); + + // the application is needed for WicketObjects#cloneObject() calls + application = new MockApplication(); + ThreadContext.setApplication(application); + application.setName(SpringBeanLocatorTest.class.getName()); + application.setServletContext(new MockServletContext(application, "/")); + application.initApplication(); } /** @@ -69,7 +89,7 @@ public class SpringBeanLocatorTest extends Assert ctx.putBean("bean", bean); - SpringBeanLocator locator = (SpringBeanLocator)WicketObjects.cloneObject(new SpringBeanLocator( + SpringBeanLocator locator = WicketObjects.cloneObject(new SpringBeanLocator( Bean.class, ctxLocator)); assertNotNull(locator.locateProxyTarget()); @@ -139,7 +159,7 @@ public class SpringBeanLocatorTest extends Assert Bean bean = new Bean(); ctx.putBean("bean", bean); - SpringBeanLocator locator = (SpringBeanLocator)WicketObjects.cloneObject(new SpringBeanLocator( + SpringBeanLocator locator = WicketObjects.cloneObject(new SpringBeanLocator( "bean", Bean.class, ctxLocator)); assertNotNull(locator.locateProxyTarget());
