[kaffe] CVS kaffe (guilhem): MulticastSocket fixes and Object serialization updates.

Kaffe CVS Kaffe Mailing List <kaffe@kaffe.org>
Sun Dec 14 01:30:03 2003


PatchSet 4225 
Date: 2003/12/14 09:26:54
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
MulticastSocket fixes and Object serialization updates.

Members: 
	ChangeLog:1.1814->1.1815 
	libraries/clib/net/PlainDatagramSocketImpl.c:1.35->1.36 
	libraries/javalib/java/io/ObjectInputStream.java:1.26->1.27 
	libraries/javalib/java/io/ObjectOutputStream.java:1.17->1.18 
	libraries/javalib/java/io/ObjectStreamClass.java:1.15->1.16 
	libraries/javalib/java/io/ObjectStreamField.java:1.3->1.4 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.1814 kaffe/ChangeLog:1.1815
--- kaffe/ChangeLog:1.1814	Sat Dec 13 20:01:52 2003
+++ kaffe/ChangeLog	Sun Dec 14 09:26:54 2003
@@ -1,3 +1,22 @@
+2003-12-14  Guilhem Lavaux <guilhem@kaffe.org>,
+	Everton da Silva Marques <everton@lab.ipaccess.diveo.net.br>
+
+	* libraries/clib/net/PlainDatagramSocket.c:
+	(gnu_java_net_PlainDatagramSocketImpl_join,
+	gnu_java_net_PlainDatagramSocketImpl_leave,
+	gnu_java_net_PlainDatagramSocketImpl_joinGroup,
+	gnu_java_net_PlainDatagramSocketImpl_leaveGroup)
+	Use the last setup network interface for the multicast socket
+	if there is no explicit mention of it in the parameters.
+	Changes suggested by Everton da Silva Marques 
+	<everton@lab.ipaccess.diveo.net.br>.
+
+	* libraries/javalib/java/io/ObjectInputStream.java,
+	libraries/javalib/java/io/ObjectOutputStream.java,
+	libraries/javalib/java/io/ObjectStreamClass.java,
+	libraries/javalib/java/io/ObjectStreamField.java:
+	Upgraded to classpath's version.
+
 2003-12-13  Dalibor Topic <robilad@kaffe.org>
 
 	* config/s390/sysdepCallMethod.h: New file.
Index: kaffe/libraries/clib/net/PlainDatagramSocketImpl.c
diff -u kaffe/libraries/clib/net/PlainDatagramSocketImpl.c:1.35 kaffe/libraries/clib/net/PlainDatagramSocketImpl.c:1.36
--- kaffe/libraries/clib/net/PlainDatagramSocketImpl.c:1.35	Tue Nov  4 20:42:41 2003
+++ kaffe/libraries/clib/net/PlainDatagramSocketImpl.c	Sun Dec 14 09:26:55 2003
@@ -531,11 +531,17 @@
 #if defined(IP_ADD_MEMBERSHIP)
 	int r;
 	struct ip_mreq ipm;
-
+	int iface_addr;
+	
+	memset(&ipm, 0, sizeof(ipm));
 	memcpy(&ipm.imr_multiaddr, unhand_byte_array(unhand(laddr)->addr),
 	       sizeof(ipm.imr_multiaddr));
-	ipm.imr_interface.s_addr = htonl(INADDR_ANY);
-
+	
+        iface_addr =
+	  gnu_java_net_PlainDatagramSocketImpl_socketGetOption(this, 
+	    java_net_SocketOptions_IP_MULTICAST_IF);
+	ipm.imr_interface.s_addr = htonl(iface_addr);
+	
 DBG(NATIVENET,
 	dprintf("datagram_join (%p, %p) => %s\n",
 		this, laddr, ip2str(ipm.imr_interface.s_addr));
@@ -561,10 +567,16 @@
 #if defined(IP_DROP_MEMBERSHIP)
 	int r;
 	struct ip_mreq ipm;
+	int iface_addr;
 
+	memset(&ipm, 0, sizeof(ipm));
 	memcpy(&ipm.imr_multiaddr, unhand_byte_array(unhand(laddr)->addr),
 	       sizeof(ipm.imr_multiaddr));
-	ipm.imr_interface.s_addr = htonl(INADDR_ANY);
+
+        iface_addr = 
+	  gnu_java_net_PlainDatagramSocketImpl_socketGetOption(this, 
+	    java_net_SocketOptions_IP_MULTICAST_IF);
+	ipm.imr_interface.s_addr = htonl(iface_addr);
 
 DBG(NATIVENET,
 	dprintf("datagram_leave (%p, %p) => %s\n",
@@ -594,7 +606,8 @@
 	int r;
 
 	jisa = (struct Hjava_net_InetSocketAddress *)jsa;
-	
+
+	memset(&ipm, 0, sizeof(ipm));
 	memcpy(&ipm.imr_multiaddr,
 	       unhand_byte_array(unhand(unhand(jisa)->addr)->addr),
 	       sizeof(ipm.imr_multiaddr));
@@ -614,7 +627,9 @@
 	}
 	else
 	{
-	  ipm.imr_interface.s_addr = htonl(INADDR_ANY);
+	  ipm.imr_interface.s_addr =
+	    gnu_java_net_PlainDatagramSocketImpl_socketGetOption(this, 
+	      java_net_SocketOptions_IP_MULTICAST_IF);
 	}
 
 	r = KSETSOCKOPT(unhand(unhand(this)->fd)->nativeFd,
@@ -643,7 +658,8 @@
 	int r;
 
 	jisa = (struct Hjava_net_InetSocketAddress *)jsa;
-	
+
+	memset(&ipm, 0, sizeof(ipm));
 	memcpy(&ipm.imr_multiaddr,
 	       unhand_byte_array(unhand(unhand(jisa)->addr)->addr),
 	       sizeof(ipm.imr_multiaddr));
@@ -658,7 +674,9 @@
 	}
 	else
 	{
-		ipm.imr_interface.s_addr = htonl(INADDR_ANY);
+	  ipm.imr_interface.s_addr =
+	    gnu_java_net_PlainDatagramSocketImpl_socketGetOption(this, 
+	      java_net_SocketOptions_IP_MULTICAST_IF);
 	}
 
 	r = KSETSOCKOPT(unhand(unhand(this)->fd)->nativeFd,
Index: kaffe/libraries/javalib/java/io/ObjectInputStream.java
diff -u kaffe/libraries/javalib/java/io/ObjectInputStream.java:1.26 kaffe/libraries/javalib/java/io/ObjectInputStream.java:1.27
--- kaffe/libraries/javalib/java/io/ObjectInputStream.java:1.26	Sat Aug 30 14:18:31 2003
+++ kaffe/libraries/javalib/java/io/ObjectInputStream.java	Sun Dec 14 09:26:56 2003
@@ -47,7 +47,6 @@
 import java.util.Hashtable;
 import java.util.Vector;
 
-
 import gnu.java.io.ObjectIdentityWrapper;
 import gnu.java.lang.reflect.TypeSignature;
 import java.lang.reflect.Field;
@@ -99,11 +98,11 @@
     this.blockDataInput = new DataInputStream (this);
     this.realInputStream = new DataInputStream (in);
     this.nextOID = baseWireHandle;
-    this.objectLookupTable = new Hashtable ();
-    this.validators = new Vector ();
+    this.objectLookupTable = new Hashtable();
+    this.validators = new Vector();
     this.classLookupTable = new Hashtable();
     setBlockDataMode (true);
-    readStreamHeader ();
+    readStreamHeader();
   }
 
 
@@ -204,7 +203,7 @@
 	      Class cl = resolveProxyClass(intfs);
 	      setBlockDataMode(oldmode);
 	      
-	      ObjectStreamClass osc = lookupClass(cl);
+	      ObjectStreamClass osc = lookupClass (cl);
 	      assignNewHandle (osc);
 	      
 	      if (!is_consumed)
@@ -418,54 +417,63 @@
     return ret_val;
   }
 
+  /**
+   * This method reads a class descriptor from the real input stream
+   * and use these data to create a new instance of ObjectStreamClass.
+   * Fields are sorted and ordered for the real read which occurs for
+   * each instance of the described class. Be aware that if you call that
+   * method you must ensure that the stream is synchronized, in the other
+   * case it may be completely desynchronized.
+   *
+   * @return A new instance of ObjectStreamClass containing the freshly
+   * created descriptor.
+   * @throws ClassNotFoundException if the required class to build the
+   * descriptor has not been found in the system.
+   * @throws IOException An input/output error occured.
+   * @throws InvalidClassException If there was a compatibility problem
+   * between the class present in the system and the serialized class.
+   */
   protected ObjectStreamClass readClassDescriptor ()
     throws ClassNotFoundException, IOException
   {
+    dumpElement ("CLASSDESC NAME=");
     String name = this.realInputStream.readUTF ();
+    dumpElement (name + "; UID=");
     long uid = this.realInputStream.readLong ();
+    dumpElement (Long.toHexString(uid) + "; FLAGS=");
     byte flags = this.realInputStream.readByte ();
+    dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");
     short field_count = this.realInputStream.readShort ();
+    dumpElementln (Short.toString(field_count));
     ObjectStreamField[] fields = new ObjectStreamField[field_count];
     ObjectStreamClass osc = new ObjectStreamClass (name, uid,
                                                    flags, fields);
     assignNewHandle (osc);
-
-    dumpElementln("CLASSDESC NAME=" + name + "; UID=" + Long.toHexString(uid)
-		  + "; FLAGS=" + Integer.toHexString(flags) + "; FIELD COUNT="
-		  + field_count);
-    
-    int real_count = 0;
+	      
+    int real_count;
     for (int i=0; i < field_count; i++)
       {
+	dumpElement ("  TYPE CODE=");
 	char type_code = (char)this.realInputStream.readByte ();
+	dumpElement (type_code + "; FIELD NAME=");
 	String field_name = this.realInputStream.readUTF ();
+	dumpElementln (field_name);
 	String class_name;
-
-	dumpElementln ("  TYPE CODE=" + type_code + "; FIELD NAME=" + field_name);
-
-        ObjectStreamField of;
 	
-	// There're many cases you can't get java.lang.Class from
-	// typename if your context class loader can't load it,
-	// then use typename to construct the field
-	// GL => No. You lose the capability to access the class loader.
-	// Type resolution must be done here. If it is an object we
-	// create the class just here if it is something else we delegate
-	// to TypeSignature.
+	// If the type code is an array or an object we must
+	// decode a String here. In the other case we convert
+	// the type code and pass it to ObjectStreamField.
+	// Type codes are decoded by gnu.java.lang.reflect.TypeSignature.
 	if (type_code == 'L' || type_code == '[')
-	{
 	  class_name = (String)readObject ();
-	}
 	else
-	{
 	  class_name = String.valueOf (type_code);
-        }
-	
-        of = new ObjectStreamField (field_name, class_name, currentLoader());
-	
-	fields[i] = of;
+
+	fields[i] =
+	  new ObjectStreamField (field_name, class_name, currentLoader());
       }
 
+
     /* Now that fields have been read we may resolve the class
      * (and read annotation if needed). */
     Class clazz = resolveClass(osc);
@@ -489,7 +497,7 @@
       }
 
     boolean oldmode = setBlockDataMode (true);
-    osc.setClass (clazz, lookupClass(clazz.getSuperclass()));
+    osc.setClass (clazz, lookupClass (clazz.getSuperclass()));
     classLookupTable.put (clazz, osc);
     setBlockDataMode (oldmode);
 	      
@@ -519,10 +527,13 @@
     throws ClassNotFoundException, IOException, NotActiveException
   {
     if (this.currentObject == null || this.currentObjectStreamClass == null)
-      throw new NotActiveException ("defaultReadObject called by non-active class and/or object");
+      throw new NotActiveException ("defaultReadObject called by non-active"
+				    + " class and/or object");
 
     if (fieldsAlreadyRead)
-      throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
+      throw new NotActiveException ("defaultReadObject called but fields "
+				    + "already read from stream (by "
+				    + "defaultReadObject or readFields)");
 
     boolean oldmode = setBlockDataMode(false);
     readFields (this.currentObject, this.currentObjectStreamClass);
@@ -555,10 +566,12 @@
     throws InvalidObjectException, NotActiveException
   {
     if (this.currentObject == null || this.currentObjectStreamClass == null)
-      throw new NotActiveException ("registerValidation called by non-active class and/or object");
+      throw new NotActiveException ("registerValidation called by non-active "
+				    +"class and/or object");
 
     if (validator == null)
-      throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");
+      throw new InvalidObjectException ("attempt to add a null "
+					+"ObjectInputValidation object");
 
     this.validators.addElement (new ValidatorAndPriority (validator,
 							  priority));
@@ -587,19 +600,33 @@
     return Class.forName (osc.getName(), true, currentLoader()); 
   }
 
+  /**
+   * This method invokes the method currentClassLoader for the
+   * current security manager (or build an empty one if it is not
+   * present).
+   *
+   * @return The most recent non-system ClassLoader on the execution stack.
+   * @see java.lang.SecurityManager#currentClassLoader()
+   */
   private ClassLoader currentLoader ()
   {
     SecurityManager sm = System.getSecurityManager ();
     if (sm == null)
       sm = new SecurityManager () {};
-
+ 
     return currentClassLoader (sm);
   }
 
-  /* Lookup a class stored in the local hashtable. If it is not
+  /**
+   * Lookup a class stored in the local hashtable. If it is not
    * use the global lookup function in ObjectStreamClass to build
    * the ObjectStreamClass. This method is requested according to
    * the behaviour detected in the JDK by Kaffe's team.
+   *
+   * @param clazz Class to lookup in the hash table or for which
+   * we must build a descriptor. 
+   * @return A valid instance of ObjectStreamClass corresponding
+   * to the specified class.
    */
   private ObjectStreamClass lookupClass (Class clazz)
   {
@@ -612,10 +639,17 @@
       return oclazz;
   }
 
-  /* Reconstruct class hierarchy the same way
-   * ObjectStreamClass.getObjectStreamClasses does but using
-   * lookupClass instead of ObjectStreamClass.lookup. This
-   * dup is necessary localize the lookup table. :(
+  /**
+   * Reconstruct class hierarchy the same way
+   * {@link java.io.ObjectStreamClass.getObjectStreamClasses(java.lang.Class)} does
+   * but using lookupClass instead of ObjectStreamClass.lookup. This
+   * dup is necessary localize the lookup table. Hopefully some future
+   * rewritings will be able to prevent this.
+   *
+   * @param clazz This is the class for which we want the hierarchy.
+   *
+   * @return An array of valid {@link java.io.ObjectStreamClass} instances which
+   * represent the class hierarchy for clazz.
    */
   private ObjectStreamClass[] inputGetObjectStreamClasses (Class clazz)
   {
@@ -1002,6 +1036,19 @@
       throws IOException, IllegalArgumentException;
   }
 
+  /**
+   * This method should be called by a method called 'readObject' in the
+   * deserializing class (if present). It cannot (and should not)be called
+   * outside of it. Its goal is to read all fields in the real input stream
+   * and keep them accessible through the {@link #GetField} class. Calling
+   * this method will not alterate the deserializing object.
+   *
+   * @return A valid freshly created 'GetField' instance to get access to
+   * the deserialized stream.
+   * @throws IOException An input/output exception occured. 
+   * @throws ClassNotFoundException 
+   * @throws NotActiveException
+   */
   public GetField readFields ()
     throws IOException, ClassNotFoundException, NotActiveException
   {
@@ -1010,9 +1057,10 @@
 
     if (prereadFields != null)
       return prereadFields;
-    
+
     if (fieldsAlreadyRead)
-      throw new NotActiveException ("readFields called but fields already read from stream (by defaultReadObject or readFields)");
+      throw new NotActiveException ("readFields called but fields already read from"
+				    + " stream (by defaultReadObject or readFields)");
 
     final ObjectStreamClass clazz = this.currentObjectStreamClass;
     final byte[] prim_field_data = new byte[clazz.primFieldSize];
@@ -1026,7 +1074,7 @@
     for (int i = 0; i < objs.length; ++ i)
       objs[i] = readObject ();
     setBlockDataMode (oldmode);
-    
+
     prereadFields = new GetField ()
       {
 	public ObjectStreamClass getObjectStreamClass ()
@@ -1038,26 +1086,26 @@
 	  throws IOException, IllegalArgumentException
 	{
 	  ObjectStreamField f = clazz.getField (name);
-
+	  
 	  /* First if we have a serialized field use the descriptor */
 	  if (f != null)
-	  {
-	    /* It is in serialPersistentFields but setClass tells us
-	     * it should not be set. This value is defaulted.
-	     */
-	    if (f.isPersistent() && !f.isToSet())
-	      return true;
-	    
-	    return false;
-	  }
+	    {
+	      /* It is in serialPersistentFields but setClass tells us
+	       * it should not be set. This value is defaulted.
+	       */
+	      if (f.isPersistent() && !f.isToSet())
+		return true;
+	      
+	      return false;
+	    }
 
 	  /* This is not a serialized field. There should be
 	   * a default value only if the field really exists.
 	   */
 	  try
-	  {
-	    return (clazz.forClass().getDeclaredField (name) != null);
-	  }
+	    {
+	      return (clazz.forClass().getDeclaredField (name) != null);
+	    }
 	  catch (NoSuchFieldException e)
 	    {
 	      throw new IllegalArgumentException (e.getMessage());
@@ -1209,18 +1257,15 @@
 	    {
 	      try
 		{
-		  Class field_type = field.getType ();
+		  Class field_type = field.getType();
 		  
 		  if (type == field_type ||
-		      (type == null && ! field_type.isPrimitive ()))
+		      (type == null && !field_type.isPrimitive()))
 		    {
 		      /* See defaulted */
-		      /*if (field.isPersistent() && !field.isToSet())
-			return null;*/
-		      
 		      return field;
 		    }
-		 
+	 
 		  illegal = true;
 		  throw new IllegalArgumentException ("Field requested is of type "
 						      + field_type.getName ()
@@ -1229,7 +1274,13 @@
 							 "Object" : type.getName ()));
 		}
 	      catch (NullPointerException _)
-		{}
+		{
+		  /* Here we catch NullPointerException, because it may
+		     only come from the call 'field.getType()'. If field
+		     is null, we have to return null and classpath ethic
+		     say we must try to avoid 'if (xxx == null)'.
+		  */
+		}
 	      catch (IllegalArgumentException e)
 		{
 		  throw e;
@@ -1247,13 +1298,14 @@
 	      /* We do not want to modify transient fields. They should
 	       * be left to 0.
 	       */
-	      try {
-		Field f = clazz.forClass().getDeclaredField (name);
-		if (Modifier.isTransient(f.getModifiers()))
-		  throw new IllegalArgumentException("no such field (non transient) " + name);
-		if (field == null && f.getType() != type)
-		  throw new IllegalArgumentException ("Invalid requested type for field " + name);
-	      }
+	      try
+		{
+		  Field f = clazz.forClass().getDeclaredField (name);
+		  if (Modifier.isTransient(f.getModifiers()))
+		    throw new IllegalArgumentException("no such field (non transient) " + name);
+		  if (field == null && f.getType() != type)
+		    throw new IllegalArgumentException ("Invalid requested type for field " + name);
+		}
 	      catch (NoSuchFieldException e)
 		{
 		  if (field == null)
@@ -1264,8 +1316,8 @@
 	}
       };
 
-      fieldsAlreadyRead = true;
-      return prereadFields;
+    fieldsAlreadyRead = true;
+    return prereadFields;
   }
 
   /**
@@ -1303,7 +1355,12 @@
     throw new IOException ("Subclass of ObjectInputStream must implement readObjectOverride");
   }
 
-  // assigns the next availible handle to OBJ
+  /**
+   * Assigns the next available handle to <code>obj</code>.
+   *
+   * @param obj The object for which we want a new handle.
+   * @return A valid handle for the specified object.
+   */
   private int assignNewHandle (Object obj)
   {
     this.objectLookupTable.put (new Integer (this.nextOID),
@@ -1370,8 +1427,7 @@
       }
     else
       {
-	throw new EOFException ("Attempt to read primitive data, but no data block is active. Marker is 0x" +
-				Integer.toHexString((int)marker));
+	throw new EOFException ("Attempt to read primitive data, but no data block is active.");
       }
 
     if (this.blockData.length < this.blockDataBytes)
@@ -1516,9 +1572,9 @@
 	    default_initialize = true;
 	    set_value = false;
 	  }
-
+	
 	if (!stream_field.isToSet()) 
-	    set_value = false;
+	  set_value = false;
 
 	try
 	  {
@@ -1658,16 +1714,33 @@
       }
   }
 
-  // this native method is used to get access to the protected method
-  // of the same name in SecurityManger
+  /**
+   * This native method is used to get access to the protected method
+   * of the same name in SecurityManger.
+   *
+   * @param sm SecurityManager instance which should be called.
+   * @return The current class loader in the calling stack.
+   */
   private static native ClassLoader currentClassLoader (SecurityManager sm);
 
+  /**
+   * This method tries to access a precise field called in the
+   * specified class. Before accessing the field, it tries to
+   * gain control on this field. If the field is either declared as 
+   * not persistent or transient then it returns null
+   * immediately.
+   *
+   * @param klass Class to get the field from.
+   * @param name Name of the field to access.
+   * @return Field instance representing the requested field.
+   * @throws NoSuchFieldException if the field does not exist.
+   */
   private Field getField (Class klass, String name)
     throws java.lang.NoSuchFieldException
   {
     final Field f = klass.getDeclaredField(name);
     ObjectStreamField sf = lookupClass (klass).getField(name);
-
+    
     AccessController.doPrivileged(new PrivilegedAction()
       {
 	public Object run()
@@ -1705,7 +1778,6 @@
   private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException
   {
     Class klass = osc.forClass();
-
     try
       {
 	Class classArgs[] = {ObjectInputStream.class};
@@ -1719,13 +1791,13 @@
       }
     catch (InvocationTargetException x)
       {
-	/* Rethrow if possible. */
+        /* Rethrow if possible. */
 	Throwable exception = x.getTargetException();
 	if (exception instanceof RuntimeException)
 	  throw (RuntimeException) exception;
 	if (exception instanceof IOException)
 	  throw (IOException) exception;
-	
+
 	throw new IOException ("Exception thrown from readObject() on " +
 			       klass + ": " + exception.getClass().getName());
       }
@@ -1741,8 +1813,19 @@
 
   private native void callConstructor (Class clazz, Object obj);
 
+  /**
+   * This method writes a "boolean" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The boolean value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setBooleanField (Object obj, Class klass, String field_name,
-				boolean val) throws IOException
+				boolean val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1755,11 +1838,22 @@
       }
     catch (Exception _)
       {
-      }
+      }    
   }
 
+  /**
+   * This method writes a "byte" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The byte value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setByteField (Object obj, Class klass, String field_name,
-			     byte val) throws IOException
+			     byte val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1772,11 +1866,22 @@
       }
     catch (Exception _)
       {
-      }
+      }    
   }
 
+  /**
+   * This method writes a "character" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The character value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setCharField (Object obj, Class klass, String field_name,
-			     char val) throws IOException
+			     char val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1789,11 +1894,22 @@
       }
     catch (Exception _)
       {
-      }
+      }    
   }
 
+  /**
+   * This method writes a "double" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The double value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setDoubleField (Object obj, Class klass, String field_name,
-			       double val) throws IOException
+			       double val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1806,11 +1922,22 @@
       }
     catch (Exception _)
       {
-      }
+      }    
   }
 
+  /**
+   * This method writes a "float" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The float value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setFloatField (Object obj, Class klass, String field_name,
-			      float val) throws IOException
+			      float val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1826,8 +1953,19 @@
       }    
   }
 
+  /**
+   * This method writes an "integer" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The integer value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setIntField (Object obj, Class klass, String field_name,
-			    int val) throws IOException
+			    int val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1843,9 +1981,19 @@
       }    
   }
 
-
+  /**
+   * This method writes the long value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The long value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setLongField (Object obj, Class klass, String field_name,
-			     long val) throws IOException
+			     long val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1861,9 +2009,19 @@
       }    
   }
 
-
+  /**
+   * This method writes a "short" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The short value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setShortField (Object obj, Class klass, String field_name,
-			      short val) throws IOException
+			      short val) throws IOException, InvalidClassException
   {
     try
       {
@@ -1879,19 +2037,29 @@
       }    
   }
 
-
+  /**
+   * This method writes an "object" value <code>val</code> in the specified field
+   * of the instance <code>obj</code> of the type <code>klass</code>.
+   *
+   * @param obj Instance to setup.
+   * @param klass Class type of the specified instance.
+   * @param field_name Name of the field in the specified class type.
+   * @param val The "object" value to write into the field.
+   * @throws InvalidClassException if the specified field has not the required type.
+   * @throws IOException if there is no field of that name in the specified class.
+   */
   private void setObjectField (Object obj, Class klass, String field_name,
-			       String type_code, Object val) throws IOException
+			       String type_code, Object val) throws IOException, InvalidClassException
   {
     try
       {
-	Field f = getField (klass, field_name);
+ 	Field f = getField (klass, field_name);
 	ObjectStreamField of = new ObjectStreamField(field_name, f.getType());
-
+	
 	if (of.getTypeString() == null ||
 	    !of.getTypeString().equals(type_code))
           throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-	f.set (obj, val);
+ 	f.set (obj, val);
       }
     catch (InvalidClassException e)
       {
Index: kaffe/libraries/javalib/java/io/ObjectOutputStream.java
diff -u kaffe/libraries/javalib/java/io/ObjectOutputStream.java:1.17 kaffe/libraries/javalib/java/io/ObjectOutputStream.java:1.18
--- kaffe/libraries/javalib/java/io/ObjectOutputStream.java:1.17	Tue Aug 12 07:02:21 2003
+++ kaffe/libraries/javalib/java/io/ObjectOutputStream.java	Sun Dec 14 09:26:56 2003
@@ -989,8 +989,9 @@
 	  ObjectStreamField field = getField (name);
 
 	  if (value != null &&
-	      ! field.getType ().isAssignableFrom (value.getClass ()))
-	    throw new IllegalArgumentException ();
+	      ! field.getType ().isAssignableFrom (value.getClass ()))	    
+	    throw new IllegalArgumentException ("Class " + value.getClass() +
+						" cannot be cast to " + field.getType());
 	  objs[field.getOffset ()] = value;
 	}
 
Index: kaffe/libraries/javalib/java/io/ObjectStreamClass.java
diff -u kaffe/libraries/javalib/java/io/ObjectStreamClass.java:1.15 kaffe/libraries/javalib/java/io/ObjectStreamClass.java:1.16
--- kaffe/libraries/javalib/java/io/ObjectStreamClass.java:1.15	Mon Aug 11 17:55:44 2003
+++ kaffe/libraries/javalib/java/io/ObjectStreamClass.java	Sun Dec 14 09:26:56 2003
@@ -203,15 +203,15 @@
   boolean hasReadMethod ()
   {
       try
-	{
+      {
 	  Class[] readObjectParams = { ObjectInputStream.class };
 	  forClass ().getDeclaredMethod ("readObject", readObjectParams);
 	  return true;
-	}
+      }
       catch (NoSuchMethodException e)
-	{
+      {
 	  return false;
-	}
+      }
   }
 
 
@@ -249,8 +249,6 @@
   {
     ObjectStreamClass osc = ObjectStreamClass.lookup (clazz);
 
-    ObjectStreamClass[] ret_val;
-
     if (osc == null)
       return new ObjectStreamClass[0];
     else
@@ -293,6 +291,17 @@
     this.fields = fields;
   }
 
+  /**
+   * This method builds the internal description corresponding to a Java Class.
+   * As the constructor only assign a name to the current ObjectStreamClass instance,
+   * that method sets the serial UID, chose the fields which will be serialized,
+   * and compute the position of the fields in the serialized stream.
+   *
+   * @param cl The Java class which is used as a reference for building the descriptor.
+   * @param superClass The descriptor of the super class for this class descriptor.
+   * @throws InvalidClassException if an incompatibility between computed UID and
+   * already set UID is found.
+   */
   void setClass (Class cl, ObjectStreamClass superClass) throws InvalidClassException
   {
     this.clazz = cl;
@@ -472,19 +481,18 @@
       flags |= ObjectStreamConstants.SC_SERIALIZABLE;
 
     try
-      {
-	Method writeMethod = cl.getDeclaredMethod ("writeObject",
-						   writeMethodArgTypes);
-	int modifiers = writeMethod.getModifiers ();
-	
-	if (writeMethod.getReturnType () == Void.TYPE
-	    && Modifier.isPrivate (modifiers)
-	    && !Modifier.isStatic (modifiers))
-	  flags |= ObjectStreamConstants.SC_WRITE_METHOD;
-      }
+    {
+      Method writeMethod = cl.getDeclaredMethod ("writeObject",
+						 writeMethodArgTypes);
+      int modifiers = writeMethod.getModifiers ();
+
+      if (writeMethod.getReturnType () == Void.TYPE
+	  && Modifier.isPrivate (modifiers)
+	  && !Modifier.isStatic (modifiers))
+	flags |= ObjectStreamConstants.SC_WRITE_METHOD;
+    }
     catch (NoSuchMethodException oh_well)
-      {
-      }
+    {}
   }
 
 
@@ -499,14 +507,25 @@
     }
 
     try
+    {
+      Field serialPersistentFields
+	= cl.getDeclaredField ("serialPersistentFields");
+      serialPersistentFields.setAccessible(true);
+      int modifiers = serialPersistentFields.getModifiers ();
+
+      if (Modifier.isStatic (modifiers)
+	  && Modifier.isFinal (modifiers)
+	  && Modifier.isPrivate (modifiers))
       {
 	fields = getSerialPersistentFields (cl);
-	if (fields != null) {
-	  Arrays.sort (fields);
-	  calculateOffsets ();
-	  return;
-	}
+	if (fields != null)
+	  {
+	    Arrays.sort (fields);
+	    calculateOffsets ();
+	    return;
+	  }
       }
+    }
     catch (NoSuchFieldException ignore)
       {}
     catch (IllegalAccessException ignore)
@@ -546,172 +565,180 @@
   private long getClassUID (Class cl)
   {
     try
-      {
-	// Use getDeclaredField rather than getField, since serialVersionUID
-	// may not be public AND we only want the serialVersionUID of this
-	// class, not a superclass or interface.
-	Field suid = cl.getDeclaredField ("serialVersionUID");
-	suid.setAccessible(true);
-	int modifiers = suid.getModifiers ();
-	
-	if (Modifier.isStatic (modifiers)
-	    && Modifier.isFinal (modifiers)
-	    && suid.getType() == Long.TYPE)
-	  return suid.getLong (null);
-      }
+    {
+      // Use getDeclaredField rather than getField, since serialVersionUID
+      // may not be public AND we only want the serialVersionUID of this
+      // class, not a superclass or interface.
+      Field suid = cl.getDeclaredField ("serialVersionUID");
+      suid.setAccessible(true);
+      int modifiers = suid.getModifiers ();
+
+      if (Modifier.isStatic (modifiers)
+	  && Modifier.isFinal (modifiers)
+	  && suid.getType() == Long.TYPE)
+	return suid.getLong (null);
+    }
     catch (NoSuchFieldException ignore)
-      {}
+    {}
     catch (IllegalAccessException ignore)
-      {}
-    
+    {}
+
     // cl didn't define serialVersionUID, so we have to compute it
     try
-      {
-	MessageDigest md;
-	try 
-	  {
-	    md = MessageDigest.getInstance ("SHA");
-	  }
-	catch (NoSuchAlgorithmException e)
-	  {
-	    // If a provider already provides SHA, use it; otherwise, use this.
-	    //	  Gnu gnuProvider = new Gnu();

*** Patch too long, truncated ***