Author: joehni
Date: Mon Mar 15 17:11:55 2010
New Revision: 923341

URL: http://svn.apache.org/viewvc?rev=923341&view=rev
Log:
Fix DefaultExceptionContext.addValue that overwrites information in a recursive 
situation (LANG-605). Allow explicit replacement of a label with the new 
replaceValue methods.

Modified:
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedException.java
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java
    
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java
    
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java
    
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java
    
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedException.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedException.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedException.java
 (original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedException.java
 Mon Mar 15 17:11:55 2010
@@ -139,9 +139,11 @@ public class ContextedException extends 
     /**
      * Adds information helpful to a developer in diagnosing and correcting
      * the problem.  For the information to be meaningful, the value passed
-     * should have a reasonable toString() implementation.
+     * should have a reasonable toString() implementation. If the added label
+     * is already available, the label is appended with an index.
      * <p>
      * Note: This exception is only serializable if the object added is 
serializable.
+     * </p>
      * 
      * @param label  a textual label associated with information, null not 
recommended
      * @param value  information needed to understand exception, may be null
@@ -153,6 +155,24 @@ public class ContextedException extends 
     }
 
     /**
+     * Replaces information helpful to a developer in diagnosing and correcting
+     * the problem.  For the information to be meaningful, the value passed
+     * should have a reasonable toString() implementation. If the replaced
+     * label does not yet exist, it is simply added.
+     * <p>
+     * Note: This exception is only serializable if the object added is 
serializable.
+     * </p>
+     * 
+     * @param label  a textual label associated with information, null not 
recommended
+     * @param value  information needed to understand exception, may be null
+     * @return this, for method chaining
+     */
+    public ContextedException replaceValue(String label, Object value) {       
 
+        exceptionContext.replaceValue(label, value);
+        return this;
+    }
+
+    /**
      * Retrieves a contextual data value associated with the label.
      * 
      * @param label  the label to get the contextual value for, may be null

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java
 (original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java
 Mon Mar 15 17:11:55 2010
@@ -64,7 +64,6 @@ import java.util.Set;
  * @see ContextedException
  * @author Apache Software Foundation
  * @author D. Ashmore
- * @author J&ouml;rg Schaible
  * @since 3.0
  */
 public class ContextedRuntimeException extends RuntimeException implements 
ExceptionContext {
@@ -140,9 +139,11 @@ public class ContextedRuntimeException e
     /**
      * Adds information helpful to a developer in diagnosing and correcting
      * the problem.  For the information to be meaningful, the value passed
-     * should have a reasonable toString() implementation.
+     * should have a reasonable toString() implementation. If the added label
+     * is already available, the label is appended with an index.
      * <p>
      * Note: This exception is only serializable if the object added is 
serializable.
+     * </p>
      * 
      * @param label  a textual label associated with information, null not 
recommended
      * @param value  information needed to understand exception, may be null
@@ -154,6 +155,24 @@ public class ContextedRuntimeException e
     }
 
     /**
+     * Replaces information helpful to a developer in diagnosing and correcting
+     * the problem.  For the information to be meaningful, the value passed
+     * should have a reasonable toString() implementation. If the replaced
+     * label does not yet exist, it is simply added.
+     * <p>
+     * Note: This exception is only serializable if the object added is 
serializable.
+     * </p>
+     * 
+     * @param label  a textual label associated with information, null not 
recommended
+     * @param value  information needed to understand exception, may be null
+     * @return this, for method chaining
+     */
+    public ContextedRuntimeException replaceValue(String label, Object value) 
{        
+        exceptionContext.replaceValue(label, value);
+        return this;
+    }
+
+    /**
      * Retrieves a contextual data value associated with the label.
      * 
      * @param label  the label to get the contextual value for, may be null

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java
 (original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java
 Mon Mar 15 17:11:55 2010
@@ -43,13 +43,41 @@ class DefaultExceptionContext implements
     /**
      * Adds a contextual label-value pair into this context.
      * <p>
-     * This label-value pair provides information useful for debugging.
+     * This label-value pair provides information useful for debugging. If the
+     * label already exists and the provided information is different, the 
+     * label will be added with an appended index.
+     * </p>
      * 
      * @param label  the label of the item to add, null not recommended
      * @param value  the value of item to add, may be null
      * @return this, for method chaining
      */
     public ExceptionContext addValue(String label, Object value) {        
+        String key = label;
+        int i = 0;
+        while (contextValueMap.containsKey(key)) {
+            Object information = contextValueMap.get(key);
+            if ((value == null && information == null)
+                    || (value != null && value.equals(information)))
+                return this;
+            key = label + "[" + ++i +"]";
+        }
+        contextValueMap.put(key, value);
+        return this;
+    }
+
+    /**
+     * Replaces a contextual label-value pair of this context.
+     * <p>
+     * This label-value pair provides information useful for debugging. If the
+     * label does not yet exists, a simply add operation is performed.
+     * </p>
+     * 
+     * @param label  the label of the item to add, null not recommended
+     * @param value  the value of item to add, may be null
+     * @return this, for method chaining
+     */
+    public ExceptionContext replaceValue(String label, Object value) {        
         contextValueMap.put(label, value);
         return this;
     }

Modified: 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java
 (original)
+++ 
commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java
 Mon Mar 15 17:11:55 2010
@@ -33,7 +33,10 @@ public interface ExceptionContext {
     /**
      * Adds a contextual label-value pair into this context.
      * <p>
-     * This label-value pair provides information useful for debugging.
+     * This label-value pair provides information useful for debugging. If the
+     * provided label already exists, it depends on the implementation what
+     * happens with the new value. 
+     * </p>
      * 
      * @param label  the label of the item to add, null not recommended
      * @param value  the value of item to add, may be null
@@ -42,6 +45,20 @@ public interface ExceptionContext {
     public ExceptionContext addValue(String label, Object value);
 
     /**
+     * Replaces a contextual label-value pair of this context.
+     * <p>
+     * This label-value pair provides information useful for debugging. If the
+     * label does not exist yet, it depends on the implementation what happens
+     * with the provided value.
+     * </p>
+     * 
+     * @param label  the label of the item to add, null not recommended
+     * @param value  the value of item to add, may be null
+     * @return context itself to allow method chaining
+     */
+    public ExceptionContext replaceValue(String label, Object value);
+
+    /**
      * Retrieves a contextual data value associated with the label.
      * 
      * @param label  the label to get the contextual value for, may be null

Modified: 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java
 (original)
+++ 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java
 Mon Mar 15 17:11:55 2010
@@ -26,7 +26,7 @@ import org.apache.commons.lang3.StringUt
 /**
  * JUnit tests for ContextedException.
  * @author D. Ashmore
- *
+ * @author Apache Software Foundation
  */
 public class ContextedExceptionTest extends TestCase {
     
@@ -34,10 +34,6 @@ public class ContextedExceptionTest exte
     private static final String TEST_MESSAGE = "Test Message";
     private ContextedException contextedException;
 
-    public ContextedExceptionTest(String name) {
-        super(name);
-    }
-
     public void testContextedException() {
         contextedException = new ContextedException();
         String message = contextedException.getMessage();
@@ -88,8 +84,7 @@ public class ContextedExceptionTest exte
         .addValue("test1", null)
         .addValue("test2", "some value")
         .addValue("test Date", new Date())
-        .addValue("test Nbr", new Integer(5))
-        .addValue("test Poorly written obj", new ObjectWithFaultyToString());
+        .addValue("test Nbr", new Integer(5));
         
         String message = contextedException.getMessage();
         assertTrue(message.indexOf(TEST_MESSAGE)>=0);
@@ -97,27 +92,49 @@ public class ContextedExceptionTest exte
         assertTrue(message.indexOf("test2")>=0);
         assertTrue(message.indexOf("test Date")>=0);
         assertTrue(message.indexOf("test Nbr")>=0);
-        assertTrue(message.indexOf("test Poorly written obj")>=0);
         assertTrue(message.indexOf("some value")>=0);
         assertTrue(message.indexOf("5")>=0);
-        assertTrue(message.indexOf("Crap")>=0);
         
         assertTrue(contextedException.getValue("test1") == null);
         assertTrue(contextedException.getValue("test2").equals("some value"));
-        assertTrue(contextedException.getValue("crap") == null);
-        assertTrue(contextedException.getValue("test Poorly written obj") 
instanceof ObjectWithFaultyToString);
         
-        assertTrue(contextedException.getLabelSet().size() == 5);
+        assertTrue(contextedException.getLabelSet().size() == 4);
         assertTrue(contextedException.getLabelSet().contains("test1"));
         assertTrue(contextedException.getLabelSet().contains("test2"));
         assertTrue(contextedException.getLabelSet().contains("test Date"));
         assertTrue(contextedException.getLabelSet().contains("test Nbr"));
+
+        contextedException.addValue("test2", "different value");
+        assertTrue(contextedException.getLabelSet().size() == 5);
+        assertTrue(contextedException.getLabelSet().contains("test2"));
+        assertTrue(contextedException.getLabelSet().contains("test2[1]"));
+        
+        String contextMessage = 
contextedException.getFormattedExceptionMessage(null);
+        assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
+        assertTrue(contextedException.getMessage().endsWith(contextMessage));
+    }
+
+    public void testReplaceValue() {
+        contextedException = new ContextedException(new 
Exception(TEST_MESSAGE))
+        .addValue("test Poorly written obj", new ObjectWithFaultyToString());
+        
+        String message = contextedException.getMessage();
+        assertTrue(message.indexOf(TEST_MESSAGE)>=0);
+        assertTrue(message.indexOf("test Poorly written obj")>=0);
+        assertTrue(message.indexOf("Crap")>=0);
+        
+        assertTrue(contextedException.getValue("crap") == null);
+        assertTrue(contextedException.getValue("test Poorly written obj") 
instanceof ObjectWithFaultyToString);
+        
+        assertTrue(contextedException.getLabelSet().size() == 1);
         assertTrue(contextedException.getLabelSet().contains("test Poorly 
written obj"));
         
         assertTrue(!contextedException.getLabelSet().contains("crap"));
 
-        contextedException.addValue("test Poorly written obj", "replacement");
-        
+        contextedException.replaceValue("test Poorly written obj", 
"replacement");
+
+        assertTrue(contextedException.getLabelSet().size() == 1);
+
         String contextMessage = 
contextedException.getFormattedExceptionMessage(null);
         assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
         assertTrue(contextedException.getMessage().endsWith(contextMessage));
@@ -134,10 +151,6 @@ public class ContextedExceptionTest exte
         String message = contextedException.getMessage();
         assertTrue(message != null);
     }
-
-    public void testGetMessage() {
-        testAddValue();
-    }
     
     static class ObjectWithFaultyToString implements Serializable {
 

Modified: 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java
 (original)
+++ 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java
 Mon Mar 15 17:11:55 2010
@@ -26,6 +26,7 @@ import org.apache.commons.lang3.exceptio
 /**
  * JUnit tests for ContextedRuntimeException.
  * @author D. Ashmore
+ * @author Apache Software Foundation
  *
  */
 public class ContextedRuntimeExceptionTest extends TestCase {
@@ -34,10 +35,6 @@ public class ContextedRuntimeExceptionTe
     private static final String TEST_MESSAGE = "Test Message";
     private ContextedRuntimeException contextedRuntimeException;
 
-    public ContextedRuntimeExceptionTest(String name) {
-        super(name);
-    }
-
     public void testContextedException() {
         contextedRuntimeException = new ContextedRuntimeException();
         String message = contextedRuntimeException.getMessage();
@@ -88,8 +85,7 @@ public class ContextedRuntimeExceptionTe
         .addValue("test1", null)
         .addValue("test2", "some value")
         .addValue("test Date", new Date())
-        .addValue("test Nbr", new Integer(5))
-        .addValue("test Poorly written obj", new ObjectWithFaultyToString());
+        .addValue("test Nbr", new Integer(5));
         
         String message = contextedRuntimeException.getMessage();
         assertTrue(message.indexOf(TEST_MESSAGE)>=0);
@@ -97,27 +93,49 @@ public class ContextedRuntimeExceptionTe
         assertTrue(message.indexOf("test2")>=0);
         assertTrue(message.indexOf("test Date")>=0);
         assertTrue(message.indexOf("test Nbr")>=0);
-        assertTrue(message.indexOf("test Poorly written obj")>=0);
         assertTrue(message.indexOf("some value")>=0);
         assertTrue(message.indexOf("5")>=0);
-        assertTrue(message.indexOf("Crap")>=0);
         
         assertTrue(contextedRuntimeException.getValue("test1") == null);
         assertTrue(contextedRuntimeException.getValue("test2").equals("some 
value"));
-        assertTrue(contextedRuntimeException.getValue("crap") == null);
-        assertTrue(contextedRuntimeException.getValue("test Poorly written 
obj") instanceof ObjectWithFaultyToString);
         
-        assertTrue(contextedRuntimeException.getLabelSet().size() == 5);
+        assertTrue(contextedRuntimeException.getLabelSet().size() == 4);
         assertTrue(contextedRuntimeException.getLabelSet().contains("test1"));
         assertTrue(contextedRuntimeException.getLabelSet().contains("test2"));
         assertTrue(contextedRuntimeException.getLabelSet().contains("test 
Date"));
         assertTrue(contextedRuntimeException.getLabelSet().contains("test 
Nbr"));
+
+        contextedRuntimeException.addValue("test2", "different value");
+        assertTrue(contextedRuntimeException.getLabelSet().size() == 5);
+        assertTrue(contextedRuntimeException.getLabelSet().contains("test2"));
+        
assertTrue(contextedRuntimeException.getLabelSet().contains("test2[1]"));
+        
+        String contextMessage = 
contextedRuntimeException.getFormattedExceptionMessage(null);
+        assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
+        
assertTrue(contextedRuntimeException.getMessage().endsWith(contextMessage));
+    }
+
+    public void testReplaceValue() {
+        contextedRuntimeException = new ContextedRuntimeException(new 
Exception(TEST_MESSAGE))
+        .addValue("test Poorly written obj", new ObjectWithFaultyToString());
+        
+        String message = contextedRuntimeException.getMessage();
+        assertTrue(message.indexOf(TEST_MESSAGE)>=0);
+        assertTrue(message.indexOf("test Poorly written obj")>=0);
+        assertTrue(message.indexOf("Crap")>=0);
+        
+        assertTrue(contextedRuntimeException.getValue("crap") == null);
+        assertTrue(contextedRuntimeException.getValue("test Poorly written 
obj") instanceof ObjectWithFaultyToString);
+        
+        assertTrue(contextedRuntimeException.getLabelSet().size() == 1);
         assertTrue(contextedRuntimeException.getLabelSet().contains("test 
Poorly written obj"));
         
         assertTrue(!contextedRuntimeException.getLabelSet().contains("crap"));
 
-        contextedRuntimeException.addValue("test Poorly written obj", 
"replacement");
-        
+        contextedRuntimeException.replaceValue("test Poorly written obj", 
"replacement");
+
+        assertTrue(contextedRuntimeException.getLabelSet().size() == 1);
+
         String contextMessage = 
contextedRuntimeException.getFormattedExceptionMessage(null);
         assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
         
assertTrue(contextedRuntimeException.getMessage().endsWith(contextMessage));
@@ -134,10 +152,4 @@ public class ContextedRuntimeExceptionTe
         String message = contextedRuntimeException.getMessage();
         assertTrue(message != null);
     }
-
-    public void testGetMessage() {
-        testAddValue();
-    }
-    
-
 }

Modified: 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java?rev=923341&r1=923340&r2=923341&view=diff
==============================================================================
--- 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java
 (original)
+++ 
commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java
 Mon Mar 15 17:11:55 2010
@@ -23,7 +23,7 @@ import org.apache.commons.lang3.exceptio
 import junit.framework.TestCase;
 
 /**
- * JUnit tests for DefaultExceptionContext
+ * JUnit tests for DefaultExceptionContext.
  * @author D. Ashmore
  *
  */
@@ -46,21 +46,42 @@ public class DefaultExceptionContextTest
     }
     
     public void testAddValue() {
+        defaultExceptionContext.addValue("test2", "different value");
                 
         String message = 
defaultExceptionContext.getFormattedExceptionMessage("This is an error");
         assertTrue(message.indexOf("This is an error")>=0);
         assertTrue(message.indexOf("test1")>=0);
         assertTrue(message.indexOf("test2")>=0);
+        assertTrue(message.indexOf("test2[1]")>=0);
         assertTrue(message.indexOf("test Date")>=0);
         assertTrue(message.indexOf("test Nbr")>=0);
         assertTrue(message.indexOf("test Poorly written obj")>=0);
         assertTrue(message.indexOf("some value")>=0);
+        assertTrue(message.indexOf("different value")>=0);
         assertTrue(message.indexOf("5")>=0);
         assertTrue(message.indexOf("Crap")>=0);
-        
-        //contextedException.printStackTrace();
     }
     
+    public void testReplaceValue() {
+        defaultExceptionContext.replaceValue("test2", "different value");
+        defaultExceptionContext.replaceValue("test3", "3");
+                
+        String message = 
defaultExceptionContext.getFormattedExceptionMessage("This is an error");
+        assertTrue(message.indexOf("This is an error")>=0);
+        assertTrue(message.indexOf("test1")>=0);
+        assertTrue(message.indexOf("test2")>=0);
+        assertTrue(message.indexOf("test3")>=0);
+        assertTrue(message.indexOf("test Date")>=0);
+        assertTrue(message.indexOf("test Nbr")>=0);
+        assertTrue(message.indexOf("test Poorly written obj")>=0);
+        assertTrue(message.indexOf("different value")>=0);
+        assertTrue(message.indexOf("5")>=0);
+        assertTrue(message.indexOf("Crap")>=0);
+
+        assertTrue(message.indexOf("test2[1]")<0);
+        assertTrue(message.indexOf("some value")<0);
+}
+    
     public void testFormattedExceptionMessageNull() {
         defaultExceptionContext = new DefaultExceptionContext();
         defaultExceptionContext.getFormattedExceptionMessage(null);


Reply via email to