TAPESTRY-2570: Fixed NPE issue when trying to report an exception involving an instance that returns null for toString() + move around some variables definition to improve readability

git-svn-id: https://svn.apache.org/repos/asf/tapestry/tapestry4/trunk@833891 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tapestry-framework/src/java/org/apache/tapestry/util/exception/ExceptionAnalyzer.java b/tapestry-framework/src/java/org/apache/tapestry/util/exception/ExceptionAnalyzer.java
index abb3f8a..1ba34a9 100644
--- a/tapestry-framework/src/java/org/apache/tapestry/util/exception/ExceptionAnalyzer.java
+++ b/tapestry-framework/src/java/org/apache/tapestry/util/exception/ExceptionAnalyzer.java
@@ -101,30 +101,15 @@
     }
 
     protected Throwable buildDescription(Throwable exception)
-    {
-        BeanInfo info;
-        Class exceptionClass;
-        ExceptionProperty property;
-        PropertyDescriptor[] descriptors;
-        PropertyDescriptor descriptor;
-        Throwable next = null;
-        int i;
-        Object value;
-        Method method;
-        ExceptionProperty[] properties;
-        ExceptionDescription description;
-        String stringValue;
-        String message;
-        String[] stackTrace = null;
-
+    {   
         propertyDescriptions.clear();
-
-        message = exception.getMessage();
-        exceptionClass = exception.getClass();
+        
+        Class exceptionClass = exception.getClass();
 
         // Get properties, ignoring those in Throwable and higher
         // (including the 'message' property).
 
+        BeanInfo info;
         try
         {
             info = Introspector.getBeanInfo(exceptionClass, Throwable.class);
@@ -134,13 +119,16 @@
             return null;
         }
 
-        descriptors = info.getPropertyDescriptors();
+        Object value;
+        Throwable next = null;
+        String message = exception.getMessage();
+        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
 
-        for (i = 0; i < descriptors.length; i++)
+        for (int i = 0; i < descriptors.length; i++)
         {
-            descriptor = descriptors[i];
+        	PropertyDescriptor descriptor = descriptors[i];
 
-            method = descriptor.getReadMethod();
+            Method method = descriptor.getReadMethod();
             if (method == null)
                 continue;
 
@@ -175,29 +163,35 @@
                 continue;
             }
 
-            stringValue = value.toString().trim();
+            String stringValue = value.toString();
+            
+            if (stringValue == null)
+            	continue;
+            
+            stringValue = stringValue.trim();            
 
             if (stringValue.length() == 0)
                 continue;
 
-            property = new ExceptionProperty(descriptor.getDisplayName(), value);
+            ExceptionProperty property = new ExceptionProperty(descriptor.getDisplayName(), value);
 
             propertyDescriptions.add(property);
         }
 
         // If exhaustive, or in the deepest exception (where there's no next)
         // the extract the stack trace.
-
+        String[] stackTrace = null;
+        
         if (next == null || exhaustive)
             stackTrace = getStackTrace(exception);
 
         // Would be nice to sort the properties here.
 
-        properties = new ExceptionProperty[propertyDescriptions.size()];
+        ExceptionProperty[] properties = new ExceptionProperty[propertyDescriptions.size()];
 
         ExceptionProperty[] propArray = (ExceptionProperty[]) propertyDescriptions.toArray(properties);
 
-        description = new ExceptionDescription(exceptionClass.getName(), message, propArray, stackTrace);
+        ExceptionDescription description = new ExceptionDescription(exceptionClass.getName(), message, propArray, stackTrace);
 
         exceptionDescriptions.add(description);
 
diff --git a/tapestry-framework/src/test/org/apache/tapestry/util/exception/TestExceptionAnalyzer.java b/tapestry-framework/src/test/org/apache/tapestry/util/exception/TestExceptionAnalyzer.java
new file mode 100644
index 0000000..ccc3595
--- /dev/null
+++ b/tapestry-framework/src/test/org/apache/tapestry/util/exception/TestExceptionAnalyzer.java
@@ -0,0 +1,52 @@
+package org.apache.tapestry.util.exception;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@Test
+public class TestExceptionAnalyzer extends Assert {
+	
+	public void test_report_exception() {
+		ApplicationRuntimeException ex = new ApplicationRuntimeException("TAPerrorSTRY");		
+		
+		ByteArrayOutputStream stream = new ByteArrayOutputStream();
+		
+		new ExceptionAnalyzer().reportException(ex, new PrintStream(stream));
+		
+		String output = stream.toString();
+			
+		assertTrue(output.contains("org.apache.hivemind.ApplicationRuntimeException"));
+		assertTrue(output.contains("TAPerrorSTRY"));
+	}
+	
+	// test for TAPESTRY-2570
+	public void test_with_null_tostring_exception() {
+		Exception dummyException = new Exception("TAPerrorSTRY"){
+			public Object getDummy() {
+				return new Object(){
+					@Override
+					public String toString() {
+						return null;
+					}
+				};
+			}
+		};
+		ApplicationRuntimeException ex = new ApplicationRuntimeException(dummyException);
+		
+		ByteArrayOutputStream stream = new ByteArrayOutputStream();
+		
+		new ExceptionAnalyzer().reportException(ex, new PrintStream(stream));
+		
+		String output = stream.toString();
+		
+		assertTrue(output.contains("org.apache.hivemind.ApplicationRuntimeException"));
+		assertTrue(output.contains("TAPerrorSTRY"));
+		
+	}
+	
+	
+}