|
|
@@ -805,6 +805,23 @@ public abstract class StreamOutput extends OutputStream {
|
|
|
}
|
|
|
));
|
|
|
|
|
|
+ private static Class<?> getGenericType(Object value) {
|
|
|
+ if (value instanceof List) {
|
|
|
+ return List.class;
|
|
|
+ } else if (value instanceof Object[]) {
|
|
|
+ return Object[].class;
|
|
|
+ } else if (value instanceof Map) {
|
|
|
+ return Map.class;
|
|
|
+ } else if (value instanceof Set) {
|
|
|
+ return Set.class;
|
|
|
+ } else if (value instanceof ReadableInstant) {
|
|
|
+ return ReadableInstant.class;
|
|
|
+ } else if (value instanceof BytesReference) {
|
|
|
+ return BytesReference.class;
|
|
|
+ } else {
|
|
|
+ return value.getClass();
|
|
|
+ }
|
|
|
+ }
|
|
|
/**
|
|
|
* Notice: when serialization a map, the stream out map with the stream in map maybe have the
|
|
|
* different key-value orders, they will maybe have different stream order.
|
|
|
@@ -816,22 +833,7 @@ public abstract class StreamOutput extends OutputStream {
|
|
|
writeByte((byte) -1);
|
|
|
return;
|
|
|
}
|
|
|
- final Class type;
|
|
|
- if (value instanceof List) {
|
|
|
- type = List.class;
|
|
|
- } else if (value instanceof Object[]) {
|
|
|
- type = Object[].class;
|
|
|
- } else if (value instanceof Map) {
|
|
|
- type = Map.class;
|
|
|
- } else if (value instanceof Set) {
|
|
|
- type = Set.class;
|
|
|
- } else if (value instanceof ReadableInstant) {
|
|
|
- type = ReadableInstant.class;
|
|
|
- } else if (value instanceof BytesReference) {
|
|
|
- type = BytesReference.class;
|
|
|
- } else {
|
|
|
- type = value.getClass();
|
|
|
- }
|
|
|
+ final Class<?> type = getGenericType(value);
|
|
|
final Writer writer = WRITERS.get(type);
|
|
|
if (writer != null) {
|
|
|
writer.write(this, value);
|
|
|
@@ -840,6 +842,38 @@ public abstract class StreamOutput extends OutputStream {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public static void checkWriteable(@Nullable Object value) throws IllegalArgumentException {
|
|
|
+ if (value == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ final Class<?> type = getGenericType(value);
|
|
|
+
|
|
|
+ if (type == List.class) {
|
|
|
+ @SuppressWarnings("unchecked") List<Object> list = (List<Object>) value;
|
|
|
+ for (Object v : list) {
|
|
|
+ checkWriteable(v);
|
|
|
+ }
|
|
|
+ } else if (type == Object[].class) {
|
|
|
+ Object[] array = (Object[]) value;
|
|
|
+ for (Object v : array) {
|
|
|
+ checkWriteable(v);
|
|
|
+ }
|
|
|
+ } else if (type == Map.class) {
|
|
|
+ @SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) value;
|
|
|
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
|
+ checkWriteable(entry.getKey());
|
|
|
+ checkWriteable(entry.getValue());
|
|
|
+ }
|
|
|
+ } else if (type == Set.class) {
|
|
|
+ @SuppressWarnings("unchecked") Set<Object> set = (Set<Object>) value;
|
|
|
+ for (Object v : set) {
|
|
|
+ checkWriteable(v);
|
|
|
+ }
|
|
|
+ } else if (WRITERS.containsKey(type) == false) {
|
|
|
+ throw new IllegalArgumentException("Cannot write type [" + type.getCanonicalName() + "] to stream");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void writeIntArray(int[] values) throws IOException {
|
|
|
writeVInt(values.length);
|
|
|
for (int value : values) {
|