Updated license information, general code cleanup
This commit is contained in:
parent
572550b5b5
commit
660ae68f6c
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 2010 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.util.entropy;
|
||||
|
||||
import dorkbox.network.util.exceptions.InitializationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final
|
||||
class Entropy {
|
||||
|
||||
@SuppressWarnings("StaticNonFinalField")
|
||||
private static EntropyProvider provider = null;
|
||||
|
||||
/**
|
||||
* Starts the process, and gets, the next amount of entropy bytes
|
||||
*/
|
||||
public static
|
||||
byte[] get(String messageForUser) throws InitializationException {
|
||||
synchronized (Entropy.class) {
|
||||
try {
|
||||
if (provider == null) {
|
||||
Entropy.init(SimpleEntropy.class);
|
||||
}
|
||||
|
||||
return provider.get(messageForUser);
|
||||
} catch (Exception e) {
|
||||
Logger logger = LoggerFactory.getLogger(Entropy.class);
|
||||
String error = "Unable to get entropy bytes for " + provider.getClass();
|
||||
logger.error(error, e);
|
||||
throw new InitializationException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will only set the Entropy provider if it has not ALREADY been set!
|
||||
*/
|
||||
public static
|
||||
void init(Class<? extends EntropyProvider> providerClass, Object... args) throws InitializationException {
|
||||
synchronized (Entropy.class) {
|
||||
if (provider == null) {
|
||||
Exception exception = null;
|
||||
|
||||
// use reflection to create the provider.
|
||||
try {
|
||||
Method createMethod = null;
|
||||
Method[] declaredMethods = providerClass.getDeclaredMethods();
|
||||
for (Method m : declaredMethods) {
|
||||
if (m.getName()
|
||||
.equals("create")) {
|
||||
createMethod = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (createMethod != null) {
|
||||
createMethod.setAccessible(true);
|
||||
|
||||
if (args.length == 0) {
|
||||
provider = (EntropyProvider) createMethod.invoke(null);
|
||||
}
|
||||
else {
|
||||
provider = (EntropyProvider) createMethod.invoke(null, args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
}
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(Entropy.class);
|
||||
String error = "Unable to create entropy provider for " + providerClass + " with " + args.length + " args";
|
||||
if (exception != null) {
|
||||
logger.error(error, exception);
|
||||
}
|
||||
else {
|
||||
logger.error(error);
|
||||
}
|
||||
|
||||
throw new InitializationException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
Entropy() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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 "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.util.serializers;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
|
||||
/**
|
||||
* A kryo {@link Serializer} for lists created via {@link Arrays#asList(Object...)}.
|
||||
* <p>
|
||||
* Note: This serializer does not support cyclic references, so if one of the objects
|
||||
* gets set the list as attribute this might cause an error during deserialization.
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||
*/
|
||||
public class ArraysAsListSerializer extends Serializer<List<?>> {
|
||||
|
||||
private Field _arrayField;
|
||||
|
||||
public ArraysAsListSerializer() {
|
||||
try {
|
||||
_arrayField = Class.forName( "java.util.Arrays$ArrayList" ).getDeclaredField( "a" );
|
||||
_arrayField.setAccessible( true );
|
||||
} catch ( final Exception e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
// Immutable causes #copy(obj) to return the original object
|
||||
setImmutable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<?> read(final Kryo kryo, final Input input, final Class<List<?>> type) {
|
||||
final int length = input.readInt(true);
|
||||
Class<?> componentType = kryo.readClass( input ).getType();
|
||||
if (componentType.isPrimitive()) {
|
||||
componentType = getPrimitiveWrapperClass(componentType);
|
||||
}
|
||||
try {
|
||||
final Object items = Array.newInstance( componentType, length );
|
||||
for( int i = 0; i < length; i++ ) {
|
||||
Array.set(items, i, kryo.readClassAndObject( input ));
|
||||
}
|
||||
return Arrays.asList( (Object[])items );
|
||||
} catch ( final Exception e ) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final Kryo kryo, final Output output, final List<?> obj) {
|
||||
try {
|
||||
final Object[] array = (Object[]) _arrayField.get( obj );
|
||||
output.writeInt(array.length, true);
|
||||
final Class<?> componentType = array.getClass().getComponentType();
|
||||
kryo.writeClass( output, componentType );
|
||||
for( final Object item : array ) {
|
||||
kryo.writeClassAndObject( output, item );
|
||||
}
|
||||
} 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 );
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* 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 "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.util.serializers;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.factories.SerializerFactory;
|
||||
import com.esotericsoftware.kryo.serializers.FieldSerializer;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* references to a dependency injection framework. As an example for Spring:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* {@code
|
||||
* Set<Class<? extends Annotation>> marks = new HashSet<>();
|
||||
* marks.add(Autowired.class);
|
||||
* SerializerFactory disregardingFactory = new FieldAnnotationAwareSerializer.Factory(marks, true);
|
||||
* Kryo kryo = new Kryo();
|
||||
* kryo.setDefaultSerializer(factory);
|
||||
* }
|
||||
* </pre>
|
||||
* <p/>
|
||||
* The resulting {@link Kryo} instance would ignore all fields that are annotated with Spring's {@code @Autowired}
|
||||
* annotation.
|
||||
* <p/>
|
||||
* Similarly, it is possible to created a serializer which does the opposite such that the resulting serializer
|
||||
* would only serialize fields that are annotated with the specified annotations.
|
||||
*
|
||||
* @author <a href="mailto:rafael.wth@web.de">Rafael Winterhalter</a>
|
||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||
*/
|
||||
public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
|
||||
|
||||
/**
|
||||
* A factory for creating instances of {@link FieldAnnotationAwareSerializer}.
|
||||
*/
|
||||
public static class Factory implements SerializerFactory {
|
||||
|
||||
private final Collection<Class<? extends Annotation>> marked;
|
||||
private final boolean disregarding;
|
||||
|
||||
/**
|
||||
* Creates a new factory. See {@link FieldAnnotationAwareSerializer#FieldAnnotationAwareSerializer(
|
||||
*com.esotericsoftware.kryo.Kryo, Class, java.util.Collection, boolean)}
|
||||
* for additional information on the constructor parameters.
|
||||
*
|
||||
* @param marked The annotations that will be considered of the resulting converter.
|
||||
* @param disregarding If {@code true}, the serializer will ignore all 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) {
|
||||
this.marked = marked;
|
||||
this.disregarding = disregarding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializer<?> makeSerializer(final Kryo kryo, final Class<?> type) {
|
||||
return new FieldAnnotationAwareSerializer<Object>(kryo, type, this.marked, this.disregarding);
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<Class<? extends Annotation>> marked;
|
||||
|
||||
/**
|
||||
* Determines whether annotated fields should be excluded from serialization.
|
||||
* <p/>
|
||||
* {@code true} if annotated fields should be excluded from serialization,
|
||||
* {@code false} if only annotated fields should be included from serialization.
|
||||
*/
|
||||
private final boolean disregarding;
|
||||
|
||||
/**
|
||||
* Creates a new field annotation aware serializer.
|
||||
*
|
||||
* @param kryo The {@link Kryo} instace.
|
||||
* @param type The type of the class being serialized.
|
||||
* @param marked The annotations this serializer considers for its serialization process. Be aware tha
|
||||
* a serializer with {@code disregarding} set to {@code false} will never be able to
|
||||
* serialize fields that are not annotated with any of these annotations since it is not
|
||||
* possible to add fields to a {@link FieldSerializer} once it is created. See the
|
||||
* documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and
|
||||
* {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information.
|
||||
* @param disregarding If {@code true}, the serializer will ignore all annotated fields,
|
||||
* if set to {@code false} it will exclusively look at annotated fields.
|
||||
*/
|
||||
public FieldAnnotationAwareSerializer(final Kryo kryo,
|
||||
final Class<?> type,
|
||||
final Collection<Class<? extends Annotation>> marked,
|
||||
final boolean disregarding) {
|
||||
super(kryo, type);
|
||||
this.disregarding = disregarding;
|
||||
this.marked = new HashSet<Class<? extends Annotation>>(marked);
|
||||
rebuildCachedFields();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void rebuildCachedFields() {
|
||||
// In order to avoid rebuilding the cached fields twice, the super constructor's call
|
||||
// to this method will be suppressed. This can be done by a simple check of the initialization
|
||||
// state of a property of this subclass.
|
||||
if (this.marked == null) {
|
||||
return;
|
||||
}
|
||||
super.rebuildCachedFields();
|
||||
removeFields();
|
||||
}
|
||||
|
||||
private void removeFields() {
|
||||
final CachedField<?>[] cachedFields = getFields();
|
||||
for (final CachedField<?> cachedField : cachedFields) {
|
||||
final Field field = cachedField.getField();
|
||||
if (isRemove(field)) {
|
||||
// if (TRACE) {
|
||||
// trace("kryo", String.format("Ignoring field %s tag: %s", this.disregarding ? "without" : "with", cachedField));
|
||||
// }
|
||||
super.removeField(field.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRemove(final Field field) {
|
||||
return !isMarked(field) ^ this.disregarding;
|
||||
}
|
||||
|
||||
private boolean isMarked(final Field field) {
|
||||
for (final Annotation annotation : field.getAnnotations()) {
|
||||
final Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
if (this.marked.contains(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an annotation to the annotations that are considered by this serializer.
|
||||
* <p/>
|
||||
* <b>Important</b>: This will not have an effect if the serializer was configured
|
||||
* to exclusively serialize annotated fields by setting {@code disregarding} to
|
||||
* {@code false}. This is similar to the contract of this serializer's superclass
|
||||
* {@link FieldSerializer} which does not allow to add fields that were formerly
|
||||
* removed. If this was possible, instances that were serialized before this field
|
||||
* was added could not longer be properly deserialized. In order to make this contract
|
||||
* break explicit, you need to create a new instance of this serializer if you want to
|
||||
* include new fields to a serializer that exclusively serializes annotated fields.
|
||||
*
|
||||
* @param clazz The annotation class to be added.
|
||||
* @return {@code true} if the method call had an effect.
|
||||
*/
|
||||
public boolean addAnnotation(final Class<? extends Annotation> clazz) {
|
||||
if (this.disregarding && this.marked.add(clazz)) {
|
||||
initializeCachedFields();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an annotation to the annotations that are considered by this serializer.
|
||||
* <p/>
|
||||
* <b>Important</b>: This will not have an effect if the serializer was configured
|
||||
* to not serialize annotated fields by setting {@code disregarding} to
|
||||
* {@code true}. This is similar to the contract of this serializer's superclass
|
||||
* {@link FieldSerializer} which does not allow to add fields that were formerly
|
||||
* removed. If this was possible, instances that were serialized before this field
|
||||
* was added could not longer be properly deserialized. In order to make this contract
|
||||
* break explicit, you need to create a new instance of this serializer if you want to
|
||||
* include new fields to a serializer that ignores annotated fields for serialization.
|
||||
*
|
||||
* @param clazz The annotation class to be removed.
|
||||
* @return {@code true} if the method call had an effect.
|
||||
*/
|
||||
public boolean removeAnnotation(final Class<? extends Annotation> clazz) {
|
||||
if (!this.disregarding && this.marked.remove(clazz)) {
|
||||
initializeCachedFields();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* 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 "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.util.serializers;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import dorkbox.util.exceptions.NetException;
|
||||
import dorkbox.util.SerializationManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A kryo {@link Serializer} for unmodifiable {@link Collection}s and {@link Map}s
|
||||
* created via {@link Collections}.
|
||||
*
|
||||
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
|
||||
*/
|
||||
public class UnmodifiableCollectionsSerializer extends Serializer<Object> {
|
||||
|
||||
private static final Field SOURCE_COLLECTION_FIELD;
|
||||
private static final Field SOURCE_MAP_FIELD;
|
||||
|
||||
static {
|
||||
try {
|
||||
SOURCE_COLLECTION_FIELD = Class.forName("java.util.Collections$UnmodifiableCollection" )
|
||||
.getDeclaredField("c");
|
||||
SOURCE_COLLECTION_FIELD.setAccessible( true );
|
||||
|
||||
|
||||
SOURCE_MAP_FIELD = Class.forName("java.util.Collections$UnmodifiableMap" )
|
||||
.getDeclaredField("m");
|
||||
SOURCE_MAP_FIELD.setAccessible( true );
|
||||
} catch ( final Exception e ) {
|
||||
throw new NetException("Could not access source collection" +
|
||||
" 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
|
||||
* for the several unmodifiable Collections that can be created via {@link Collections},
|
||||
* including {@link Map}s.
|
||||
*
|
||||
* @param manager the {@link SerializationManager} instance to set the serializer on.
|
||||
*
|
||||
* @see Collections#unmodifiableCollection(Collection)
|
||||
* @see Collections#unmodifiableList(List)
|
||||
* @see Collections#unmodifiableSet(Set)
|
||||
* @see Collections#unmodifiableSortedSet(SortedSet)
|
||||
* @see Collections#unmodifiableMap(Map)
|
||||
* @see Collections#unmodifiableSortedMap(SortedMap)
|
||||
*/
|
||||
public static void registerSerializers( final SerializationManager manager ) {
|
||||
final UnmodifiableCollectionsSerializer serializer = new UnmodifiableCollectionsSerializer();
|
||||
UnmodifiableCollection.values();
|
||||
for ( final UnmodifiableCollection item : UnmodifiableCollection.values() ) {
|
||||
manager.register( item.type, serializer );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue