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.

Change-Id: Ie563237017e19c9c1462f549c9211fd3c3779999
Signed-off-by: Juan Hernandez <juan.hernan...@redhat.com>
(cherry picked from commit c85128b91ddd69084f0d2cf64b8b069a646492ec)
---
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/44/12844/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/12844
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie563237017e19c9c1462f549c9211fd3c3779999
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: engine_3.2
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