Storage can now register classes with the serializer via the builder pattern. Added default serialization class to make registering defaults with kryo easier
This commit is contained in:
parent
f59ee3ca24
commit
693bf4cef2
75
src/dorkbox/util/serialization/SerializationDefaults.java
Normal file
75
src/dorkbox/util/serialization/SerializationDefaults.java
Normal file
|
@ -0,0 +1,75 @@
|
|||
package dorkbox.util.serialization;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Registration;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
|
||||
import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer;
|
||||
|
||||
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);
|
||||
|
||||
// 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());
|
||||
|
||||
|
||||
// hacky way to register unmodifiable serializers
|
||||
Kryo kryoHack = new Kryo() {
|
||||
@Override
|
||||
public
|
||||
Registration register(final Class type, final Serializer serializer) {
|
||||
kryo.register(type, serializer);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
UnmodifiableCollectionsSerializer.registerSerializers(kryoHack);
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ package dorkbox.util.serialization;
|
|||
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;
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.esotericsoftware.kryo.io.Input;
|
|||
import com.esotericsoftware.kryo.io.Output;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
import dorkbox.util.serialization.SerializationDefaults;
|
||||
import dorkbox.util.serialization.SerializationManager;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
|
@ -32,6 +33,11 @@ class DefaultStorageSerializationManager implements SerializationManager {
|
|||
Log.set(Log.LEVEL_ERROR);
|
||||
}};
|
||||
|
||||
public
|
||||
DefaultStorageSerializationManager() {
|
||||
SerializationDefaults.register(kryo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> SerializationManager register(final Class<T> clazz) {
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.slf4j.Logger;
|
|||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
|
||||
import dorkbox.util.OS;
|
||||
import dorkbox.os.OS;
|
||||
import dorkbox.util.serialization.SerializationManager;
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,61 @@
|
|||
package dorkbox.util.storage;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
|
||||
public
|
||||
interface StorageBuilder {
|
||||
/**
|
||||
* Builds the storage using the specified configuration
|
||||
*/
|
||||
Storage build();
|
||||
|
||||
/**
|
||||
* Registers the class using the lowest, next available integer ID and the {@link Kryo#getDefaultSerializer(Class) default 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> StorageBuilder register(Class<T> clazz);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* 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.
|
||||
*/
|
||||
<T> StorageBuilder register(Class<T> clazz, int id);
|
||||
|
||||
/**
|
||||
* 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> StorageBuilder register(Class<T> clazz, Serializer<T> serializer);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* 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.
|
||||
*/
|
||||
<T> StorageBuilder register(Class<T> clazz, Serializer<T> serializer, int id);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ import java.util.Map;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.helpers.NOPLogger;
|
||||
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
|
||||
import dorkbox.os.OS;
|
||||
import dorkbox.util.FileUtil;
|
||||
import dorkbox.util.OS;
|
||||
import dorkbox.util.serialization.SerializationManager;
|
||||
|
||||
public
|
||||
|
@ -151,7 +153,7 @@ class StorageSystem {
|
|||
public static
|
||||
class DiskBuilder implements StorageBuilder {
|
||||
private File file;
|
||||
private SerializationManager serializationManager;
|
||||
private SerializationManager serializationManager = createDefaultSerializationManager(); // default
|
||||
private boolean readOnly = false;
|
||||
private Logger logger = null;
|
||||
private long saveDelayInMilliseconds = 3000L; // default
|
||||
|
@ -220,6 +222,34 @@ class StorageSystem {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz) {
|
||||
this.serializationManager.register(clazz);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final int id) {
|
||||
this.serializationManager.register(clazz, id);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final Serializer<T> serializer) {
|
||||
this.serializationManager.register(clazz, serializer);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final Serializer<T> serializer, final int id) {
|
||||
this.serializationManager.register(clazz, serializer, id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the storage system
|
||||
*/
|
||||
|
@ -230,10 +260,6 @@ class StorageSystem {
|
|||
throw new IllegalArgumentException("file cannot be null!");
|
||||
}
|
||||
|
||||
if (this.serializationManager == null) {
|
||||
this.serializationManager = createDefaultSerializationManager();
|
||||
}
|
||||
|
||||
// if we load from a NEW storage at the same location as an ALREADY EXISTING storage,
|
||||
// without saving the existing storage first --- whoops!
|
||||
synchronized (storages) {
|
||||
|
@ -283,7 +309,7 @@ class StorageSystem {
|
|||
|
||||
|
||||
/**
|
||||
* Creates an in-memory only storage system
|
||||
* Creates an in-memory only storage system. This storage system DOES NOT care about serializing data, so `register` has no effect.
|
||||
*/
|
||||
public static
|
||||
class MemoryBuilder implements StorageBuilder {
|
||||
|
@ -296,5 +322,29 @@ class StorageSystem {
|
|||
Storage build() {
|
||||
return new MemoryStorage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final int id) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final Serializer<T> serializer) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
<T> StorageBuilder register(final Class<T> clazz, final Serializer<T> serializer, final int id) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user