mirror of
https://github.com/apache/commons-collections.git
synced 2025-02-08 19:15:14 +00:00
[COLLECTIONS-580] Add validation to MultiValueMap#ReflectionFactory: only Collection classes are support.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1714360 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7a72b1983c
commit
3eee44cf63
@ -29,6 +29,11 @@
|
||||
ForClosure, InstantiateFactory, InstantiateTransformer, InvokerTransformer,
|
||||
PrototypeCloneFactory, PrototypeSerializationFactory, WhileClosure.
|
||||
</action>
|
||||
<action issue="COLLECTIONS-580" dev="tn" type="fix">
|
||||
Added validation when de-serializing a "MultiValueMap#ReflectionFactory":
|
||||
only Collection classes are allowed, otherwise an UnsupportedOperationException
|
||||
will be thrown during de-serialization.
|
||||
</action>
|
||||
<action issue="COLLECTIONS-576" dev="tn" type="fix" due-to="Stephan Roch">
|
||||
Subclasses of MultiKey did not re-calculate their hashcode after de-serialization.
|
||||
</action>
|
||||
|
@ -20,7 +20,6 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -209,6 +208,7 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
* @param value the value to remove
|
||||
* @return {@code true} if the mapping was removed, {@code false} otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean removeMapping(final Object key, final Object value) {
|
||||
final Collection<V> valuesForKey = getCollection(key);
|
||||
if (valuesForKey == null) {
|
||||
@ -434,14 +434,18 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
}
|
||||
final K key = keyIterator.next();
|
||||
final Transformer<V, Entry<K, V>> transformer = new Transformer<V, Entry<K, V>>() {
|
||||
@Override
|
||||
public Entry<K, V> transform(final V input) {
|
||||
return new Entry<K, V>() {
|
||||
@Override
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
@Override
|
||||
public V getValue() {
|
||||
return input;
|
||||
}
|
||||
@Override
|
||||
public V setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@ -519,6 +523,7 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
this.iterator = values.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
iterator.remove();
|
||||
if (values.isEmpty()) {
|
||||
@ -526,10 +531,12 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V next() {
|
||||
return iterator.next();
|
||||
}
|
||||
@ -549,6 +556,7 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T create() {
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
@ -556,6 +564,14 @@ public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> impleme
|
||||
throw new FunctorException("Cannot instantiate class: " + clazz, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {
|
||||
is.defaultReadObject();
|
||||
// ensure that the de-serialized class is a Collection, COLLECTIONS-580
|
||||
if (clazz != null && !Collection.class.isAssignableFrom(clazz)) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,6 +16,11 @@
|
||||
*/
|
||||
package org.apache.commons.collections4.map;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -387,6 +392,39 @@ public class MultiValueMapTest<K, V> extends AbstractObjectTest {
|
||||
assertEquals(new MultiValueMap<K, V>(), map);
|
||||
}
|
||||
|
||||
public void testUnsafeDeSerialization() throws Exception {
|
||||
MultiValueMap map1 = MultiValueMap.multiValueMap(new HashMap(), ArrayList.class);
|
||||
byte[] bytes = serialize(map1);
|
||||
Object result = deserialize(bytes);
|
||||
assertEquals(map1, result);
|
||||
|
||||
MultiValueMap map2 = MultiValueMap.multiValueMap(new HashMap(), (Class) String.class);
|
||||
bytes = serialize(map2);
|
||||
try {
|
||||
result = deserialize(bytes);
|
||||
fail("unsafe clazz accepted when de-serializing MultiValueMap");
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] serialize(Object object) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
|
||||
oos.writeObject(object);
|
||||
oos.close();
|
||||
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
private Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data);
|
||||
ObjectInputStream iis = new ObjectInputStream(bais);
|
||||
|
||||
return iis.readObject();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Manual serialization testing as this class cannot easily
|
||||
// extend the AbstractTestMap
|
||||
|
Loading…
x
Reference in New Issue
Block a user