From 66d09690a9c113766d63df4e7623534fb278f265 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Fri, 30 Jul 2010 19:38:30 +0000 Subject: [PATCH] --- .../wamblee/general/LookupProxyFactory.java | 23 ++++++-- .../general/ObjectSerializationUtils.java | 59 +++++++++++++++++++ .../general/ThreadSpecificProxyFactory.java | 12 +++- .../general/LookupProxyFactoryTest.java | 35 +++++++++++ .../general/ObjectSerializationUtilsTest.java | 34 +++++++++++ 5 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 support/general/src/main/java/org/wamblee/general/ObjectSerializationUtils.java create mode 100644 support/general/src/test/java/org/wamblee/general/ObjectSerializationUtilsTest.java diff --git a/support/general/src/main/java/org/wamblee/general/LookupProxyFactory.java b/support/general/src/main/java/org/wamblee/general/LookupProxyFactory.java index 53151862..286e5f56 100644 --- a/support/general/src/main/java/org/wamblee/general/LookupProxyFactory.java +++ b/support/general/src/main/java/org/wamblee/general/LookupProxyFactory.java @@ -15,6 +15,7 @@ */ package org.wamblee.general; +import java.io.Serializable; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -25,7 +26,7 @@ import javax.naming.NamingException; /** * Proxy factory that can provide contextual references to objects retrieved - * through a lookup mechanism. + * through a lookup mechanism. The returned proxies are serializable. * * @param T * Interface to proxy. @@ -39,7 +40,7 @@ public class LookupProxyFactory { * * @author Erik Brakkee */ - public static interface Lookup { + public static interface Lookup extends Serializable { /** * Looks up the object. * @return Object (non-null) @@ -69,7 +70,19 @@ public class LookupProxyFactory { * * @author Erik Brakkee */ - private class LookupInvocationHandler implements InvocationHandler { + private static class LookupInvocationHandler implements InvocationHandler, Serializable { + + private Class clazz; + private Lookup lookup; + + /** + * Constructs the invocation handler. + * @param aLookup Lookup class. + */ + public LookupInvocationHandler(Class aClass, Lookup aLookup) { + clazz = aClass; + lookup = aLookup; + } @Override /** @@ -85,7 +98,7 @@ public class LookupProxyFactory { "Error looking up object", e); } if (svcObj == null) { - throw new LookupException("Object at is null"); + throw new LookupException("Object is null"); } if (!clazz.isInstance(svcObj)) { throw new LookupException("Object '" + svcObj + "' is not of type " + clazz.getName() + @@ -130,7 +143,7 @@ public class LookupProxyFactory { * @return Proxy. */ public T getProxy() { - InvocationHandler handler = new LookupInvocationHandler(); + InvocationHandler handler = new LookupInvocationHandler(clazz, lookup); Class proxyClass = Proxy.getProxyClass(clazz.getClassLoader(), new Class[] { clazz }); T proxy; diff --git a/support/general/src/main/java/org/wamblee/general/ObjectSerializationUtils.java b/support/general/src/main/java/org/wamblee/general/ObjectSerializationUtils.java new file mode 100644 index 00000000..1b820f03 --- /dev/null +++ b/support/general/src/main/java/org/wamblee/general/ObjectSerializationUtils.java @@ -0,0 +1,59 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.general; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Utility for serializating and deserializing objects. + * + * @author Erik Brakkee + */ +public class ObjectSerializationUtils { + + /** + * Serialize an object to a byte array. + * @param aObject Object ot serialize. + * @return Byte array. + * @throws IOException + */ + public static byte[] serialize(Object aObject) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream os = new ObjectOutputStream(bos); + os.writeObject(aObject); + os.flush(); + return bos.toByteArray(); + } + + /** + * Desrializes an object from a byte array. + * @param Type of the object. + * @param aData Serialized data. + * @param aType Type of the object. + * @return Object. + * @throws IOException + * @throws ClassNotFoundException + */ + public static T deserialize(byte[] aData, Class aType) throws IOException, ClassNotFoundException { + ByteArrayInputStream bis = new ByteArrayInputStream(aData); + ObjectInputStream os = new ObjectInputStream(bis); + return (T)os.readObject(); + } +} diff --git a/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java b/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java index ce912ef3..81127009 100644 --- a/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java +++ b/support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java @@ -19,24 +19,34 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** + *

* Thread-specific proxy is used to create implementations of interfaces that * delegate to a thread-specific implementation of the service. + *

* + *

* It can be used for instance to create a contextual reference to an entity * manager that delegates to a thread-specific instance. + *

* + *

* The {@link #set(Object)} method sets the current service instance for the * current thread. The {@link #get()} method gets the current service instance * for the current thread. The {@link #getProxy()} method gets a proxy that will * delegate at runtime to the thread-specific instance. The result from this * method can be passed at construction of an object that will be used by * multiple threads. - * + *

+ * + *

* This class is mostly used by infrastructure code (utilities) and test tools. + *

* + *

* Care has been taken so that the invocation handler is serializable. However, * it is only serializable within one virtual machine. It cannot be used in a * distributed context where it can be sent to another JVM. + *

* * @param T * Interface to proxy. diff --git a/support/general/src/test/java/org/wamblee/general/LookupProxyFactoryTest.java b/support/general/src/test/java/org/wamblee/general/LookupProxyFactoryTest.java index c7650906..5dbf81ad 100644 --- a/support/general/src/test/java/org/wamblee/general/LookupProxyFactoryTest.java +++ b/support/general/src/test/java/org/wamblee/general/LookupProxyFactoryTest.java @@ -18,6 +18,8 @@ package org.wamblee.general; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.io.Serializable; + import javax.naming.InitialContext; import org.junit.After; @@ -93,5 +95,38 @@ public class LookupProxyFactoryTest { assertEquals(NAA_NA_NA_NAA_NA, e.getMessage()); } } + + private static final class MyLookup implements Lookup { + + @Override + public Object lookup() throws Exception { + return new MyInterface() { + + @Override + public int execute() { + return 10; + } + }; + } + } + + @Test + public void testProxyMustBerializable() throws Exception { + lookup = new MyLookup(); + LookupProxyFactory factory = new LookupProxyFactory( + MyInterface.class, lookup); + proxy = factory.getProxy(); + + assertEquals(10, proxy.execute()); + + assertTrue(proxy instanceof Serializable); + + proxy = ObjectSerializationUtils.deserialize(ObjectSerializationUtils.serialize(proxy), + MyInterface.class); + + // and it should still work + assertEquals(10, proxy.execute()); + } + } diff --git a/support/general/src/test/java/org/wamblee/general/ObjectSerializationUtilsTest.java b/support/general/src/test/java/org/wamblee/general/ObjectSerializationUtilsTest.java new file mode 100644 index 00000000..a558b420 --- /dev/null +++ b/support/general/src/test/java/org/wamblee/general/ObjectSerializationUtilsTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.general; + +import static junit.framework.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +public class ObjectSerializationUtilsTest { + + @Test + public void testSerialize() throws Exception { + String s = "hello world"; + byte[] data = ObjectSerializationUtils.serialize(s); + assertNotNull(data); + String t = ObjectSerializationUtils.deserialize(data, String.class); + assertEquals(s, t); + } +} -- 2.31.1