Added/cleaned up serializers.

master
Robinson 2021-05-17 00:14:14 +02:00
parent 092b908aeb
commit 7781e12b90
21 changed files with 227 additions and 751 deletions

View File

@ -1,44 +0,0 @@
package dorkbox.serializers;
import java.util.BitSet;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
public class BitSetSerializer extends Serializer<BitSet> {
@Override
public BitSet copy(final Kryo kryo, final BitSet original) {
final BitSet result = new BitSet();
final int length = original.length();
for(int i = 0; i < length; i++) {
result.set(i, original.get(i));
}
return result;
}
@Override
public void write(final Kryo kryo, final Output output, final BitSet bitSet) {
final int len = bitSet.length();
output.writeInt(len, true);
for(int i = 0; i < len; i++) {
output.writeBoolean(bitSet.get(i));
}
}
@Override
public BitSet read(final Kryo kryo, final Input input, final Class<? extends BitSet> bitSetClass) {
final int len = input.readInt(true);
final BitSet ret = new BitSet(len);
for(int i = 0; i < len; i++) {
ret.set(i, input.readBoolean());
}
return ret;
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.util.Collections;
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 {@link List}s created via {@link Collections#emptyList()}
* or that were just assigned the {@link Collections#EMPTY_LIST}.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CollectionsEmptyListSerializer extends Serializer<List<?>> {
public CollectionsEmptyListSerializer() {
setImmutable(true);
}
@Override
public List<?> read(final Kryo kryo, final Input input, final Class<? extends List<?>> type) {
return Collections.EMPTY_LIST;
}
@Override
public void write(final Kryo kryo, final Output output, final List<?> object) {
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.util.Collections;
import java.util.Map;
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 {@link Map}s created via {@link Collections#emptyMap()}
* or that were just assigned the {@link Collections#EMPTY_MAP}.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CollectionsEmptyMapSerializer extends Serializer<Map<?, ?>> {
public CollectionsEmptyMapSerializer() {
setImmutable(true);
}
@Override
public Map<?, ?> read(final Kryo kryo, final Input input, final Class<? extends Map<?, ?>> type) {
return Collections.EMPTY_MAP;
}
@Override
public void write(final Kryo kryo, final Output output, final Map<?, ?> object) {
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
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 {@link Map}s created via {@link Collections#emptySet()}
* or that were just assigned the {@link Collections#EMPTY_SET}.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CollectionsEmptySetSerializer extends Serializer<Set<?>> {
public CollectionsEmptySetSerializer() {
setImmutable(true);
}
@Override
public Set<?> read(final Kryo kryo, final Input input, final Class<? extends Set<?>> type) {
return Collections.EMPTY_SET;
}
@Override
public void write(final Kryo kryo, final Output output, final Set<?> object) {
}
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.util.ArrayList;
import java.util.Collection;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
/**
* A kryo {@link Serializer} that creates a copy of the source collection for writing object data.
* <p>
* This is useful for applications where objects/collections that are serialized
* might be accessed by different threads. However, it only reduces the probability
* of concurrent modification exceptions, as even during taking the copy the
* collection might be modified by another thread.
* </p>
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CopyForIterateCollectionSerializer extends CollectionSerializer {
@SuppressWarnings("unchecked")
@Override
public void write( final Kryo kryo, final Output output, @SuppressWarnings("rawtypes") final Collection object ) {
super.write( kryo, output, new ArrayList<Object>(object));
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.MapSerializer;
/**
* A kryo {@link Serializer} that creates a copy of the source map for writing object data.
* <p>
* This is useful for applications where objects/maps that are serialized
* might be accessed by different threads. However, it only reduces the probability
* of concurrent modification exceptions, as even during taking the copy the
* map might be modified by another thread.
* </p>
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class CopyForIterateMapSerializer extends MapSerializer {
@SuppressWarnings("unchecked")
@Override
public void write( final Kryo kryo, final Output output, @SuppressWarnings("rawtypes") final Map object ) {
final Map<?, ?> map;
// we only need special support for linked hash map, as SortedMaps will
// recreate correct sorting during deserialization...
if ( object instanceof LinkedHashMap<?, ?> ) {
map = new LinkedHashMap<Object, Object>( object );
}
else {
map = new HashMap<Object, Object>( object );
}
super.write( kryo, output, map );
}
}

View File

@ -1,79 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.lang.reflect.Constructor;
import java.util.Date;
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 {@link Date} and subclasses. Must be registered like this:
* <code><pre>
* Kryo kryo = new Kryo() {
* public Serializer<?> getDefaultSerializer(final Class clazz) {
* if ( Date.class.isAssignableFrom( type ) ) {
* return new DateSerializer( type );
* }
* return super.getDefaultSerializer( clazz );
* }
* };
* </pre></code>
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class DateSerializer extends Serializer<Date> {
private final Constructor<? extends Date> _constructor;
public DateSerializer(final Class<? extends Date> clazz) {
try {
_constructor = clazz.getConstructor(long.class);
} catch ( final Exception e ) {
throw new RuntimeException( e );
}
}
/**
* {@inheritDoc}
*/
@Override
public Date read(final Kryo kryo, final Input input, final Class<? extends Date> type) {
try {
return _constructor.newInstance(input.readLong(true));
} catch (final Exception e) {
throw new RuntimeException( e );
}
}
/**
* {@inheritDoc}
*/
@Override
public void write(final Kryo kryo, final Output output, final Date obj) {
output.writeLong(obj.getTime(), true);
}
@Override
public Date copy(final Kryo kryo, final Date original) {
return (Date) original.clone();
}
}

View File

@ -13,31 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.serializers;
package dorkbox.serializers
import java.io.File;
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.kryo.Kryo
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import java.io.File
/**
* Serialize the path of a file instead of the File object
*/
public
class FileSerializer extends Serializer<File> {
@Override
public
void write(Kryo kryo, Output output, File file) {
output.writeString(file.getPath());
class FileSerializer : Serializer<File>() {
override fun write(kryo: Kryo, output: Output, file: File) {
output.writeString(file.path)
}
@Override
public
File read(final Kryo kryo, final Input input, final Class<? extends File> type) {
String path = input.readString();
return new File(path);
override fun read(kryo: Kryo, input: Input, type: Class<out File>): File {
val path = input.readString()
return File(path)
}
}

View File

@ -1,96 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
* A more efficient kryo {@link Serializer} for {@link GregorianCalendar} instances (which
* are created via <code>Calendar.getInstance()</code> if the locale is not thai or japanese, so
* JapaneseImperialCalendar and BuddhistCalendar are not supported by this serializer).
* <p>
* With the default reflection based serialization, a calendar instance
* (created via <code>Calendar.getInstance(Locale.ENGLISH)</code>)
* would take 1323 byte, this one only takes 24 byte.
* </p>
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class GregorianCalendarSerializer extends Serializer<GregorianCalendar> {
private final Field _zoneField;
public GregorianCalendarSerializer() {
try {
_zoneField = Calendar.class.getDeclaredField( "zone" );
_zoneField.setAccessible( true );
} catch ( final Exception e ) {
throw new RuntimeException( e );
}
}
@Override
public GregorianCalendar read(final Kryo kryo, final Input input, final Class<? extends GregorianCalendar> type) {
final Calendar result = GregorianCalendar.getInstance();
result.setTimeInMillis( input.readLong( true ) );
result.setLenient( input.readBoolean() );
result.setFirstDayOfWeek( input.readInt( true ) );
result.setMinimalDaysInFirstWeek( input.readInt( true ) );
/* check if we actually need to set the timezone, as
* TimeZone.getTimeZone is synchronized, so we might prevent this
*/
final String timeZoneId = input.readString();
if ( !getTimeZone( result ).getID().equals( timeZoneId ) ) {
result.setTimeZone( TimeZone.getTimeZone( timeZoneId ) );
}
return (GregorianCalendar) result;
}
@Override
public void write(final Kryo kryo, final Output output, final GregorianCalendar calendar) {
output.writeLong( calendar.getTimeInMillis(), true );
output.writeBoolean( calendar.isLenient() );
output.writeInt( calendar.getFirstDayOfWeek(), true );
output.writeInt( calendar.getMinimalDaysInFirstWeek(), true );
output.writeString( getTimeZone( calendar ).getID() );
}
@Override
public GregorianCalendar copy(final Kryo kryo, final GregorianCalendar original) {
return (GregorianCalendar) original.clone();
}
private TimeZone getTimeZone( final Calendar obj ) {
/* access the timezone via the field, to prevent cloning of the tz */
try {
return (TimeZone) _zoneField.get( obj );
} catch ( final Exception e ) {
throw new RuntimeException( e );
}
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright 2010 Martin Grotzke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package dorkbox.serializers;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
* A serializer for jdk proxies (proxies created via <code>java.lang.reflect.Proxy.newProxyInstance</code>).
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class JdkProxySerializer extends Serializer<Object> {
@Override
public Object read(final Kryo kryo, final Input input, final Class<? extends Object> type) {
final InvocationHandler invocationHandler = (InvocationHandler) kryo.readClassAndObject( input );
final Class<?>[] interfaces = kryo.readObject( input, Class[].class );
final ClassLoader classLoader = kryo.getClassLoader();
try {
return Proxy.newProxyInstance( classLoader, interfaces, invocationHandler );
} catch( final RuntimeException e ) {
System.err.println( getClass().getName()+ ".read:\n" +
"Could not create proxy using classLoader " + classLoader + "," +
" have invocationhandler.classloader: " + invocationHandler.getClass().getClassLoader() +
" have contextclassloader: " + Thread.currentThread().getContextClassLoader() );
throw e;
}
}
@Override
public void write(final Kryo kryo, final Output output, final Object obj) {
kryo.writeClassAndObject( output, Proxy.getInvocationHandler( obj ) );
kryo.writeObject( output, obj.getClass().getInterfaces() );
}
@Override
public Object copy(final Kryo kryo, final Object original) {
return Proxy.newProxyInstance( kryo.getClassLoader(), original.getClass().getInterfaces(),
Proxy.getInvocationHandler(original) );
}
}

View File

@ -1,34 +0,0 @@
package dorkbox.serializers;
import java.util.regex.Pattern;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
* Kryo {@link Serializer} for regex {@link Pattern}s.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
* @author serverperformance
*/
public class RegexSerializer extends Serializer<Pattern> {
public RegexSerializer() {
setImmutable(true);
}
@Override
public void write(final Kryo kryo, final Output output, final Pattern pattern) {
output.writeString(pattern.pattern());
output.writeInt(pattern.flags(), true);
}
@Override
public Pattern read(final Kryo kryo, final Input input, final Class<? extends Pattern> patternClass) {
String regex = input.readString();
int flags = input.readInt(true);
return Pattern.compile(regex, flags);
}
}

View File

@ -0,0 +1,30 @@
package dorkbox.serializers
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import java.util.regex.Pattern
/**
* Kryo [Serializer] for regex [Pattern]s.
*
* @author [Martin Grotzke](mailto:martin.grotzke@javakaffee.de)
* @author serverperformance
*/
class RegexSerializer : Serializer<Pattern>() {
init {
isImmutable = true
}
override fun write(kryo: Kryo, output: Output, pattern: Pattern) {
output.writeString(pattern.pattern())
output.writeInt(pattern.flags(), true)
}
override fun read(kryo: Kryo, input: Input, patternClass: Class<out Pattern>): Pattern {
val regex = input.readString()
val flags = input.readInt(true)
return Pattern.compile(regex, flags)
}
}

View File

@ -1,81 +0,0 @@
/*
* Copyright 2021 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.serializers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import com.esotericsoftware.kryo.Kryo;
public
class SerializationDefaults {
/**
* Allows for the kryo registration of sensible defaults in a common, well used way.
*/
public static
void register(Kryo kryo) {
// these are registered using the default serializers. We don't customize these, because we don't care about it.
kryo.register(String.class);
kryo.register(String[].class);
kryo.register(int[].class);
kryo.register(short[].class);
kryo.register(float[].class);
kryo.register(double[].class);
kryo.register(long[].class);
kryo.register(byte[].class);
kryo.register(char[].class);
kryo.register(boolean[].class);
kryo.register(Integer[].class);
kryo.register(Short[].class);
kryo.register(Float[].class);
kryo.register(Double[].class);
kryo.register(Long[].class);
kryo.register(Byte[].class);
kryo.register(Character[].class);
kryo.register(Boolean[].class);
kryo.register(Object[].class);
kryo.register(Object[][].class);
kryo.register(Class.class);
kryo.register(Exception.class);
kryo.register(IOException.class);
kryo.register(RuntimeException.class);
kryo.register(NullPointerException.class);
// necessary for the transport of exceptions.
kryo.register(StackTraceElement.class);
kryo.register(StackTraceElement[].class);
kryo.register(ArrayList.class);
kryo.register(HashMap.class);
kryo.register(HashSet.class);
kryo.register(Collections.emptyList().getClass());
kryo.register(Collections.emptySet().getClass());
kryo.register(Collections.emptyMap().getClass());
kryo.register(Collections.emptyNavigableSet().getClass());
kryo.register(Collections.emptyNavigableMap().getClass());
UnmodifiableCollectionsSerializer.registerSerializers(kryo);
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2021 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.serializers
import com.esotericsoftware.kryo.Kryo
import java.io.IOException
import java.math.BigDecimal
import java.net.URI
import java.util.*
import java.util.regex.Pattern
object SerializationDefaults {
/**
* Allows for the kryo registration of sensible defaults in a common, well-used way.
*/
fun register(kryo: Kryo) {
// these are registered using the default serializers. We don't customize these, because we don't care about it.
kryo.register(String::class.java)
kryo.register(Array<String>::class.java)
kryo.register(IntArray::class.java)
kryo.register(ShortArray::class.java)
kryo.register(FloatArray::class.java)
kryo.register(DoubleArray::class.java)
kryo.register(LongArray::class.java)
kryo.register(ByteArray::class.java)
kryo.register(CharArray::class.java)
kryo.register(BooleanArray::class.java)
kryo.register(Array<Int>::class.java)
kryo.register(Array<Short>::class.java)
kryo.register(Array<Float>::class.java)
kryo.register(Array<Double>::class.java)
kryo.register(Array<Long>::class.java)
kryo.register(Array<Byte>::class.java)
kryo.register(Array<Char>::class.java)
kryo.register(Array<Boolean>::class.java)
kryo.register(Array<Any>::class.java)
kryo.register(Array<Array<Any>>::class.java)
kryo.register(Class::class.java)
kryo.register(Exception::class.java)
kryo.register(IOException::class.java)
kryo.register(RuntimeException::class.java)
kryo.register(NullPointerException::class.java)
kryo.register(BigDecimal::class.java)
kryo.register(BitSet::class.java)
// necessary for the transport of exceptions.
kryo.register(StackTraceElement::class.java)
kryo.register(Array<StackTraceElement>::class.java)
kryo.register(ArrayList::class.java)
kryo.register(HashMap::class.java)
kryo.register(HashSet::class.java)
kryo.register(EnumSet::class.java, EnumSetSerializer())
kryo.register(EnumMap::class.java, EnumMapSerializer())
kryo.register(Arrays.asList("").javaClass, ArraysAsListSerializer())
kryo.register(emptyList<Any>().javaClass)
kryo.register(emptySet<Any>().javaClass)
kryo.register(emptyMap<Any, Any>().javaClass)
kryo.register(Collections.EMPTY_LIST.javaClass)
kryo.register(Collections.EMPTY_SET.javaClass)
kryo.register(Collections.EMPTY_MAP.javaClass)
kryo.register(Collections.emptyNavigableSet<Any>().javaClass)
kryo.register(Collections.emptyNavigableMap<Any, Any>().javaClass)
kryo.register(Collections.singletonMap("", "").javaClass, CollectionsSingletonMapSerializer())
kryo.register(listOf("").javaClass, CollectionsSingletonListSerializer())
kryo.register(setOf("").javaClass, CollectionsSingletonSetSerializer())
kryo.register(Pattern::class.java, RegexSerializer())
kryo.register(URI::class.java, URISerializer())
kryo.register(UUID::class.java, UUIDSerializer())
UnmodifiableCollectionsSerializer.registerSerializers(kryo)
SynchronizedCollectionsSerializer.registerSerializers(kryo)
}
}

View File

@ -13,88 +13,96 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dorkbox.serializers;
package dorkbox.serializers
import java.io.IOException;
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import java.io.IOException
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
public
interface SerializationManager<IO> {
/**
* Registers the class using the lowest, next available integer ID and the {@link Kryo#getDefaultSerializer(Class) default serializer}.
* Registers the class using the lowest, next available integer ID and the [default serializer][Kryo.getDefaultSerializer].
* If the class is already registered, the existing entry is updated with the new serializer.
* <p>
*
*
* Registering a primitive also affects the corresponding primitive wrapper.
* <p>
*
*
* Because the ID assigned is affected by the IDs registered before it, the order classes are registered is important when using this
* method. The order must be the same at deserialization as it was for serialization.
*/
<T> SerializationManager register(Class<T> clazz);
fun <T> register(clazz: Class<T>?): SerializationManager<*>?
/**
* Registers the class using the specified ID. If the ID is already in use by the same type, the old entry is overwritten. If the ID
* is already in use by a different type, a {@link KryoException} is thrown.
* <p>
* is already in use by a different type, a [KryoException] is thrown.
*
*
* Registering a primitive also affects the corresponding primitive wrapper.
* <p>
*
*
* IDs must be the same at deserialization as they were for serialization.
*
* @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs 0-8 are used by default for primitive types and String, but
* these IDs can be repurposed.
* these IDs can be repurposed.
*/
<T> SerializationManager register(Class<T> clazz, int id);
fun <T> register(clazz: Class<T>?, id: Int): SerializationManager<*>?
/**
* Registers the class using the lowest, next available integer ID and the specified serializer. If the class is already registered,
* the existing entry is updated with the new serializer.
* <p>
*
*
* Registering a primitive also affects the corresponding primitive wrapper.
* <p>
*
*
* Because the ID assigned is affected by the IDs registered before it, the order classes are registered is important when using this
* method. The order must be the same at deserialization as it was for serialization.
*/
<T> SerializationManager register(Class<T> clazz, Serializer<T> serializer);
fun <T> register(clazz: Class<T>?, serializer: Serializer<T>?): SerializationManager<*>?
/**
* Registers the class using the specified ID and serializer. If the ID is already in use by the same type, the old entry is
* overwritten. If the ID is already in use by a different type, a {@link KryoException} is thrown.
* <p>
* overwritten. If the ID is already in use by a different type, a [KryoException] is thrown.
*
*
* Registering a primitive also affects the corresponding primitive wrapper.
* <p>
*
*
* IDs must be the same at deserialization as they were for serialization.
*
* @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs 0-8 are used by default for primitive types and String, but
* these IDs can be repurposed.
* these IDs can be repurposed.
*/
<T> SerializationManager register(Class<T> clazz, Serializer<T> serializer, int id);
fun <T> register(clazz: Class<T>?, serializer: Serializer<T>?, id: Int): SerializationManager<*>?
/**
* Waits until a kryo is available to write, using CAS operations to prevent having to synchronize.
* <p/>
*
*
* There is a small speed penalty if there were no kryo's available to use.
*/
void write(IO buffer, Object message) throws IOException;
@Throws(IOException::class)
fun write(buffer: IO, message: Any?)
/**
* Reads an object from the buffer.
*
* @param length should ALWAYS be the length of the expected object!
*/
Object read(IO buffer, int length) throws IOException;
@Throws(IOException::class)
fun read(buffer: IO, length: Int): Any?
/**
* Writes the class and object using an available kryo instance
*/
void writeFullClassAndObject(Output output, Object value) throws IOException;
@Throws(IOException::class)
fun writeFullClassAndObject(output: Output?, value: Any?)
/**
* Returns a class read from the input
*/
Object readFullClassAndObject(final Input input) throws IOException;
@Throws(IOException::class)
fun readFullClassAndObject(input: Input?): Any?
}

View File

@ -75,7 +75,7 @@ public class SynchronizedCollectionsSerializer extends Serializer<Object> {
public void write(final Kryo kryo, final Output output, final Object object) {
try {
final SynchronizedCollection collection = SynchronizedCollection.valueOfType( object.getClass() );
// the ordinal could be replaced by s.th. else (e.g. a explicitely managed "id")
// the ordinal could be replaced by something else (e.g. a explicitly managed "id")
output.writeInt( collection.ordinal(), true );
synchronized (object) {
kryo.writeClassAndObject( output, collection.sourceCollectionField.get( object ) );
@ -189,10 +189,9 @@ public class SynchronizedCollectionsSerializer extends Serializer<Object> {
*/
public static void registerSerializers( final Kryo kryo ) {
final SynchronizedCollectionsSerializer serializer = new SynchronizedCollectionsSerializer();
SynchronizedCollection.values();
for ( final SynchronizedCollection item : SynchronizedCollection.values() ) {
SynchronizedCollection[] values = SynchronizedCollection.values();
for ( final SynchronizedCollection item : values) {
kryo.register( item.type, serializer );
}
}
}

View File

@ -1,25 +0,0 @@
package dorkbox.serializers;
import java.net.URI;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
public class URISerializer extends Serializer<URI> {
public URISerializer() {
setImmutable(true);
}
@Override
public void write(final Kryo kryo, final Output output, final URI uri) {
output.writeString(uri.toString());
}
@Override
public URI read(final Kryo kryo, final Input input, final Class<? extends URI> uriClass) {
return URI.create(input.readString());
}
}

View File

@ -0,0 +1,21 @@
package dorkbox.serializers
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import java.net.URI
class URISerializer : Serializer<URI>() {
init {
isImmutable = true
}
override fun write(kryo: Kryo, output: Output, uri: URI) {
output.writeString(uri.toString())
}
override fun read(kryo: Kryo, input: Input, uriClass: Class<out URI>): URI {
return URI.create(input.readString())
}
}

View File

@ -1,25 +0,0 @@
package dorkbox.serializers;
import java.util.UUID;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
public class UUIDSerializer extends Serializer<UUID> {
public UUIDSerializer() {
setImmutable(true);
}
@Override
public void write(final Kryo kryo, final Output output, final UUID uuid) {
output.writeLong(uuid.getMostSignificantBits());
output.writeLong(uuid.getLeastSignificantBits());
}
@Override public UUID read(final Kryo kryo, final Input input, final Class<? extends UUID> uuidClass) {
return new UUID(input.readLong(), input.readLong());
}
}

View File

@ -0,0 +1,22 @@
package dorkbox.serializers
import com.esotericsoftware.kryo.Kryo
import com.esotericsoftware.kryo.Serializer
import com.esotericsoftware.kryo.io.Input
import com.esotericsoftware.kryo.io.Output
import java.util.*
class UUIDSerializer : Serializer<UUID>() {
init {
isImmutable = true
}
override fun write(kryo: Kryo, output: Output, uuid: UUID) {
output.writeLong(uuid.mostSignificantBits)
output.writeLong(uuid.leastSignificantBits)
}
override fun read(kryo: Kryo, input: Input, uuidClass: Class<out UUID>): UUID {
return UUID(input.readLong(), input.readLong())
}
}

View File

@ -58,6 +58,7 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
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 );
@ -76,7 +77,8 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
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")
// the ordinal could be replaced by something else (e.g. a explicitly managed "id")
output.writeInt( unmodifiableCollection.ordinal(), true );
kryo.writeClassAndObject( output, unmodifiableCollection.sourceCollectionField.get( object ) );
} catch ( final RuntimeException e ) {
@ -102,7 +104,7 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
}
}
private static enum UnmodifiableCollection {
private enum UnmodifiableCollection {
COLLECTION( Collections.unmodifiableCollection( Arrays.asList( "" ) ).getClass(), SOURCE_COLLECTION_FIELD ){
@Override
public Object create( final Object sourceCollection ) {
@ -151,7 +153,7 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
private final Class<?> type;
private final Field sourceCollectionField;
private UnmodifiableCollection( final Class<?> type, final Field sourceCollectionField ) {
UnmodifiableCollection( final Class<?> type, final Field sourceCollectionField ) {
this.type = type;
this.sourceCollectionField = sourceCollectionField;
}
@ -169,7 +171,6 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
}
throw new IllegalArgumentException( "The type " + type + " is not supported." );
}
}
/**
@ -188,10 +189,9 @@ public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
*/
public static void registerSerializers( final Kryo kryo ) {
final UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer();
UnmodifiableCollection.values();
for ( final UnmodifiableCollection item : UnmodifiableCollection.values() ) {
UnmodifiableCollection[] values = UnmodifiableCollection.values();
for ( final UnmodifiableCollection item : values) {
kryo.register( item.type, serializer );
}
}
}