(no commit message)
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 30 Jul 2010 19:38:30 +0000 (19:38 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Fri, 30 Jul 2010 19:38:30 +0000 (19:38 +0000)
support/general/src/main/java/org/wamblee/general/LookupProxyFactory.java
support/general/src/main/java/org/wamblee/general/ObjectSerializationUtils.java [new file with mode: 0644]
support/general/src/main/java/org/wamblee/general/ThreadSpecificProxyFactory.java
support/general/src/test/java/org/wamblee/general/LookupProxyFactoryTest.java
support/general/src/test/java/org/wamblee/general/ObjectSerializationUtilsTest.java [new file with mode: 0644]

index 5315186259443eadc8dae4ad73cf2858e664f63e..286e5f5651ead211874d53773753be89a7a56431 100644 (file)
@@ -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<T> {
      * 
      * @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<T> {
      * 
      * @author Erik Brakkee
      */
-    private class LookupInvocationHandler implements InvocationHandler {
+    private static class LookupInvocationHandler<T> 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<T> {
                     "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<T> {
      * @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 (file)
index 0000000..1b820f0
--- /dev/null
@@ -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 <T> Type of the object.
+     * @param aData Serialized data.
+     * @param aType Type of the object.
+     * @return Object. 
+     * @throws IOException
+     * @throws ClassNotFoundException
+     */
+    public static <T> T deserialize(byte[] aData, Class<T> aType) throws IOException, ClassNotFoundException { 
+        ByteArrayInputStream bis = new ByteArrayInputStream(aData); 
+        ObjectInputStream os = new ObjectInputStream(bis); 
+        return (T)os.readObject();
+    }
+}
index ce912ef37b53b6c54dd8a51717f6cced462991e5..81127009e4a6afc09993800789637a0001c78ce0 100644 (file)
@@ -19,24 +19,34 @@ import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
 
 /**
+ * <p>
  * Thread-specific proxy is used to create implementations of interfaces that
  * delegate to a thread-specific implementation of the service.
+ * </p>
  * 
+ * <p>
  * It can be used for instance to create a contextual reference to an entity
  * manager that delegates to a thread-specific instance.
+ * </p>
  * 
+ * <p>
  * 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.
- * 
+ * </p>
+ *
+ * <p>
  * This class is mostly used by infrastructure code (utilities) and test tools.
+ * </p>
  * 
+ * <p>
  * 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.
+ * </p>
  * 
  * @param T
  *            Interface to proxy.
index c7650906ffa2488103a72c606fcd8a6d93aca105..5dbf81ad3a78a3105b569e2355599d3cbe9e37b2 100644 (file)
@@ -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<MyInterface> factory = new LookupProxyFactory<MyInterface>(
+            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 (file)
index 0000000..a558b42
--- /dev/null
@@ -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);
+    }
+}