Fix DefaultExceptionContext.addValue that overwrites information in a recursive situation (LANG-605). Allow explicit replacement of a label with the new replaceValue methods.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@923341 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4d7a616cca
commit
022d08cfd3
|
@ -139,9 +139,11 @@ public class ContextedException extends Exception implements ExceptionContext {
|
|||
/**
|
||||
* 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
|
||||
|
@ -152,6 +154,24 @@ public class ContextedException extends Exception implements ExceptionContext {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -64,7 +64,6 @@ import java.util.Set;
|
|||
* @see ContextedException
|
||||
* @author Apache Software Foundation
|
||||
* @author D. Ashmore
|
||||
* @author Jörg Schaible
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ContextedRuntimeException extends RuntimeException implements ExceptionContext {
|
||||
|
@ -140,9 +139,11 @@ public class ContextedRuntimeException extends RuntimeException implements Excep
|
|||
/**
|
||||
* 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 +154,24 @@ public class ContextedRuntimeException extends RuntimeException implements Excep
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -43,13 +43,41 @@ class DefaultExceptionContext implements ExceptionContext, Serializable {
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -41,6 +44,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.
|
||||
*
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
/**
|
||||
* JUnit tests for ContextedException.
|
||||
* @author D. Ashmore
|
||||
*
|
||||
* @author Apache Software Foundation
|
||||
*/
|
||||
public class ContextedExceptionTest extends TestCase {
|
||||
|
||||
|
@ -34,10 +34,6 @@ public class ContextedExceptionTest extends TestCase {
|
|||
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 extends TestCase {
|
|||
.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,26 +92,48 @@ public class ContextedExceptionTest extends TestCase {
|
|||
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);
|
||||
|
@ -135,10 +152,6 @@ public class ContextedExceptionTest extends TestCase {
|
|||
assertTrue(message != null);
|
||||
}
|
||||
|
||||
public void testGetMessage() {
|
||||
testAddValue();
|
||||
}
|
||||
|
||||
static class ObjectWithFaultyToString implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3495843995332310458L;
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.apache.commons.lang3.exception.ContextedExceptionTest.ObjectWithFault
|
|||
/**
|
||||
* JUnit tests for ContextedRuntimeException.
|
||||
* @author D. Ashmore
|
||||
* @author Apache Software Foundation
|
||||
*
|
||||
*/
|
||||
public class ContextedRuntimeExceptionTest extends TestCase {
|
||||
|
@ -34,10 +35,6 @@ public class ContextedRuntimeExceptionTest extends TestCase {
|
|||
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 ContextedRuntimeExceptionTest extends TestCase {
|
|||
.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,26 +93,48 @@ public class ContextedRuntimeExceptionTest extends TestCase {
|
|||
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);
|
||||
|
@ -134,10 +152,4 @@ public class ContextedRuntimeExceptionTest extends TestCase {
|
|||
String message = contextedRuntimeException.getMessage();
|
||||
assertTrue(message != null);
|
||||
}
|
||||
|
||||
public void testGetMessage() {
|
||||
testAddValue();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.commons.lang3.exception.ContextedExceptionTest.ObjectWithFault
|
|||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* JUnit tests for DefaultExceptionContext
|
||||
* JUnit tests for DefaultExceptionContext.
|
||||
* @author D. Ashmore
|
||||
*
|
||||
*/
|
||||
|
@ -46,20 +46,41 @@ public class DefaultExceptionContextTest extends TestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
//contextedException.printStackTrace();
|
||||
}
|
||||
assertTrue(message.indexOf("test2[1]")<0);
|
||||
assertTrue(message.indexOf("some value")<0);
|
||||
}
|
||||
|
||||
public void testFormattedExceptionMessageNull() {
|
||||
defaultExceptionContext = new DefaultExceptionContext();
|
||||
|
|
Loading…
Reference in New Issue