Index: SpreadConnection.java
===================================================================
RCS file: /storage/cvsroot/spread/javalib/SpreadConnection.java,v
retrieving revision 1.7
diff -u -r1.7 SpreadConnection.java
--- SpreadConnection.java	5 Mar 2004 00:37:12 -0000	1.7
+++ SpreadConnection.java	22 Apr 2004 16:15:20 -0000
@@ -348,7 +348,7 @@
 		}
 		catch(SocketException e)
 		{
-			throw new SpreadException("set/getSend/ReceiveBufferSize(): " + e);
+			throw new SpreadException("Socket buffer size manipulation failed", e);
 		}
 NOT SUPPORTED IN 1.1	*/
 	}
@@ -417,7 +417,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("write(): " + e);
+			throw new SpreadException("Sending connection message failed", e);
 		}		
 	}
 
@@ -434,7 +434,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading auth methods failed", e);
 		}
 		
 		// System.out.println("readAuthMethods: len is " + len);
@@ -448,7 +448,7 @@
 		//////////////////////////////////
 		if( len < -1 )
 		{
-			throw new SpreadException("Connection attempt rejected=" + (byte)len);
+			throw new SpreadException("Connection attempt rejected (message len " + (byte)len + ')');
 		}
 
 		// Read the name.
@@ -461,7 +461,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading name failed", e);
 		}
 		
 		// System.out.println("readAuthMethods: string is " + new String(buffer));
@@ -470,7 +470,7 @@
 		/////////////////////////////
 		if(numRead != len)
 		{
-			throw new SpreadException("Connection clsoed during connect attempt to read authnames");
+			throw new SpreadException("Connection closed during connect attempt to read authnames");
 		}
 		
 		// for now we ignore the list.
@@ -506,7 +506,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("write(): " + e);
+			throw new SpreadException("Sending auth method failed", e);
 		}		
 	}
 
@@ -521,13 +521,13 @@
 		try {
 			authclass = Class.forName(authClassName);
 		} catch (ClassNotFoundException e) {
-			throw new SpreadException("class " + authClassName + " not found.\n");
+			throw new SpreadException("Class '" + authClassName + "' not found", e);
 		}
 
 		try {
 			authObj = authclass.newInstance();
 		} catch (Exception e) {
-			throw new SpreadException("class " + authClassName + " error getting instance.\n" + e);
+			throw new SpreadException("Error creating instance of class '" + authClassName + '\'', e);
 		}
 		try {
 		    authMethodAuthenticate = authclass.getMethod("authenticate", new Class[] { });
@@ -554,7 +554,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading handshake response failed", e);
 		}
 		
 		// Check for no more data.
@@ -568,7 +568,7 @@
 		///////////////////
 		if(accepted != ACCEPT_SESSION)
 		{
-			throw new SpreadException("Connection attempt rejected=" + (byte)accepted);
+			throw new SpreadException("Connection attempt rejected: " + (byte)accepted + " does not signify an accepted connection");
 		}
 	}
 	
@@ -585,7 +585,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading version failed", e);
 		}
 		
 		// Read the sub-version.
@@ -597,7 +597,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Read sub-version failed", e);
 		}
 		
 		// Read the patch-version.
@@ -609,14 +609,14 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading patch version failed", e);
 		}
 		
 		// Check for no more data.
 		//////////////////////////
 		if((majorVersion == -1) || (minorVersion == -1) || (patchVersion == -1) )
 		{
-			throw new SpreadException("Connection closed during connect attempt");
+			throw new SpreadException("Full version info indeterminate: Connection closed during connect attempt");
 		}
 		
 		// Check the version.
@@ -645,7 +645,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading group failed", e);
 		}
 		
 		// Check for no more data.
@@ -665,7 +665,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading name failed", e);
 		}
 		
 		// Check for not enough data.
@@ -778,7 +778,7 @@
 		}
 		catch(UnsupportedEncodingException e)
 		{
-			throw new SpreadException("ISO8859_1 encoding is not supported.");
+			throw new SpreadException("ISO8859_1 encoding is not supported", e);
 		}
 		
 		// Store member variables.
@@ -800,7 +800,7 @@
 			}
 			catch(UnknownHostException e)
 			{
-				throw new SpreadException("Error getting local host");
+				throw new SpreadException("Error getting local host", e);
 			}
 		}
 		
@@ -815,9 +815,10 @@
 		
 		// Check if the port is out of range.
 		/////////////////////////////////////
-		if((port < 0) || (port > (32 * 1024)))
+		if (port < 0 || port > (32 * 1024))
 		{
-			throw new SpreadException("Bad port (" + port + ").");
+			throw new SpreadException("Invalid port number '" + port +
+                                      "': Valid range is 0-" + (32 * 1024));
 		}
 		
 		// Create the socket.
@@ -828,7 +829,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("Socket(): " + e);
+			throw new SpreadException("Socket creation failed", e);
 		}
 		
 		// Set the socket's buffer sizes.
@@ -844,7 +845,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("getInput/OutputStream(): " + e);
+			throw new SpreadException("Retrieval of socket input/output streams failed", e);
 		}
 		
 		// Send the connect message.
@@ -872,16 +873,21 @@
 		try {
 			    authMethodAuthenticate.invoke( authObj, new Object[] { });
 		    } catch (IllegalAccessException e) {
-			    System.out.println("error calling authenticate" + e.toString() );
+			    System.err.println("error calling authenticate" + e.toString() );
 			    System.exit(1);
 		    } catch (IllegalArgumentException e) {
-			    System.out.println("error calling authenticate" + e.toString() );
+			    System.err.println("error calling authenticate" + e.toString() );
 			    System.exit(1);
 		    } catch (java.lang.reflect.InvocationTargetException e) {
 			    Throwable thr = e.getTargetException();
 			    if ( thr.getClass().equals(SpreadException.class) )
 			    {
-				 throw new SpreadException("Connection Rejected: Authentication failed");   
+				 throw new SpreadException("Connection Rejected: Authentication failed", e);
+			    }
+			    else
+			    {
+				 System.err.println("Auth method invocation failed");
+				 e.printStackTrace();
 			    }
 		}
 		// Check for acceptance.
@@ -974,7 +980,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("close(): " + e);
+			throw new SpreadException("Closing socket failed", e);
 		}
 
 		connected = false;
@@ -1057,7 +1063,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading header failed", e);
 		}
 		
 		// Reset header index.
@@ -1181,7 +1187,7 @@
                         }
                         catch(IOException e)
                         {
-                                throw new SpreadException("read(): " + e);
+                                throw new SpreadException("Reading groups failed", e);
                         }
                         int oldType = toInt(oldtypeBuffer, 0);
                         if ( sameEndian(serviceType) == false )
@@ -1210,7 +1216,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read(): " + e);
+			throw new SpreadException("Reading groups failed", e);
 		}
 		
 		// Clear the endian type.
@@ -1247,7 +1253,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("read():" + e);
+			throw new SpreadException("Reading data failed", e);
 		}
 		
 		// Is it a membership message?
@@ -1349,7 +1355,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("available(): " + e);
+			throw new SpreadException("Socket input unavailable", e);
 		}
 		
 		// There's something to read.
@@ -1841,7 +1847,7 @@
 		
 		if (numBytes + data.length > MAX_MESSAGE_LENGTH )
 		{
-		    throw new SpreadException("Message is too long for a Spread Message");
+		    throw new SpreadException("Message is too long for a Spread Message: " + (numBytes + data.length) + " bytes");
 		}
 		// Allocate the send buffer.
 		////////////////////////////
@@ -1891,7 +1897,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("write(): " + e.toString());
+			throw new SpreadException("Writing multicast failed", e);
 		}
 	}
 	}
Index: SpreadException.java
===================================================================
RCS file: /storage/cvsroot/spread/javalib/SpreadException.java,v
retrieving revision 1.3
diff -u -r1.3 SpreadException.java
--- SpreadException.java	5 Mar 2004 00:37:12 -0000	1.3
+++ SpreadException.java	22 Apr 2004 16:15:20 -0000
@@ -35,6 +35,9 @@
 
 package spread;
 
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
 /**
  * A SpreadException is thrown whenever a problem occurs in a spread method.
  * One example is calling a SpreadConnection object's {@link SpreadConnection#receive()} method
@@ -47,8 +50,8 @@
  */
 public class SpreadException extends Exception
 {
-	// Constructor.
-	///////////////
+	private Throwable cause;
+
 	/**
 	 * Creates a SpreadException with no error message.
 	 */
@@ -57,8 +60,6 @@
 		super();
 	}
 	
-	// Constructor.
-	///////////////
 	/**
 	 * Creates a SpreadException with an error message.
 	 * 
@@ -68,4 +69,56 @@
 	{
 		super(errorMessage);
 	}
+
+	/**
+	 * Creates a SpreadException with an error message.
+	 * 
+	 * @param  errorMessage  a description of the error
+        * @param  cause  The root cause of this exception.
+	 */
+	public SpreadException(String errorMessage, Throwable cause)
+	{
+		super(errorMessage);
+               this.cause = cause;
+	}
+
+    /**
+     * Includes info from any root cause exception.
+     */
+    public String getMessage()
+    {
+        String msg = super.getMessage();
+        if (cause != null)
+        {
+            msg += ": " + cause.getMessage();
+        }
+        return msg;
+    }
+
+    /**
+     * Includes info from any root cause exception.
+     */
+    public void printStackTrace(PrintStream s)
+    {
+        super.printStackTrace(s);
+        if (cause != null)
+        {
+            s.println("--- root cause ---");
+            cause.printStackTrace(s);
+        }
+    }
+
+    /**
+     * Includes info from any root cause exception.
+     */
+    public void printStackTrace(PrintWriter w)
+    {
+        super.printStackTrace(w);
+        if (cause != null)
+        {
+            w.write("--- root cause ---");
+            w.write(System.getProperty("line.separator"));
+            cause.printStackTrace(w);
+        }
+    }
 }
Index: SpreadGroup.java
===================================================================
RCS file: /storage/cvsroot/spread/javalib/SpreadGroup.java,v
retrieving revision 1.5
diff -u -r1.5 SpreadGroup.java
--- SpreadGroup.java	5 Mar 2004 00:37:12 -0000	1.5
+++ SpreadGroup.java	22 Apr 2004 16:15:20 -0000
@@ -126,7 +126,7 @@
 		}
 		catch(UnsupportedEncodingException e)
 		{
-			throw new SpreadException("ISO8859_1 encoding not supported.");
+			throw new SpreadException("ISO8859_1 encoding not supported", e);
 		}
 		for(int i = 0 ; i < bytes.length ; i++)
 		{
Index: SpreadMessage.java
===================================================================
RCS file: /storage/cvsroot/spread/javalib/SpreadMessage.java,v
retrieving revision 1.3
diff -u -r1.3 SpreadMessage.java
--- SpreadMessage.java	5 Mar 2004 00:37:12 -0000	1.3
+++ SpreadMessage.java	22 Apr 2004 16:15:20 -0000
@@ -551,7 +551,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("ObjectInputStream(): " + e);
+			throw new SpreadException("Reading object failed", e);
 		}
 			
 		// De-serialize the object.
@@ -563,11 +563,11 @@
 		}
 		catch(ClassNotFoundException e)
 		{
-			throw new SpreadException("readObject(): " + e);
+			throw new SpreadException("Type of object to read not found", e);
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("readObject(): " + e);
+			throw new SpreadException("Reading object failed", e);
 		}
 			
 		// Close the streams.
@@ -579,7 +579,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("close/close(): " + e);
+			throw new SpreadException("Closing object input stream failed", e);
 		}
 			
 		// Return the object.
@@ -618,7 +618,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("ObjectInputStream(): " + e);
+			throw new SpreadException("Creating object input stream failed", e);
 		}
 			
 		// While there are objects to read.
@@ -644,11 +644,11 @@
 		}
 		catch(ClassNotFoundException e)
 		{
-			throw new SpreadException("readObject(): " + e);
+			throw new SpreadException("Type of object to read not found", e);
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("readObject(): " + e);
+			throw new SpreadException("Reading object failed", e);
 		}
 			
 		// Close the streams.
@@ -660,7 +660,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("close/close(): " + e);
+			throw new SpreadException("Closing object intput stream failed", e);
 		}
 			
 		// Return the digest.
@@ -828,7 +828,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("ObjectOutputStream(): " + e);
+			throw new SpreadException("Creating ObjectOutputStream failed", e);
 		}
 		
 		// Serialize the object.
@@ -840,7 +840,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("writeObject/flush(): " + e);
+			throw new SpreadException("Writing object failed", e);
 		}
 		
 		// Store the bytes.
@@ -856,7 +856,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("close/close(): " + e);
+			throw new SpreadException("Closing object output stream failed", e);
 		}
 	}
 	
@@ -895,7 +895,7 @@
 			}
 			catch(IOException e)
 			{
-				throw new SpreadException("ObjectOutputStream(): " + e);
+				throw new SpreadException("Creating object output stream failed", e);
 			}
 		}
 		
@@ -908,7 +908,7 @@
 		}
 		catch(IOException e)
 		{
-			throw new SpreadException("writeObject/flush(): " + e);
+			throw new SpreadException("Writing object failed", e);
 		}
 	}
 	