From a0569b340d030147e5014b2f8e359a016699467a Mon Sep 17 00:00:00 2001 From: Paul Speed Date: Thu, 31 Dec 2015 04:26:22 -0500 Subject: [PATCH] Fixed a bug caused by generic registration of the enum class but it could catch the user unaware for any registered non-leaf class. When a class has a field of a specific final type then the type information is implicit in the outer object... and the proper serialization information can be written. It is then sometimes useful to register a generic serializer for something like Enum to catch these cases. However, there are many times where the type cannot be implicitly known and so must be specifically registered. Prior to this fix, having a generic Enum serializer registered would cause problems on the reading end because it wouldn't know what real enum class to use. Now we catch the issue on the write side where enough information is known to properly report this to the user. Only a few Bothans died to bring this info. --- .../jme3/network/serializing/Serializer.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java b/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java index 7e6b18849..ab1d05bc9 100644 --- a/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java +++ b/jme3-networking/src/main/java/com/jme3/network/serializing/Serializer.java @@ -130,7 +130,7 @@ public abstract class Serializer { registerClass(IdentityHashMap.class, new MapSerializer()); registerClass(TreeMap.class, new MapSerializer()); registerClass(WeakHashMap.class, new MapSerializer()); - + registerClass(Enum.class, new EnumSerializer()); registerClass(GZIPCompressedMessage.class, new GZIPSerializer()); registerClass(ZIPCompressedMessage.class, new ZIPSerializer()); @@ -331,7 +331,7 @@ public abstract class Serializer { @SuppressWarnings("unchecked") public static SerializerRegistration getSerializerRegistration(Class cls, boolean failOnMiss) { SerializerRegistration reg = classRegistrations.get(cls); - + if (reg != null) return reg; for (Map.Entry entry : classRegistrations.entrySet()) { @@ -425,6 +425,22 @@ public abstract class Serializer { return; } SerializerRegistration reg = writeClass(buffer, object.getClass()); + + // If the caller (or us) has registered a generic base class (like Enum) + // that is meant to steer automatic resolution for things like FieldSerializer + // that have final classes in fields... then there are cases where the exact + // type isn't known by the outer class. (Think of a message object + // that has an Object field but tries to send an Enum subclass in it.) + // In that case, the SerializerRegistration object we get back isn't + // really going to be capable of recreating the object on the other + // end because it won't know what class to use. This only comes up + // in writeclassAndObejct() because we just wrote an ID to a more generic + // class than will be readable on the other end. The check is simple, though. + if( reg.getType() != object.getClass() ) { + throw new IllegalArgumentException("Class has not been registered:" + + object.getClass() + " but resolved to generic serializer for:" + reg.getType()); + } + reg.getSerializer().writeObject(buffer, object); }