Code polish
This commit is contained in:
parent
c824a7f8a9
commit
f64118bae1
@ -15,16 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
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.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
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...)}.
|
* A kryo {@link Serializer} for lists created via {@link Arrays#asList(Object...)}.
|
||||||
* <p>
|
* <p>
|
||||||
@ -34,78 +34,92 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||||
*/
|
*/
|
||||||
public class ArraysAsListSerializer extends Serializer<List<?>> {
|
public
|
||||||
|
class ArraysAsListSerializer extends Serializer<List<?>> {
|
||||||
|
|
||||||
|
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;
|
private Field _arrayField;
|
||||||
|
|
||||||
public ArraysAsListSerializer() {
|
public
|
||||||
|
ArraysAsListSerializer() {
|
||||||
try {
|
try {
|
||||||
_arrayField = Class.forName( "java.util.Arrays$ArrayList" ).getDeclaredField( "a" );
|
_arrayField = Class.forName("java.util.Arrays$ArrayList")
|
||||||
_arrayField.setAccessible( true );
|
.getDeclaredField("a");
|
||||||
} catch ( final Exception e ) {
|
_arrayField.setAccessible(true);
|
||||||
throw new RuntimeException( e );
|
} catch (final Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
// Immutable causes #copy(obj) to return the original object
|
// Immutable causes #copy(obj) to return the original object
|
||||||
setImmutable(true);
|
setImmutable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<?> read(final Kryo kryo, final Input input, final Class<List<?>> type) {
|
public
|
||||||
final int length = input.readInt(true);
|
void write(final Kryo kryo, final Output output, final List<?> obj) {
|
||||||
Class<?> componentType = kryo.readClass( input ).getType();
|
|
||||||
if (componentType.isPrimitive()) {
|
|
||||||
componentType = getPrimitiveWrapperClass(componentType);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
final Object items = Array.newInstance( componentType, length );
|
final Object[] array = (Object[]) _arrayField.get(obj);
|
||||||
for( int i = 0; i < length; i++ ) {
|
output.writeInt(array.length, true);
|
||||||
Array.set(items, i, kryo.readClassAndObject( input ));
|
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 RuntimeException e) {
|
||||||
} catch ( final Exception e ) {
|
// Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write...
|
||||||
throw new RuntimeException( e );
|
// handles SerializationException specifically (resizing the buffer)...
|
||||||
|
throw e;
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(final Kryo kryo, final Output output, final List<?> obj) {
|
public
|
||||||
|
List<?> read(final Kryo kryo, final Input input, final Class<List<?>> type) {
|
||||||
|
final int length = input.readInt(true);
|
||||||
|
Class<?> componentType = kryo.readClass(input)
|
||||||
|
.getType();
|
||||||
|
if (componentType.isPrimitive()) {
|
||||||
|
componentType = getPrimitiveWrapperClass(componentType);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final Object[] array = (Object[]) _arrayField.get( obj );
|
final Object items = Array.newInstance(componentType, length);
|
||||||
output.writeInt(array.length, true);
|
for (int i = 0; i < length; i++) {
|
||||||
final Class<?> componentType = array.getClass().getComponentType();
|
Array.set(items, i, kryo.readClassAndObject(input));
|
||||||
kryo.writeClass( output, componentType );
|
|
||||||
for( final Object item : array ) {
|
|
||||||
kryo.writeClassAndObject( output, item );
|
|
||||||
}
|
}
|
||||||
} catch ( final RuntimeException e ) {
|
return Arrays.asList((Object[]) items);
|
||||||
// Don't eat and wrap RuntimeExceptions because the ObjectBuffer.write...
|
} catch (final Exception e) {
|
||||||
// handles SerializationException specifically (resizing the buffer)...
|
throw new RuntimeException(e);
|
||||||
throw e;
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import java.math.BigInteger;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
|
||||||
import com.esotericsoftware.reflectasm.FieldAccess;
|
|
||||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||||
import org.bouncycastle.crypto.ec.CustomNamedCurves;
|
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.ECCurve;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
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.
|
* Only public keys are ever sent across the wire.
|
||||||
|
@ -15,16 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import java.math.BigInteger;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
|
||||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||||
import org.bouncycastle.math.ec.ECCurve;
|
import org.bouncycastle.math.ec.ECCurve;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
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.
|
* Only public keys are ever sent across the wire.
|
||||||
|
@ -16,17 +16,17 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
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.annotation.Annotation;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
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
|
* 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
|
* 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 <a href="mailto:rafael.wth@web.de">Rafael Winterhalter</a>
|
* @author <a href="mailto:rafael.wth@web.de">Rafael Winterhalter</a>
|
||||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||||
*/
|
*/
|
||||||
public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
public
|
||||||
|
class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory for creating instances of {@link FieldAnnotationAwareSerializer}.
|
* A factory for creating instances of {@link FieldAnnotationAwareSerializer}.
|
||||||
*/
|
*/
|
||||||
public static class Factory implements SerializerFactory {
|
public static
|
||||||
|
class Factory implements SerializerFactory {
|
||||||
|
|
||||||
private final Collection<Class<? extends Annotation>> marked;
|
private final Collection<Class<? extends Annotation>> marked;
|
||||||
private final boolean disregarding;
|
private final boolean disregarding;
|
||||||
@ -66,21 +68,24 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
*com.esotericsoftware.kryo.Kryo, Class, java.util.Collection, boolean)}
|
*com.esotericsoftware.kryo.Kryo, Class, java.util.Collection, boolean)}
|
||||||
* for additional information on the constructor parameters.
|
* 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,
|
* @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<Class<? extends Annotation>> marked, final boolean disregarding) {
|
public
|
||||||
|
Factory(final Collection<Class<? extends Annotation>> marked, final boolean disregarding) {
|
||||||
this.marked = marked;
|
this.marked = marked;
|
||||||
this.disregarding = disregarding;
|
this.disregarding = disregarding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializer<?> makeSerializer(final Kryo kryo, final Class<?> type) {
|
public
|
||||||
|
Serializer<?> makeSerializer(final Kryo kryo, final Class<?> type) {
|
||||||
return new FieldAnnotationAwareSerializer<Object>(kryo, type, this.marked, this.disregarding);
|
return new FieldAnnotationAwareSerializer<Object>(kryo, type, this.marked, this.disregarding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final Set<Class<? extends Annotation>> marked;
|
private final Set<Class<? extends Annotation>> marked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,21 +99,22 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
/**
|
/**
|
||||||
* Creates a new field annotation aware serializer.
|
* Creates a new field annotation aware serializer.
|
||||||
*
|
*
|
||||||
* @param kryo The {@link Kryo} instace.
|
* @param kryo The {@link Kryo} instace.
|
||||||
* @param type The type of the class being serialized.
|
* @param type The type of the class being serialized.
|
||||||
* @param marked The annotations this serializer considers for its serialization process. Be aware tha
|
* @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
|
* 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
|
* 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
|
* possible to add fields to a {@link FieldSerializer} once it is created. See the
|
||||||
* documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and
|
* documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and
|
||||||
* {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information.
|
* {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information.
|
||||||
* @param disregarding If {@code true}, the serializer will ignore all annotated fields,
|
* @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,
|
public
|
||||||
final Class<?> type,
|
FieldAnnotationAwareSerializer(final Kryo kryo,
|
||||||
final Collection<Class<? extends Annotation>> marked,
|
final Class<?> type,
|
||||||
final boolean disregarding) {
|
final Collection<Class<? extends Annotation>> marked,
|
||||||
|
final boolean disregarding) {
|
||||||
super(kryo, type);
|
super(kryo, type);
|
||||||
this.disregarding = disregarding;
|
this.disregarding = disregarding;
|
||||||
this.marked = new HashSet<Class<? extends Annotation>>(marked);
|
this.marked = new HashSet<Class<? extends Annotation>>(marked);
|
||||||
@ -116,7 +122,8 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void rebuildCachedFields() {
|
protected
|
||||||
|
void rebuildCachedFields() {
|
||||||
// In order to avoid rebuilding the cached fields twice, the super constructor's call
|
// 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
|
// to this method will be suppressed. This can be done by a simple check of the initialization
|
||||||
// state of a property of this subclass.
|
// state of a property of this subclass.
|
||||||
@ -127,7 +134,8 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
removeFields();
|
removeFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeFields() {
|
private
|
||||||
|
void removeFields() {
|
||||||
final CachedField<?>[] cachedFields = getFields();
|
final CachedField<?>[] cachedFields = getFields();
|
||||||
for (final CachedField<?> cachedField : cachedFields) {
|
for (final CachedField<?> cachedField : cachedFields) {
|
||||||
final Field field = cachedField.getField();
|
final Field field = cachedField.getField();
|
||||||
@ -140,11 +148,13 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRemove(final Field field) {
|
private
|
||||||
|
boolean isRemove(final Field field) {
|
||||||
return !isMarked(field) ^ this.disregarding;
|
return !isMarked(field) ^ this.disregarding;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMarked(final Field field) {
|
private
|
||||||
|
boolean isMarked(final Field field) {
|
||||||
for (final Annotation annotation : field.getAnnotations()) {
|
for (final Annotation annotation : field.getAnnotations()) {
|
||||||
final Class<? extends Annotation> annotationType = annotation.annotationType();
|
final Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||||
if (this.marked.contains(annotationType)) {
|
if (this.marked.contains(annotationType)) {
|
||||||
@ -167,9 +177,11 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
* include new fields to a serializer that exclusively serializes annotated fields.
|
* include new fields to a serializer that exclusively serializes annotated fields.
|
||||||
*
|
*
|
||||||
* @param clazz The annotation class to be added.
|
* @param clazz The annotation class to be added.
|
||||||
|
*
|
||||||
* @return {@code true} if the method call had an effect.
|
* @return {@code true} if the method call had an effect.
|
||||||
*/
|
*/
|
||||||
public boolean addAnnotation(final Class<? extends Annotation> clazz) {
|
public
|
||||||
|
boolean addAnnotation(final Class<? extends Annotation> clazz) {
|
||||||
if (this.disregarding && this.marked.add(clazz)) {
|
if (this.disregarding && this.marked.add(clazz)) {
|
||||||
initializeCachedFields();
|
initializeCachedFields();
|
||||||
return true;
|
return true;
|
||||||
@ -190,9 +202,11 @@ public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
|||||||
* include new fields to a serializer that ignores annotated fields for serialization.
|
* include new fields to a serializer that ignores annotated fields for serialization.
|
||||||
*
|
*
|
||||||
* @param clazz The annotation class to be removed.
|
* @param clazz The annotation class to be removed.
|
||||||
|
*
|
||||||
* @return {@code true} if the method call had an effect.
|
* @return {@code true} if the method call had an effect.
|
||||||
*/
|
*/
|
||||||
public boolean removeAnnotation(final Class<? extends Annotation> clazz) {
|
public
|
||||||
|
boolean removeAnnotation(final Class<? extends Annotation> clazz) {
|
||||||
if (!this.disregarding && this.marked.remove(clazz)) {
|
if (!this.disregarding && this.marked.remove(clazz)) {
|
||||||
initializeCachedFields();
|
initializeCachedFields();
|
||||||
return true;
|
return true;
|
||||||
|
@ -14,13 +14,15 @@ public
|
|||||||
class FileSerializer extends Serializer<File> {
|
class FileSerializer extends Serializer<File> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Kryo kryo, Output output, File file) {
|
public
|
||||||
|
void write(Kryo kryo, Output output, File file) {
|
||||||
output.writeString(file.getPath());
|
output.writeString(file.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File read(Kryo kryo, Input input, Class<File> type) {
|
public
|
||||||
String path = input.readString();
|
File read(Kryo kryo, Input input, Class<File> type) {
|
||||||
|
String path = input.readString();
|
||||||
return new File(path);
|
return new File(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.params.IESParameters;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
import com.esotericsoftware.kryo.Serializer;
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
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<IESParameters> {
|
public
|
||||||
|
class IesParametersSerializer extends Serializer<IESParameters> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Kryo kryo, Output output, IESParameters key) {
|
public
|
||||||
|
void write(Kryo kryo, Output output, IESParameters key) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
@ -51,8 +54,8 @@ public class IesParametersSerializer extends Serializer<IESParameters> {
|
|||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public IESParameters read (Kryo kryo, Input input, Class type) {
|
public
|
||||||
|
IESParameters read(Kryo kryo, Input input, Class type) {
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
@ -69,5 +72,5 @@ public class IesParametersSerializer extends Serializer<IESParameters> {
|
|||||||
int macKeySize = input.readInt(true);
|
int macKeySize = input.readInt(true);
|
||||||
|
|
||||||
return new IESParameters(derivation, encoding, macKeySize);
|
return new IESParameters(derivation, encoding, macKeySize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.params.IESWithCipherParameters;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
import com.esotericsoftware.kryo.Serializer;
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
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<IESWithCipherParameters> {
|
public
|
||||||
|
class IesWithCipherParametersSerializer extends Serializer<IESWithCipherParameters> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Kryo kryo, Output output, IESWithCipherParameters key) {
|
public
|
||||||
|
void write(Kryo kryo, Output output, IESWithCipherParameters key) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
@ -55,8 +58,8 @@ public class IesWithCipherParametersSerializer extends Serializer<IESWithCipherP
|
|||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public IESWithCipherParameters read (Kryo kryo, Input input, Class type) {
|
public
|
||||||
|
IESWithCipherParameters read(Kryo kryo, Input input, Class type) {
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
@ -76,5 +79,5 @@ public class IesWithCipherParametersSerializer extends Serializer<IESWithCipherP
|
|||||||
int cipherKeySize = input.readInt(true);
|
int cipherKeySize = input.readInt(true);
|
||||||
|
|
||||||
return new IESWithCipherParameters(derivation, encoding, macKeySize, cipherKeySize);
|
return new IESWithCipherParameters(derivation, encoding, macKeySize, cipherKeySize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,33 +15,38 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
import com.esotericsoftware.kryo.Serializer;
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only public keys are ever sent across the wire.
|
* Only public keys are ever sent across the wire.
|
||||||
*/
|
*/
|
||||||
public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParameters> {
|
public
|
||||||
|
class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParameters> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Kryo kryo, Output output, RSAPrivateCrtKeyParameters key) {
|
public
|
||||||
|
void write(Kryo kryo, Output output, RSAPrivateCrtKeyParameters key) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getDP().toByteArray();
|
bytes = key.getDP()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
output.writeBytes(bytes, 0, length);
|
output.writeBytes(bytes, 0, length);
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getDQ().toByteArray();
|
bytes = key.getDQ()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -49,7 +54,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getExponent().toByteArray();
|
bytes = key.getExponent()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -57,7 +63,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getModulus().toByteArray();
|
bytes = key.getModulus()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -65,7 +72,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getP().toByteArray();
|
bytes = key.getP()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -73,7 +81,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getPublicExponent().toByteArray();
|
bytes = key.getPublicExponent()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -81,7 +90,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getQ().toByteArray();
|
bytes = key.getQ()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -89,7 +99,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getQInv().toByteArray();
|
bytes = key.getQInv()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -98,8 +109,8 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public RSAPrivateCrtKeyParameters read (Kryo kryo, Input input, Class type) {
|
public
|
||||||
|
RSAPrivateCrtKeyParameters read(Kryo kryo, Input input, Class type) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
@ -152,5 +163,5 @@ public class RsaPrivateKeySerializer extends Serializer<RSAPrivateCrtKeyParamete
|
|||||||
BigInteger qInv = new BigInteger(bytes);
|
BigInteger qInv = new BigInteger(bytes);
|
||||||
|
|
||||||
return new RSAPrivateCrtKeyParameters(modulus, publicExponent, exponent, P, q, DP, DQ, qInv);
|
return new RSAPrivateCrtKeyParameters(modulus, publicExponent, exponent, P, q, DP, DQ, qInv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,33 +15,38 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
package dorkbox.util.serialization;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.bouncycastle.crypto.params.RSAKeyParameters;
|
||||||
|
|
||||||
import com.esotericsoftware.kryo.Kryo;
|
import com.esotericsoftware.kryo.Kryo;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
import com.esotericsoftware.kryo.Serializer;
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
import org.bouncycastle.crypto.params.RSAKeyParameters;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only public keys are ever sent across the wire.
|
* Only public keys are ever sent across the wire.
|
||||||
*/
|
*/
|
||||||
public class RsaPublicKeySerializer extends Serializer<RSAKeyParameters> {
|
public
|
||||||
|
class RsaPublicKeySerializer extends Serializer<RSAKeyParameters> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Kryo kryo, Output output, RSAKeyParameters key) {
|
public
|
||||||
|
void write(Kryo kryo, Output output, RSAKeyParameters key) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
bytes = key.getModulus().toByteArray();
|
bytes = key.getModulus()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
output.writeBytes(bytes, 0, length);
|
output.writeBytes(bytes, 0, length);
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
bytes = key.getExponent().toByteArray();
|
bytes = key.getExponent()
|
||||||
|
.toByteArray();
|
||||||
length = bytes.length;
|
length = bytes.length;
|
||||||
|
|
||||||
output.writeInt(length, true);
|
output.writeInt(length, true);
|
||||||
@ -50,8 +55,8 @@ public class RsaPublicKeySerializer extends Serializer<RSAKeyParameters> {
|
|||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public RSAKeyParameters read (Kryo kryo, Input input, Class type) {
|
public
|
||||||
|
RSAKeyParameters read(Kryo kryo, Input input, Class type) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
@ -68,5 +73,5 @@ public class RsaPublicKeySerializer extends Serializer<RSAKeyParameters> {
|
|||||||
BigInteger exponent = new BigInteger(bytes);
|
BigInteger exponent = new BigInteger(bytes);
|
||||||
|
|
||||||
return new RSAKeyParameters(false, modulus, exponent);
|
return new RSAKeyParameters(false, modulus, exponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,28 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.serialization;
|
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.Kryo;
|
||||||
import com.esotericsoftware.kryo.Serializer;
|
import com.esotericsoftware.kryo.Serializer;
|
||||||
import com.esotericsoftware.kryo.io.Input;
|
import com.esotericsoftware.kryo.io.Input;
|
||||||
import com.esotericsoftware.kryo.io.Output;
|
import com.esotericsoftware.kryo.io.Output;
|
||||||
import dorkbox.util.SerializationManager;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import dorkbox.util.SerializationManager;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A kryo {@link Serializer} for unmodifiable {@link Collection}s and {@link Map}s
|
* A kryo {@link Serializer} for unmodifiable {@link Collection}s and {@link Map}s
|
||||||
@ -31,135 +45,102 @@ import java.util.*;
|
|||||||
*
|
*
|
||||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||||
*/
|
*/
|
||||||
public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
|
public
|
||||||
|
class UnmodifiableCollectionsSerializer extends Serializer<Object> {
|
||||||
|
|
||||||
|
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<Void>())
|
||||||
|
.getClass(), SOURCE_COLLECTION_FIELD) {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Object create(final Object sourceCollection) {
|
||||||
|
return Collections.unmodifiableList((List<?>) sourceCollection);
|
||||||
|
}
|
||||||
|
}, LIST(Collections.unmodifiableList(new LinkedList<Void>())
|
||||||
|
.getClass(), SOURCE_COLLECTION_FIELD) {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Object create(final Object sourceCollection) {
|
||||||
|
return Collections.unmodifiableList((List<?>) sourceCollection);
|
||||||
|
}
|
||||||
|
}, SET(Collections.unmodifiableSet(new HashSet<Void>())
|
||||||
|
.getClass(), SOURCE_COLLECTION_FIELD) {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Object create(final Object sourceCollection) {
|
||||||
|
return Collections.unmodifiableSet((Set<?>) sourceCollection);
|
||||||
|
}
|
||||||
|
}, SORTED_SET(Collections.unmodifiableSortedSet(new TreeSet<Void>())
|
||||||
|
.getClass(), SOURCE_COLLECTION_FIELD) {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Object create(final Object sourceCollection) {
|
||||||
|
return Collections.unmodifiableSortedSet((SortedSet<?>) sourceCollection);
|
||||||
|
}
|
||||||
|
}, MAP(Collections.unmodifiableMap(new HashMap<Void, Void>())
|
||||||
|
.getClass(), SOURCE_MAP_FIELD) {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Object create(final Object sourceCollection) {
|
||||||
|
return Collections.unmodifiableMap((Map<?, ?>) sourceCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, SORTED_MAP(Collections.unmodifiableSortedMap(new TreeMap<Void, Void>())
|
||||||
|
.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_COLLECTION_FIELD;
|
||||||
private static final Field SOURCE_MAP_FIELD;
|
private static final Field SOURCE_MAP_FIELD;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
SOURCE_COLLECTION_FIELD = Class.forName("java.util.Collections$UnmodifiableCollection" )
|
SOURCE_COLLECTION_FIELD = Class.forName("java.util.Collections$UnmodifiableCollection")
|
||||||
.getDeclaredField("c");
|
.getDeclaredField("c");
|
||||||
SOURCE_COLLECTION_FIELD.setAccessible( true );
|
SOURCE_COLLECTION_FIELD.setAccessible(true);
|
||||||
|
|
||||||
|
|
||||||
SOURCE_MAP_FIELD = Class.forName("java.util.Collections$UnmodifiableMap" )
|
SOURCE_MAP_FIELD = Class.forName("java.util.Collections$UnmodifiableMap")
|
||||||
.getDeclaredField("m");
|
.getDeclaredField("m");
|
||||||
SOURCE_MAP_FIELD.setAccessible( true );
|
SOURCE_MAP_FIELD.setAccessible(true);
|
||||||
} catch ( final Exception e ) {
|
} catch (final Exception e) {
|
||||||
throw new RuntimeException("Could not access source collection" +
|
throw new RuntimeException("Could not access source collection" + " field in java.util.Collections$UnmodifiableCollection.", e);
|
||||||
" field in java.util.Collections$UnmodifiableCollection.", e );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object read(final Kryo kryo, final Input input, final Class<Object> 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<Void>() ).getClass(), SOURCE_COLLECTION_FIELD ){
|
|
||||||
@Override
|
|
||||||
public Object create( final Object sourceCollection ) {
|
|
||||||
return Collections.unmodifiableList( (List<?>) sourceCollection );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LIST( Collections.unmodifiableList( new LinkedList<Void>() ).getClass(), SOURCE_COLLECTION_FIELD ){
|
|
||||||
@Override
|
|
||||||
public Object create( final Object sourceCollection ) {
|
|
||||||
return Collections.unmodifiableList( (List<?>) sourceCollection );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SET( Collections.unmodifiableSet( new HashSet<Void>() ).getClass(), SOURCE_COLLECTION_FIELD ){
|
|
||||||
@Override
|
|
||||||
public Object create( final Object sourceCollection ) {
|
|
||||||
return Collections.unmodifiableSet( (Set<?>) sourceCollection );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SORTED_SET( Collections.unmodifiableSortedSet( new TreeSet<Void>() ).getClass(), SOURCE_COLLECTION_FIELD ){
|
|
||||||
@Override
|
|
||||||
public Object create( final Object sourceCollection ) {
|
|
||||||
return Collections.unmodifiableSortedSet( (SortedSet<?>) sourceCollection );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MAP( Collections.unmodifiableMap( new HashMap<Void, Void>() ).getClass(), SOURCE_MAP_FIELD ) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object create( final Object sourceCollection ) {
|
|
||||||
return Collections.unmodifiableMap( (Map<?, ?>) sourceCollection );
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
SORTED_MAP( Collections.unmodifiableSortedMap( new TreeMap<Void, Void>() ).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
|
* Creates a new {@link UnmodifiableCollectionsSerializer} and registers its serializer
|
||||||
* for the several unmodifiable Collections that can be created via {@link Collections},
|
* for the several unmodifiable Collections that can be created via {@link Collections},
|
||||||
@ -174,12 +155,53 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
|
|||||||
* @see Collections#unmodifiableMap(Map)
|
* @see Collections#unmodifiableMap(Map)
|
||||||
* @see Collections#unmodifiableSortedMap(SortedMap)
|
* @see Collections#unmodifiableSortedMap(SortedMap)
|
||||||
*/
|
*/
|
||||||
public static void registerSerializers( final SerializationManager manager ) {
|
public static
|
||||||
|
void registerSerializers(final SerializationManager manager) {
|
||||||
final UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer();
|
final UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer();
|
||||||
UnmodifiableCollection.values();
|
UnmodifiableCollection.values();
|
||||||
for ( final UnmodifiableCollection item : UnmodifiableCollection.values() ) {
|
for (final UnmodifiableCollection item : UnmodifiableCollection.values()) {
|
||||||
manager.register( item.type, serializer );
|
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<Object> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user