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