diff --git a/src/dorkbox/util/serialization/ArraysAsListSerializer.java b/src/dorkbox/util/serialization/ArraysAsListSerializer.java index 8a0b760..78833c9 100644 --- a/src/dorkbox/util/serialization/ArraysAsListSerializer.java +++ b/src/dorkbox/util/serialization/ArraysAsListSerializer.java @@ -15,16 +15,16 @@ */ package dorkbox.util.serialization; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - import java.lang.reflect.Array; import java.lang.reflect.Field; import java.util.Arrays; import java.util.List; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + /** * A kryo {@link Serializer} for lists created via {@link Arrays#asList(Object...)}. *

@@ -34,78 +34,92 @@ import java.util.List; * * @author Martin Grotzke */ -public class ArraysAsListSerializer extends Serializer> { +public +class ArraysAsListSerializer extends Serializer> { + private static + Class getPrimitiveWrapperClass(final Class c) { + if (c.isPrimitive()) { + if (c.equals(Long.TYPE)) { + return Long.class; + } + else if (c.equals(Integer.TYPE)) { + return Integer.class; + } + else if (c.equals(Double.TYPE)) { + return Double.class; + } + else if (c.equals(Float.TYPE)) { + return Float.class; + } + else if (c.equals(Boolean.TYPE)) { + return Boolean.class; + } + else if (c.equals(Character.TYPE)) { + return Character.class; + } + else if (c.equals(Short.TYPE)) { + return Short.class; + } + else if (c.equals(Byte.TYPE)) { + return Byte.class; + } + } + return c; + } private Field _arrayField; - public ArraysAsListSerializer() { + public + ArraysAsListSerializer() { try { - _arrayField = Class.forName( "java.util.Arrays$ArrayList" ).getDeclaredField( "a" ); - _arrayField.setAccessible( true ); - } catch ( final Exception e ) { - throw new RuntimeException( e ); + _arrayField = Class.forName("java.util.Arrays$ArrayList") + .getDeclaredField("a"); + _arrayField.setAccessible(true); + } catch (final Exception e) { + throw new RuntimeException(e); } // Immutable causes #copy(obj) to return the original object setImmutable(true); } @Override - public List read(final Kryo kryo, final Input input, final Class> type) { - final int length = input.readInt(true); - Class componentType = kryo.readClass( input ).getType(); - if (componentType.isPrimitive()) { - componentType = getPrimitiveWrapperClass(componentType); - } + public + void write(final Kryo kryo, final Output output, final List obj) { try { - final Object items = Array.newInstance( componentType, length ); - for( int i = 0; i < length; i++ ) { - Array.set(items, i, kryo.readClassAndObject( input )); + final Object[] array = (Object[]) _arrayField.get(obj); + output.writeInt(array.length, true); + final Class componentType = array.getClass() + .getComponentType(); + kryo.writeClass(output, componentType); + for (final Object item : array) { + kryo.writeClassAndObject(output, item); } - return Arrays.asList( (Object[])items ); - } catch ( final Exception e ) { - throw new RuntimeException( e ); + } catch (final RuntimeException e) { + // Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write... + // handles SerializationException specifically (resizing the buffer)... + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); } } @Override - public void write(final Kryo kryo, final Output output, final List obj) { + public + List read(final Kryo kryo, final Input input, final Class> type) { + final int length = input.readInt(true); + Class componentType = kryo.readClass(input) + .getType(); + if (componentType.isPrimitive()) { + componentType = getPrimitiveWrapperClass(componentType); + } try { - final Object[] array = (Object[]) _arrayField.get( obj ); - output.writeInt(array.length, true); - final Class componentType = array.getClass().getComponentType(); - kryo.writeClass( output, componentType ); - for( final Object item : array ) { - kryo.writeClassAndObject( output, item ); + final Object items = Array.newInstance(componentType, length); + for (int i = 0; i < length; i++) { + Array.set(items, i, kryo.readClassAndObject(input)); } - } catch ( final RuntimeException e ) { - // Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write... - // handles SerializationException specifically (resizing the buffer)... - throw e; - } catch ( final Exception e ) { - throw new RuntimeException( e ); + return Arrays.asList((Object[]) items); + } catch (final Exception e) { + throw new RuntimeException(e); } } - - private static Class getPrimitiveWrapperClass(final Class c) { - if (c.isPrimitive()) { - if (c.equals(Long.TYPE)) { - return Long.class; - } else if (c.equals(Integer.TYPE)) { - return Integer.class; - } else if (c.equals(Double.TYPE)) { - return Double.class; - } else if (c.equals(Float.TYPE)) { - return Float.class; - } else if (c.equals(Boolean.TYPE)) { - return Boolean.class; - } else if (c.equals(Character.TYPE)) { - return Character.class; - } else if (c.equals(Short.TYPE)) { - return Short.class; - } else if (c.equals(Byte.TYPE)) { - return Byte.class; - } - } - return c; - } } diff --git a/src/dorkbox/util/serialization/EccPrivateKeySerializer.java b/src/dorkbox/util/serialization/EccPrivateKeySerializer.java index 30bbc31..ec0bc0b 100644 --- a/src/dorkbox/util/serialization/EccPrivateKeySerializer.java +++ b/src/dorkbox/util/serialization/EccPrivateKeySerializer.java @@ -15,11 +15,8 @@ */ package dorkbox.util.serialization; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.reflectasm.FieldAccess; +import java.math.BigInteger; + import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.ec.CustomNamedCurves; @@ -28,7 +25,11 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; -import java.math.BigInteger; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.reflectasm.FieldAccess; /** * Only public keys are ever sent across the wire. diff --git a/src/dorkbox/util/serialization/EccPublicKeySerializer.java b/src/dorkbox/util/serialization/EccPublicKeySerializer.java index aa42408..abcead2 100644 --- a/src/dorkbox/util/serialization/EccPublicKeySerializer.java +++ b/src/dorkbox/util/serialization/EccPublicKeySerializer.java @@ -15,16 +15,17 @@ */ package dorkbox.util.serialization; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; +import java.math.BigInteger; + import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECPoint; -import java.math.BigInteger; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; /** * Only public keys are ever sent across the wire. diff --git a/src/dorkbox/util/serialization/FieldAnnotationAwareSerializer.java b/src/dorkbox/util/serialization/FieldAnnotationAwareSerializer.java index c6ef7d4..89767cc 100644 --- a/src/dorkbox/util/serialization/FieldAnnotationAwareSerializer.java +++ b/src/dorkbox/util/serialization/FieldAnnotationAwareSerializer.java @@ -16,17 +16,17 @@ */ package dorkbox.util.serialization; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.factories.SerializerFactory; -import com.esotericsoftware.kryo.serializers.FieldSerializer; - import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Collection; import java.util.HashSet; import java.util.Set; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.factories.SerializerFactory; +import com.esotericsoftware.kryo.serializers.FieldSerializer; + /** * A kryo {@link FieldSerializer} that allows to exclusively include or exclude fields that * are attributed with user-specific annotations. This can be for example useful when serializing beans that carry @@ -51,12 +51,14 @@ import java.util.Set; * @author Rafael Winterhalter * @author Martin Grotzke */ -public class FieldAnnotationAwareSerializer extends FieldSerializer { +public +class FieldAnnotationAwareSerializer extends FieldSerializer { /** * A factory for creating instances of {@link FieldAnnotationAwareSerializer}. */ - public static class Factory implements SerializerFactory { + public static + class Factory implements SerializerFactory { private final Collection> marked; private final boolean disregarding; @@ -66,21 +68,24 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { *com.esotericsoftware.kryo.Kryo, Class, java.util.Collection, boolean)} * for additional information on the constructor parameters. * - * @param marked The annotations that will be considered of the resulting converter. + * @param marked The annotations that will be considered of the resulting converter. * @param disregarding If {@code true}, the serializer will ignore all annotated fields, - * if set to {@code false} it will exclusively look at annotated fields. + * if set to {@code false} it will exclusively look at annotated fields. */ - public Factory(final Collection> marked, final boolean disregarding) { + public + Factory(final Collection> marked, final boolean disregarding) { this.marked = marked; this.disregarding = disregarding; } @Override - public Serializer makeSerializer(final Kryo kryo, final Class type) { + public + Serializer makeSerializer(final Kryo kryo, final Class type) { return new FieldAnnotationAwareSerializer(kryo, type, this.marked, this.disregarding); } } + private final Set> marked; /** @@ -94,21 +99,22 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { /** * Creates a new field annotation aware serializer. * - * @param kryo The {@link Kryo} instace. - * @param type The type of the class being serialized. - * @param marked The annotations this serializer considers for its serialization process. Be aware tha - * a serializer with {@code disregarding} set to {@code false} will never be able to - * serialize fields that are not annotated with any of these annotations since it is not - * possible to add fields to a {@link FieldSerializer} once it is created. See the - * documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and - * {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information. + * @param kryo The {@link Kryo} instace. + * @param type The type of the class being serialized. + * @param marked The annotations this serializer considers for its serialization process. Be aware tha + * a serializer with {@code disregarding} set to {@code false} will never be able to + * serialize fields that are not annotated with any of these annotations since it is not + * possible to add fields to a {@link FieldSerializer} once it is created. See the + * documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and + * {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information. * @param disregarding If {@code true}, the serializer will ignore all annotated fields, - * if set to {@code false} it will exclusively look at annotated fields. + * if set to {@code false} it will exclusively look at annotated fields. */ - public FieldAnnotationAwareSerializer(final Kryo kryo, - final Class type, - final Collection> marked, - final boolean disregarding) { + public + FieldAnnotationAwareSerializer(final Kryo kryo, + final Class type, + final Collection> marked, + final boolean disregarding) { super(kryo, type); this.disregarding = disregarding; this.marked = new HashSet>(marked); @@ -116,7 +122,8 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { } @Override - protected void rebuildCachedFields() { + protected + void rebuildCachedFields() { // In order to avoid rebuilding the cached fields twice, the super constructor's call // to this method will be suppressed. This can be done by a simple check of the initialization // state of a property of this subclass. @@ -127,7 +134,8 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { removeFields(); } - private void removeFields() { + private + void removeFields() { final CachedField[] cachedFields = getFields(); for (final CachedField cachedField : cachedFields) { final Field field = cachedField.getField(); @@ -140,11 +148,13 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { } } - private boolean isRemove(final Field field) { + private + boolean isRemove(final Field field) { return !isMarked(field) ^ this.disregarding; } - private boolean isMarked(final Field field) { + private + boolean isMarked(final Field field) { for (final Annotation annotation : field.getAnnotations()) { final Class annotationType = annotation.annotationType(); if (this.marked.contains(annotationType)) { @@ -167,9 +177,11 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { * include new fields to a serializer that exclusively serializes annotated fields. * * @param clazz The annotation class to be added. + * * @return {@code true} if the method call had an effect. */ - public boolean addAnnotation(final Class clazz) { + public + boolean addAnnotation(final Class clazz) { if (this.disregarding && this.marked.add(clazz)) { initializeCachedFields(); return true; @@ -190,9 +202,11 @@ public class FieldAnnotationAwareSerializer extends FieldSerializer { * include new fields to a serializer that ignores annotated fields for serialization. * * @param clazz The annotation class to be removed. + * * @return {@code true} if the method call had an effect. */ - public boolean removeAnnotation(final Class clazz) { + public + boolean removeAnnotation(final Class clazz) { if (!this.disregarding && this.marked.remove(clazz)) { initializeCachedFields(); return true; diff --git a/src/dorkbox/util/serialization/FileSerializer.java b/src/dorkbox/util/serialization/FileSerializer.java index 40f4063..786f05c 100644 --- a/src/dorkbox/util/serialization/FileSerializer.java +++ b/src/dorkbox/util/serialization/FileSerializer.java @@ -14,13 +14,15 @@ public class FileSerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, File file) { + public + void write(Kryo kryo, Output output, File file) { output.writeString(file.getPath()); } @Override - public File read(Kryo kryo, Input input, Class type) { - String path = input.readString(); + public + File read(Kryo kryo, Input input, Class type) { + String path = input.readString(); return new File(path); } } diff --git a/src/dorkbox/util/serialization/IesParametersSerializer.java b/src/dorkbox/util/serialization/IesParametersSerializer.java index 17c26f2..d4ff914 100644 --- a/src/dorkbox/util/serialization/IesParametersSerializer.java +++ b/src/dorkbox/util/serialization/IesParametersSerializer.java @@ -15,19 +15,22 @@ */ package dorkbox.util.serialization; +import org.bouncycastle.crypto.params.IESParameters; + import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; -import org.bouncycastle.crypto.params.IESParameters; /** - * Only public keys are ever sent across the wire. + * Only public keys are ever sent across the wire. */ -public class IesParametersSerializer extends Serializer { +public +class IesParametersSerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, IESParameters key) { + public + void write(Kryo kryo, Output output, IESParameters key) { byte[] bytes; int length; @@ -51,8 +54,8 @@ public class IesParametersSerializer extends Serializer { @SuppressWarnings("rawtypes") @Override - public IESParameters read (Kryo kryo, Input input, Class type) { - + public + IESParameters read(Kryo kryo, Input input, Class type) { int length; ///////////// @@ -69,5 +72,5 @@ public class IesParametersSerializer extends Serializer { int macKeySize = input.readInt(true); return new IESParameters(derivation, encoding, macKeySize); - } + } } diff --git a/src/dorkbox/util/serialization/IesWithCipherParametersSerializer.java b/src/dorkbox/util/serialization/IesWithCipherParametersSerializer.java index 0d034bd..9fd8b02 100644 --- a/src/dorkbox/util/serialization/IesWithCipherParametersSerializer.java +++ b/src/dorkbox/util/serialization/IesWithCipherParametersSerializer.java @@ -15,19 +15,22 @@ */ package dorkbox.util.serialization; +import org.bouncycastle.crypto.params.IESWithCipherParameters; + import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; -import org.bouncycastle.crypto.params.IESWithCipherParameters; /** - * Only public keys are ever sent across the wire. + * Only public keys are ever sent across the wire. */ -public class IesWithCipherParametersSerializer extends Serializer { +public +class IesWithCipherParametersSerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, IESWithCipherParameters key) { + public + void write(Kryo kryo, Output output, IESWithCipherParameters key) { byte[] bytes; int length; @@ -55,8 +58,8 @@ public class IesWithCipherParametersSerializer extends Serializer { +public +class RsaPrivateKeySerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, RSAPrivateCrtKeyParameters key) { + public + void write(Kryo kryo, Output output, RSAPrivateCrtKeyParameters key) { byte[] bytes; int length; ///////////// - bytes = key.getDP().toByteArray(); + bytes = key.getDP() + .toByteArray(); length = bytes.length; output.writeInt(length, true); output.writeBytes(bytes, 0, length); ///////////// - bytes = key.getDQ().toByteArray(); + bytes = key.getDQ() + .toByteArray(); length = bytes.length; output.writeInt(length, true); @@ -49,7 +54,8 @@ public class RsaPrivateKeySerializer extends Serializer { +public +class RsaPublicKeySerializer extends Serializer { @Override - public void write(Kryo kryo, Output output, RSAKeyParameters key) { + public + void write(Kryo kryo, Output output, RSAKeyParameters key) { byte[] bytes; int length; /////////// - bytes = key.getModulus().toByteArray(); + bytes = key.getModulus() + .toByteArray(); length = bytes.length; output.writeInt(length, true); output.writeBytes(bytes, 0, length); ///////////// - bytes = key.getExponent().toByteArray(); + bytes = key.getExponent() + .toByteArray(); length = bytes.length; output.writeInt(length, true); @@ -50,8 +55,8 @@ public class RsaPublicKeySerializer extends Serializer { @SuppressWarnings("rawtypes") @Override - public RSAKeyParameters read (Kryo kryo, Input input, Class type) { - + public + RSAKeyParameters read(Kryo kryo, Input input, Class type) { byte[] bytes; int length; @@ -68,5 +73,5 @@ public class RsaPublicKeySerializer extends Serializer { BigInteger exponent = new BigInteger(bytes); return new RSAKeyParameters(false, modulus, exponent); - } + } } diff --git a/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java b/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java index 12b1b1e..61b0b3b 100644 --- a/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java +++ b/src/dorkbox/util/serialization/UnmodifiableCollectionsSerializer.java @@ -16,14 +16,28 @@ */ package dorkbox.util.serialization; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; -import dorkbox.util.SerializationManager; -import java.lang.reflect.Field; -import java.util.*; +import dorkbox.util.SerializationManager; /** * A kryo {@link Serializer} for unmodifiable {@link Collection}s and {@link Map}s @@ -31,135 +45,102 @@ import java.util.*; * * @author Martin Grotzke */ -public class UnmodifiableCollectionsSerializer extends Serializer { +public +class UnmodifiableCollectionsSerializer extends Serializer { + private + enum UnmodifiableCollection { + COLLECTION(Collections.unmodifiableCollection(Arrays.asList("")) + .getClass(), SOURCE_COLLECTION_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableCollection((Collection) sourceCollection); + } + }, RANDOM_ACCESS_LIST(Collections.unmodifiableList(new ArrayList()) + .getClass(), SOURCE_COLLECTION_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableList((List) sourceCollection); + } + }, LIST(Collections.unmodifiableList(new LinkedList()) + .getClass(), SOURCE_COLLECTION_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableList((List) sourceCollection); + } + }, SET(Collections.unmodifiableSet(new HashSet()) + .getClass(), SOURCE_COLLECTION_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableSet((Set) sourceCollection); + } + }, SORTED_SET(Collections.unmodifiableSortedSet(new TreeSet()) + .getClass(), SOURCE_COLLECTION_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableSortedSet((SortedSet) sourceCollection); + } + }, MAP(Collections.unmodifiableMap(new HashMap()) + .getClass(), SOURCE_MAP_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableMap((Map) sourceCollection); + } + + }, SORTED_MAP(Collections.unmodifiableSortedMap(new TreeMap()) + .getClass(), SOURCE_MAP_FIELD) { + @Override + public + Object create(final Object sourceCollection) { + return Collections.unmodifiableSortedMap((SortedMap) sourceCollection); + } + }; + + static + UnmodifiableCollection valueOfType(final Class type) { + for (final UnmodifiableCollection item : values()) { + if (item.type.equals(type)) { + return item; + } + } + throw new IllegalArgumentException("The type " + type + " is not supported."); + } + private final Class type; + private final Field sourceCollectionField; + + UnmodifiableCollection(final Class type, final Field sourceCollectionField) { + this.type = type; + this.sourceCollectionField = sourceCollectionField; + } + + public abstract + Object create(Object sourceCollection); + + } private static final Field SOURCE_COLLECTION_FIELD; private static final Field SOURCE_MAP_FIELD; static { try { - SOURCE_COLLECTION_FIELD = Class.forName("java.util.Collections$UnmodifiableCollection" ) - .getDeclaredField("c"); - SOURCE_COLLECTION_FIELD.setAccessible( true ); + SOURCE_COLLECTION_FIELD = Class.forName("java.util.Collections$UnmodifiableCollection") + .getDeclaredField("c"); + SOURCE_COLLECTION_FIELD.setAccessible(true); - SOURCE_MAP_FIELD = Class.forName("java.util.Collections$UnmodifiableMap" ) - .getDeclaredField("m"); - SOURCE_MAP_FIELD.setAccessible( true ); - } catch ( final Exception e ) { - throw new RuntimeException("Could not access source collection" + - " field in java.util.Collections$UnmodifiableCollection.", e ); + SOURCE_MAP_FIELD = Class.forName("java.util.Collections$UnmodifiableMap") + .getDeclaredField("m"); + SOURCE_MAP_FIELD.setAccessible(true); + } catch (final Exception e) { + throw new RuntimeException("Could not access source collection" + " field in java.util.Collections$UnmodifiableCollection.", e); } } - @Override - public Object read(final Kryo kryo, final Input input, final Class clazz) { - final int ordinal = input.readInt( true ); - final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.values()[ordinal]; - final Object sourceCollection = kryo.readClassAndObject( input ); - return unmodifiableCollection.create( sourceCollection ); - } - - @Override - public void write(final Kryo kryo, final Output output, final Object object) { - try { - final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType( object.getClass() ); - // the ordinal could be replaced by s.th. else (e.g. a explicitely managed "id") - output.writeInt( unmodifiableCollection.ordinal(), true ); - kryo.writeClassAndObject( output, unmodifiableCollection.sourceCollectionField.get( object ) ); - } catch ( final RuntimeException e ) { - // Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write... - // handles SerializationException specifically (resizing the buffer)... - throw e; - } catch ( final Exception e ) { - throw new RuntimeException( e ); - } - } - - @Override - public Object copy(Kryo kryo, Object original) { - try { - final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType( original.getClass() ); - Object sourceCollectionCopy = kryo.copy(unmodifiableCollection.sourceCollectionField.get(original)); - return unmodifiableCollection.create( sourceCollectionCopy ); - } catch ( final RuntimeException e ) { - // Don't eat and wrap RuntimeExceptions - throw e; - } catch ( final Exception e ) { - throw new RuntimeException( e ); - } - } - - private static enum UnmodifiableCollection { - COLLECTION( Collections.unmodifiableCollection( Arrays.asList( "" ) ).getClass(), SOURCE_COLLECTION_FIELD ){ - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableCollection( (Collection) sourceCollection ); - } - }, - RANDOM_ACCESS_LIST( Collections.unmodifiableList( new ArrayList() ).getClass(), SOURCE_COLLECTION_FIELD ){ - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableList( (List) sourceCollection ); - } - }, - LIST( Collections.unmodifiableList( new LinkedList() ).getClass(), SOURCE_COLLECTION_FIELD ){ - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableList( (List) sourceCollection ); - } - }, - SET( Collections.unmodifiableSet( new HashSet() ).getClass(), SOURCE_COLLECTION_FIELD ){ - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableSet( (Set) sourceCollection ); - } - }, - SORTED_SET( Collections.unmodifiableSortedSet( new TreeSet() ).getClass(), SOURCE_COLLECTION_FIELD ){ - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableSortedSet( (SortedSet) sourceCollection ); - } - }, - MAP( Collections.unmodifiableMap( new HashMap() ).getClass(), SOURCE_MAP_FIELD ) { - - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableMap( (Map) sourceCollection ); - } - - }, - SORTED_MAP( Collections.unmodifiableSortedMap( new TreeMap() ).getClass(), SOURCE_MAP_FIELD ) { - @Override - public Object create( final Object sourceCollection ) { - return Collections.unmodifiableSortedMap( (SortedMap) sourceCollection ); - } - }; - - private final Class type; - private final Field sourceCollectionField; - - private UnmodifiableCollection( final Class type, final Field sourceCollectionField ) { - this.type = type; - this.sourceCollectionField = sourceCollectionField; - } - - /** - * @param sourceCollection - */ - public abstract Object create( Object sourceCollection ); - - static UnmodifiableCollection valueOfType( final Class type ) { - for( final UnmodifiableCollection item : values() ) { - if ( item.type.equals( type ) ) { - return item; - } - } - throw new IllegalArgumentException( "The type " + type + " is not supported." ); - } - - } - /** * Creates a new {@link UnmodifiableCollectionsSerializer} and registers its serializer * for the several unmodifiable Collections that can be created via {@link Collections}, @@ -174,12 +155,53 @@ public class UnmodifiableCollectionsSerializer extends Serializer { * @see Collections#unmodifiableMap(Map) * @see Collections#unmodifiableSortedMap(SortedMap) */ - public static void registerSerializers( final SerializationManager manager ) { + public static + void registerSerializers(final SerializationManager manager) { final UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer(); UnmodifiableCollection.values(); - for ( final UnmodifiableCollection item : UnmodifiableCollection.values() ) { - manager.register( item.type, serializer ); + for (final UnmodifiableCollection item : UnmodifiableCollection.values()) { + manager.register(item.type, serializer); } } + @Override + public + void write(final Kryo kryo, final Output output, final Object object) { + try { + final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType(object.getClass()); + // the ordinal could be replaced by s.th. else (e.g. a explicitely managed "id") + output.writeInt(unmodifiableCollection.ordinal(), true); + kryo.writeClassAndObject(output, unmodifiableCollection.sourceCollectionField.get(object)); + } catch (final RuntimeException e) { + // Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write... + // handles SerializationException specifically (resizing the buffer)... + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public + Object read(final Kryo kryo, final Input input, final Class clazz) { + final int ordinal = input.readInt(true); + final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.values()[ordinal]; + final Object sourceCollection = kryo.readClassAndObject(input); + return unmodifiableCollection.create(sourceCollection); + } + + @Override + public + Object copy(Kryo kryo, Object original) { + try { + final UnmodifiableCollection unmodifiableCollection = UnmodifiableCollection.valueOfType(original.getClass()); + Object sourceCollectionCopy = kryo.copy(unmodifiableCollection.sourceCollectionField.get(original)); + return unmodifiableCollection.create(sourceCollectionCopy); + } catch (final RuntimeException e) { + // Don't eat and wrap RuntimeExceptions + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } }