Juan Hernandez has uploaded a new change for review.

Change subject: core: Don't use commons collections clone method
......................................................................

core: Don't use commons collections clone method

The commons collections package provides a mechanism to clone an object
doing serialization and then deserialization. Unfortunatelly the
implementation uses its own class loader (the class loader that loaded
commons collections itself) to load the class of the serialized object.
This means that the deserialization will fail if commons collections
happens to use be loaded by a class loader that doesn't have access to
the class being cloned. This is what happens if we try to use a JBoss
module instead of dropping commons-collections in the lib directory of
the ear.

This patch implements the clone method so that it uses the context class
loader if possible, this solves the issue with separate class loaders.

Bacported from master commit c85128b91ddd69084f0d2cf64b8b069a646492ec.

Change-Id: Ice10d1d6d1e49b5c1ad6bd009a956902dd888e6a
Signed-off-by: Juan Hernandez <juan.hernan...@redhat.com>
---
M 
backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/collections/CopyOnAccessMap.java
1 file changed, 70 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/22/12622/1

diff --git 
a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/collections/CopyOnAccessMap.java
 
b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/collections/CopyOnAccessMap.java
index 42e1450..ee73c46 100644
--- 
a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/collections/CopyOnAccessMap.java
+++ 
b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/collections/CopyOnAccessMap.java
@@ -1,5 +1,11 @@
 package org.ovirt.engine.core.utils.collections;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -7,10 +13,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import org.apache.commons.collections.Transformer;
-import org.apache.commons.collections.TransformerUtils;
-
 
 /**
  * A map decorator for providing copies of keys and values upon invocation of 
accessor methods. With this decorator the
@@ -24,11 +26,9 @@
 
     private static final int REALLOCATION_FACTOR = 2;
     private Map<K, V> innerMap;
-    Transformer cloner;
 
     public CopyOnAccessMap(Map<K, V> innerMap) {
         this.innerMap = innerMap;
-        cloner = TransformerUtils.cloneTransformer();
     }
 
     @Override
@@ -58,10 +58,71 @@
 
     @SuppressWarnings("unchecked")
     private <O> O clone(O originalKey) {
-        return (O) cloner.transform(originalKey);
+        // We use an intermediate buffer to hold the serialized form of the
+        // object:
+        byte[] buffer = null;
+
+        // Serialize the object to an array of bytes:
+        ByteArrayOutputStream bufferOut = null;
+        ObjectOutputStream objectOut = null;
+        try {
+            bufferOut = new ByteArrayOutputStream(512);
+            objectOut = new ObjectOutputStream(bufferOut);
+            objectOut.writeObject(originalKey);
+            buffer = bufferOut.toByteArray();
+        }
+        catch (IOException exception) {
+            throw new RuntimeException(exception);
+        }
+        finally {
+            if (objectOut != null) {
+                try {
+                    objectOut.close();
+                }
+                catch (IOException exception) {
+                    // Ignored.
+                }
+            }
+        }
+
+        // Create a new instance of the object deserializing it from the
+        // buffer:
+        ByteArrayInputStream bufferIn = null;
+        ObjectInputStream objectIn = null;
+        try {
+            bufferIn = new ByteArrayInputStream(buffer);
+            objectIn = new ObjectInputStream(bufferIn) {
+                @Override
+                protected Class<?> resolveClass(ObjectStreamClass description) 
throws IOException, ClassNotFoundException {
+                    // First try with the context class loader, if that fails
+                    // then just call the overridden method:
+                    try {
+                        return Class.forName(description.getName(), false, 
Thread.currentThread().getContextClassLoader());
+                    }
+                    catch (ClassNotFoundException exception) {
+                        return super.resolveClass(description);
+                    }
+                }
+            };
+            return (O) objectIn.readObject();
+        }
+        catch (IOException exception) {
+            throw new RuntimeException(exception);
+        }
+        catch (ClassNotFoundException exception) {
+            throw new RuntimeException(exception);
+        }
+        finally {
+            if (objectIn != null) {
+                try {
+                    objectIn.close();
+                }
+                catch (IOException exception) {
+                    // Ignored.
+                }
+            }
+        }
     }
-
-
 
     @Override
     public V put(K key, V value) {


--
To view, visit http://gerrit.ovirt.org/12622
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ice10d1d6d1e49b5c1ad6bd009a956902dd888e6a
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Juan Hernandez <juan.hernan...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to