You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2014/05/19 12:29:34 UTC
git commit: Validate method for CollectionType
Repository: cassandra
Updated Branches:
refs/heads/cassandra-2.1 33bd8c207 -> 590b3b23a
Validate method for CollectionType
patch by slebresne; reviewed by thobbs for CASSANDRA-7208
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/590b3b23
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/590b3b23
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/590b3b23
Branch: refs/heads/cassandra-2.1
Commit: 590b3b23ac2db333048c52c5323b78d0630605ae
Parents: 33bd8c2
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Mon May 19 12:28:49 2014 +0200
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Mon May 19 12:28:49 2014 +0200
----------------------------------------------------------------------
CHANGES.txt | 1 +
.../cassandra/db/marshal/CollectionType.java | 5 --
.../serializers/CollectionSerializer.java | 12 +--
.../cassandra/serializers/ListSerializer.java | 15 ++++
.../cassandra/serializers/MapSerializer.java | 18 ++++
.../cassandra/serializers/SetSerializer.java | 15 ++++
.../db/marshal/CollectionTypeTest.java | 93 ++++++++++++++++++++
7 files changed, 149 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 3a9eb2b..4efaa46 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -15,6 +15,7 @@
* Make batchlog replay asynchronous (CASSANDRA-6134)
* remove unused classes (CASSANDRA-7197)
* Limit user types to the keyspace they are defined in (CASSANDRA-6643)
+ * Add validate method to CollectionType (CASSANDRA-7208)
Merged from 2.0:
* (Hadoop) support authentication in CqlRecordReader (CASSANDRA-7221)
* (Hadoop) Close java driver Cluster in CQLRR.close (CASSANDRA-7228)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/db/marshal/CollectionType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
index 7f75a5f..b1d8da1 100644
--- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
@@ -85,11 +85,6 @@ public abstract class CollectionType<T> extends AbstractType<T>
}
}
- public void validate(ByteBuffer bytes)
- {
- valueComparator().validate(bytes);
- }
-
@Override
public boolean isCompatibleWith(AbstractType<?> previous)
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/CollectionSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/CollectionSerializer.java b/src/java/org/apache/cassandra/serializers/CollectionSerializer.java
index 5452a96..7cddb12 100644
--- a/src/java/org/apache/cassandra/serializers/CollectionSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/CollectionSerializer.java
@@ -25,15 +25,11 @@ import org.apache.cassandra.utils.ByteBufferUtil;
public abstract class CollectionSerializer<T> implements TypeSerializer<T>
{
- public void validate(ByteBuffer bytes) throws MarshalException
- {
- // The collection is not currently being properly validated.
- }
-
protected abstract List<ByteBuffer> serializeValues(T value);
protected abstract int getElementCount(T value);
public abstract T deserializeForNativeProtocol(ByteBuffer buffer, int version);
+ public abstract void validateForNativeProtocol(ByteBuffer buffer, int version);
public ByteBuffer serialize(T value)
{
@@ -52,6 +48,12 @@ public abstract class CollectionSerializer<T> implements TypeSerializer<T>
return deserializeForNativeProtocol(bytes, 3);
}
+ public void validate(ByteBuffer bytes) throws MarshalException
+ {
+ // Same thing than above
+ validateForNativeProtocol(bytes, 3);
+ }
+
public static ByteBuffer pack(List<ByteBuffer> buffers, int elements, int version)
{
int size = 0;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/ListSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/ListSerializer.java b/src/java/org/apache/cassandra/serializers/ListSerializer.java
index e662341..b64c012 100644
--- a/src/java/org/apache/cassandra/serializers/ListSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/ListSerializer.java
@@ -60,6 +60,21 @@ public class ListSerializer<T> extends CollectionSerializer<List<T>>
return value.size();
}
+ public void validateForNativeProtocol(ByteBuffer bytes, int version)
+ {
+ try
+ {
+ ByteBuffer input = bytes.duplicate();
+ int n = readCollectionSize(input, version);
+ for (int i = 0; i < n; i++)
+ elements.validate(readValue(input, version));
+ }
+ catch (BufferUnderflowException e)
+ {
+ throw new MarshalException("Not enough bytes to read a list");
+ }
+ }
+
public List<T> deserializeForNativeProtocol(ByteBuffer bytes, int version)
{
try
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/MapSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/MapSerializer.java b/src/java/org/apache/cassandra/serializers/MapSerializer.java
index 5d349dd..34e7c05 100644
--- a/src/java/org/apache/cassandra/serializers/MapSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/MapSerializer.java
@@ -67,6 +67,24 @@ public class MapSerializer<K, V> extends CollectionSerializer<Map<K, V>>
return value.size();
}
+ public void validateForNativeProtocol(ByteBuffer bytes, int version)
+ {
+ try
+ {
+ ByteBuffer input = bytes.duplicate();
+ int n = readCollectionSize(input, version);
+ for (int i = 0; i < n; i++)
+ {
+ keys.validate(readValue(input, version));
+ values.validate(readValue(input, version));
+ }
+ }
+ catch (BufferUnderflowException e)
+ {
+ throw new MarshalException("Not enough bytes to read a set");
+ }
+ }
+
public Map<K, V> deserializeForNativeProtocol(ByteBuffer bytes, int version)
{
try
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/src/java/org/apache/cassandra/serializers/SetSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/SetSerializer.java b/src/java/org/apache/cassandra/serializers/SetSerializer.java
index 812dd68..136b4e0 100644
--- a/src/java/org/apache/cassandra/serializers/SetSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/SetSerializer.java
@@ -60,6 +60,21 @@ public class SetSerializer<T> extends CollectionSerializer<Set<T>>
return value.size();
}
+ public void validateForNativeProtocol(ByteBuffer bytes, int version)
+ {
+ try
+ {
+ ByteBuffer input = bytes.duplicate();
+ int n = readCollectionSize(input, version);
+ for (int i = 0; i < n; i++)
+ elements.validate(readValue(input, version));
+ }
+ catch (BufferUnderflowException e)
+ {
+ throw new MarshalException("Not enough bytes to read a set");
+ }
+ }
+
public Set<T> deserializeForNativeProtocol(ByteBuffer bytes, int version)
{
try
http://git-wip-us.apache.org/repos/asf/cassandra/blob/590b3b23/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
index c51d304..18156c3 100644
--- a/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
+++ b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
+import java.util.*;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -25,8 +26,10 @@ import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.serializers.*;
public class CollectionTypeTest
{
@@ -112,4 +115,94 @@ public class CollectionTypeTest
}
}
}
+
+ @Test
+ public void listSerDerTest()
+ {
+ ListSerializer<String> sls = ListType.getInstance(UTF8Type.instance).getSerializer();
+ ListSerializer<Integer> ils = ListType.getInstance(Int32Type.instance).getSerializer();
+
+ List<String> sl = Arrays.asList("Foo", "Bar");
+ List<Integer> il = Arrays.asList(3, 1, 5);
+
+ ByteBuffer sb = sls.serialize(sl);
+ ByteBuffer ib = ils.serialize(il);
+
+ assertEquals(sls.deserialize(sb), sl);
+ assertEquals(ils.deserialize(ib), il);
+
+ sls.validate(sb);
+ ils.validate(ib);
+
+ // string list with integer list type
+ assertInvalid(ils, sb);
+ // non list value
+ assertInvalid(sls, UTF8Type.instance.getSerializer().serialize("foo"));
+ }
+
+ @Test
+ public void setSerDerTest()
+ {
+ SetSerializer<String> sss = SetType.getInstance(UTF8Type.instance).getSerializer();
+ SetSerializer<Integer> iss = SetType.getInstance(Int32Type.instance).getSerializer();
+
+ Set<String> ss = new HashSet(){{ add("Foo"); add("Bar"); }};
+ Set<Integer> is = new HashSet(){{ add(3); add(1); add(5); }};
+
+ ByteBuffer sb = sss.serialize(ss);
+ ByteBuffer ib = iss.serialize(is);
+
+ assertEquals(sss.deserialize(sb), ss);
+ assertEquals(iss.deserialize(ib), is);
+
+ sss.validate(sb);
+ iss.validate(ib);
+
+ // string set with integer set type
+ assertInvalid(iss, sb);
+ // non set value
+ assertInvalid(sss, UTF8Type.instance.getSerializer().serialize("foo"));
+ }
+
+ @Test
+ public void setMapDerTest()
+ {
+ MapSerializer<String, String> sms = MapType.getInstance(UTF8Type.instance, UTF8Type.instance).getSerializer();
+ MapSerializer<Integer, Integer> ims = MapType.getInstance(Int32Type.instance, Int32Type.instance).getSerializer();
+
+ Map<String, String> sm = new HashMap(){{ put("Foo", "xxx"); put("Bar", "yyy"); }};
+ Map<Integer, Integer> im = new HashMap(){{ put(3, 0); put(1, 8); put(5, 2); }};
+
+ ByteBuffer sb = sms.serialize(sm);
+ ByteBuffer ib = ims.serialize(im);
+
+ assertEquals(sms.deserialize(sb), sm);
+ assertEquals(ims.deserialize(ib), im);
+
+ sms.validate(sb);
+ ims.validate(ib);
+
+ // string map with integer map type
+ assertInvalid(ims, sb);
+ // non map value
+ assertInvalid(sms, UTF8Type.instance.getSerializer().serialize("foo"));
+
+ MapSerializer<Integer, String> sims = MapType.getInstance(Int32Type.instance, UTF8Type.instance).getSerializer();
+ MapSerializer<String, Integer> isms = MapType.getInstance(UTF8Type.instance, Int32Type.instance).getSerializer();
+
+ // only key are invalid
+ assertInvalid(isms, sb);
+ // only values are invalid
+ assertInvalid(sims, sb);
+ }
+
+ private void assertInvalid(TypeSerializer<?> type, ByteBuffer value)
+ {
+ try {
+ type.validate(value);
+ fail("Value " + ByteBufferUtil.bytesToHex(value) + " shouldn't be valid for type " + type);
+ } catch (MarshalException e) {
+ // ok, that's what we want
+ }
+ }
}