Explorar el Código

Added a message that can be used to compile and
send the serializer registry... and then register
them on the other end.

Paul Speed hace 10 años
padre
commit
9abedf284e

+ 188 - 0
jme3-networking/src/main/java/com/jme3/network/message/SerializerRegistrationsMessage.java

@@ -0,0 +1,188 @@
+/*
+ * $Id: SerializerRegistrationsMessage.java 3829 2014-11-24 07:25:43Z pspeed $
+ *
+ * Copyright (c) 2012, Paul Speed
+ * All rights reserved.
+ */
+
+package com.jme3.network.message;
+
+import com.jme3.network.AbstractMessage;
+import com.jme3.network.serializing.Serializable;
+import com.jme3.network.serializing.Serializer;
+import com.jme3.network.serializing.SerializerRegistration;
+import com.jme3.network.serializing.serializers.FieldSerializer;
+import java.util.*;
+import java.util.jar.Attributes;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ *  Holds a compiled set of message registration information that
+ *  can be sent over the wire.  The received message can then be
+ *  used to register all of the classes using the same IDs and 
+ *  same ordering, etc..  The intent is that the server compiles
+ *  this message once it is sure that all serializable classes have
+ *  been registered.  It can then send this to each new client and
+ *  they can use it to register all of the classes without requiring
+ *  exactly reproducing the same calls that the server did to register
+ *  messages.
+ *
+ *  <p>Normally, JME recommends that apps have a common utility method
+ *  that they call on both client and server.  However, this makes 
+ *  pluggable services nearly impossible as some central class has to
+ *  know about all registered serializers.  This message implementation
+ *  gets around by only requiring registration on the server.</p>
+ *
+ *  @author    Paul Speed
+ */
+@Serializable
+public class SerializerRegistrationsMessage extends AbstractMessage {
+
+    static final Logger log = Logger.getLogger(SerializerRegistrationsMessage.class.getName());
+
+    public static final Set<Class> ignore = new HashSet<Class>();
+    static {
+        // We could build this automatically but then we
+        // risk making a client and server out of date simply because
+        // their JME versions are out of date.
+        ignore.add(Boolean.class);
+        ignore.add(Float.class);
+        ignore.add(Boolean.class);
+        ignore.add(Byte.class);
+        ignore.add(Character.class);
+        ignore.add(Short.class);
+        ignore.add(Integer.class);
+        ignore.add(Long.class);
+        ignore.add(Float.class);
+        ignore.add(Double.class);
+        ignore.add(String.class);
+ 
+        ignore.add(DisconnectMessage.class);
+        ignore.add(ClientRegistrationMessage.class);
+    
+        ignore.add(Date.class);
+        ignore.add(AbstractCollection.class);
+        ignore.add(AbstractList.class);
+        ignore.add(AbstractSet.class);
+        ignore.add(ArrayList.class);
+        ignore.add(HashSet.class);
+        ignore.add(LinkedHashSet.class);
+        ignore.add(LinkedList.class);
+        ignore.add(TreeSet.class);
+        ignore.add(Vector.class);
+        ignore.add(AbstractMap.class);
+        ignore.add(Attributes.class);
+        ignore.add(HashMap.class);
+        ignore.add(Hashtable.class);
+        ignore.add(IdentityHashMap.class);
+        ignore.add(TreeMap.class);
+        ignore.add(WeakHashMap.class);        
+        ignore.add(Enum.class);
+        
+        ignore.add(GZIPCompressedMessage.class);
+        ignore.add(ZIPCompressedMessage.class);
+
+        ignore.add(ChannelInfoMessage.class);
+        
+        ignore.add(SerializerRegistrationsMessage.class);
+        ignore.add(SerializerRegistrationsMessage.Registration.class);        
+    }
+ 
+    public static SerializerRegistrationsMessage INSTANCE;   
+    public static Registration[] compiled;
+    private static final Serializer fieldSerializer = new FieldSerializer();
+    
+    private Registration[] registrations;
+
+    public SerializerRegistrationsMessage() {
+        setReliable(true);
+    }
+
+    public SerializerRegistrationsMessage( Registration... registrations ) {
+        setReliable(true);
+        this.registrations = registrations;
+    }
+    
+    public static void compile() {
+    
+        // Let's just see what they are here
+        List<Registration> list = new ArrayList<Registration>();
+        for( SerializerRegistration reg : Serializer.getSerializerRegistrations() ) {
+            Class type = reg.getType();
+            if( ignore.contains(type) )
+                continue;
+            if( type.isPrimitive() )
+                continue;
+ 
+            list.add(new Registration(reg));
+        }
+            
+        if( log.isLoggable(Level.FINE) ) {
+            log.log( Level.FINE, "Number of registered classes:{0}", list.size());
+            for( Registration reg : list ) { 
+                log.log( Level.FINE, "    {0}", reg);
+            }
+        }
+        compiled = list.toArray(new Registration[list.size()]);
+        
+        INSTANCE = new SerializerRegistrationsMessage(compiled);                                
+    }
+ 
+    public void registerAll() {    
+        for( Registration reg : registrations ) {
+            log.log( Level.INFO, "Registering:{0}", reg);
+            reg.register();
+        }
+    }
+    
+    @Serializable
+    public static final class Registration {
+    
+        private short id;
+        private String className;
+        private String serializerClassName;
+        
+        public Registration() {
+        }
+        
+        public Registration( SerializerRegistration reg ) {
+        
+            this.id = reg.getId();
+            this.className = reg.getType().getName();
+            if( reg.getSerializer().getClass() != FieldSerializer.class ) {
+                this.serializerClassName = reg.getSerializer().getClass().getName();
+            } 
+        }
+ 
+        public void register() {        
+            try {
+                Class type = Class.forName(className);
+                Serializer serializer;
+                if( serializerClassName == null ) {
+                    serializer = fieldSerializer;
+                } else {
+                    Class serializerType = Class.forName(serializerClassName);
+                    serializer = (Serializer)serializerType.newInstance();                    
+                }
+                SerializerRegistration result = Serializer.registerClassForId(id, type, serializer);
+                log.log( Level.FINE, "   result:{0}", result);                
+            } catch( ClassNotFoundException e ) {
+                throw new RuntimeException( "Class not found attempting to register:" + this, e );
+            } catch( InstantiationException e ) {
+                throw new RuntimeException( "Error instantiating serializer registering:" + this, e );
+            } catch( IllegalAccessException e ) {
+                throw new RuntimeException( "Error instantiating serializer registering:" + this, e );
+            }            
+        }
+        
+        @Override
+        public String toString() {
+            return "Registration[" + id + " = " + className + ", serializer=" + serializerClassName + "]";
+        }
+    }
+}
+
+
+