Add ExceptionContext package (LANG-497, contributed by Derek Ashmore).

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@802566 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Joerg Schaible 2009-08-09 17:46:13 +00:00
parent 2e165be127
commit ad922624da
9 changed files with 930 additions and 4 deletions

View File

@ -0,0 +1,184 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.io.Serializable;
import java.util.Set;
/**
* Provides an easier and safer way for developers to provide context when
* generating checked exceptions. Often, additional information, besides what's
* embedded in the exception cause, is needed for developers to debug and correct
* a bug. Often, this additional information can reduce the time it takes
* to replicate and fix a bug.
*
* <p>ContextedException is easier as developers don't need to be concerned
* with formatting the exception message to include additional information
* with the exception. Additional information is automatically included
* in the message and printed stack trace. This often thins out exception
* handling code.</p>
*
* <p>ContextedException is safer as the additional code needed to embed additional
* information in a normal exception tends to be tested less and is more vulnerable
* to errors such as null pointer exceptions.</p>
*
* <p>An unchecked version of this exception is provided by ContextedRuntimeException.</p>
*
* <p>To use this class write code as follows:</p>
*
* <pre>
* try {
*
* ...
*
* } catch (Throwable e) {
* throw new ContextedException("Error posting account transaction", e)
* .addLabeledValue("accountNumber", accountNumber)
* .addLabeledValue("amountPosted", amountPosted)
* .addLabeledValue("previousBalance", previousBalance)
* }
* }
* </pre>
*
* <p>The output in a printStacktrace() (which often is written to a log) would look something like the following:
* <pre>
* org.apache.commons.lang.exception.ContextedException: java.lang.Exception: Error posting account transaction
* Exception Context:
* [accountNumber=null]
* [amountPosted=100.00]
* [previousBalance=-2.17]
*
* ---------------------------------
* at org.apache.commons.lang.exception.ContextedExceptionTest.testAddLabeledValue(ContextedExceptionTest.java:88)
* ..... (rest of trace)
* </pre>
*
* @see ContextedRuntimeException
* @author D. Ashmore
* @since 3.0
*
*/
public class ContextedException extends Exception implements ExceptionContext {
private static final long serialVersionUID = 8940917952810290164L;
private ExceptionContext exceptionContext = new DefaultExceptionContext();
/**
* Instantiates ContextedException without message or cause.
* <p>DefaultExceptionContext used to store and format context information.</p>
*/
public ContextedException() {
}
/**
* Instantiates ContextedException with message, but without cause.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param message The exception message
*/
public ContextedException(String message) {
super(message);
}
/**
* Instantiates ContextedException with cause, but without message.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param cause Exception creating need for ContextedException
*/
public ContextedException(Throwable cause) {
super(cause);
}
/**
* Instantiates ContextedException with cause and message.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param message The exception message
* @param cause Exception creating need for ContextedException
*/
public ContextedException(String message, Throwable cause) {
super(message, cause);
}
/**
* Instantiates ContextedException with cause, message, and ExceptionContext.
* @param message The exception message
* @param cause Exception creating need for ContextedException
* @param context Context used to store additional information
* @since 3.0
*/
public ContextedException(String message, Throwable cause, ExceptionContext context) {
super(message, cause);
if (context != null) {
this.exceptionContext = context;
}
}
/**
* 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.
*
* <p>Note: If the value provided isn't Serializable, one solution would be
* to provide its toString() if it has a meaningful implementation or
* individual properties of the value object instead.</p>
* @param label a textual label associated with information
* @param value information needed to understand exception. May be <code>null</code>.
* @return this
* @since 3.0
*/
public ContextedException addLabeledValue(String label, Serializable value) {
this.exceptionContext.addLabeledValue(label, value);
return this;
}
/**
* Convenience method to retrieve a value from the underlying ExceptionContext.
* @param label a textual label associated with information
* @return value information needed to understand exception. May be <code>null</code>.
* @since 3.0
*/
public Serializable getLabeledValue(String label) {
return this.exceptionContext.getLabeledValue(label);
}
/**
* Convenience method to retrieve currently defined labels from the underlying ExceptionContext.
* @return labelSet
* @since 3.0
*/
public Set<String> getLabelSet() {
return this.exceptionContext.getLabelSet();
}
/**
* Provides message pertaining to exception.
* @see java.lang.Throwable#getMessage()
* @return message
* @since 3.0
*/
@Override
public String getMessage(){
return getFormattedExceptionMessage(super.getMessage());
}
/**
* {@inheritDoc}
*/
public String getFormattedExceptionMessage(String baseMessage) {
return this.exceptionContext.getFormattedExceptionMessage(baseMessage);
}
}

View File

@ -0,0 +1,138 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.io.Serializable;
import java.util.Set;
/**
* Provides an unchecked version of ContextedException
* @see ContextedException
* @author D. Ashmore
* @author J&ouml;rg Schaible
* @since 3.0
*
*/
public class ContextedRuntimeException extends RuntimeException implements ExceptionContext {
private static final long serialVersionUID = 1459691936045811817L;
private ExceptionContext exceptionContext = new DefaultExceptionContext();
/**
* Instantiates ContextedRuntimeException without message or cause.
* <p>DefaultExceptionContext used to store and format context information.</p>
*
*/
public ContextedRuntimeException() {
}
/**
* Instantiates ContextedRuntimeException with message, but without cause.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param message The exception message
* @since 3.0
*/
public ContextedRuntimeException(String message) {
super(message);
}
/**
* Instantiates ContextedRuntimeException with cause, but without message.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param cause Exception creating need for ContextedRuntimeException
* @since 3.0
*/
public ContextedRuntimeException(Throwable cause) {
super(cause);
}
/**
* Instantiates ContextedRuntimeException with cause and message.
* <p>DefaultExceptionContext used to store and format context information.</p>
* @param message The exception message
* @param cause Exception creating need for ContextedException
* @since 3.0
*/
public ContextedRuntimeException(String message, Throwable cause) {
this(message, cause, cause instanceof ExceptionContext ? (ExceptionContext)cause : null);
}
/**
* Instantiates ContextedRuntimeException with cause, message, and ExceptionContext.
* @param message The exception message
* @param cause Exception creating need for ContextedRuntimeException
* @param context Context used to store additional information
* @since 3.0
*/
public ContextedRuntimeException(String message, Throwable cause, ExceptionContext context) {
super(message, cause);
if (context != null) {
this.exceptionContext = context;
}
}
/**
* Adds information helpful to a developer in diagnosing and correcting
* the problem.
* @see ContextedException#addLabeledValue(String, Serializable)
* @param label a textual label associated with information
* @param value information needed to understand exception. May be <code>null</code>.
* @return this
* @since 3.0
*/
public ContextedRuntimeException addLabeledValue(String label, Serializable value) {
this.exceptionContext.addLabeledValue(label, value);
return this;
}
/**
* Convenience method to retrieve a value from the underlying ExceptionContext.
* @param label a textual label associated with information
* @return value information needed to understand exception. May be <code>null</code>.
* @since 3.0
*/
public Serializable getLabeledValue(String label) {
return this.exceptionContext.getLabeledValue(label);
}
/**
* Convenience method to retrieve currently defined labels from the underlying ExceptionContext.
* @return labelSet
* @since 3.0
*/
public Set<String> getLabelSet() {
return this.exceptionContext.getLabelSet();
}
/**
* Provides message pertaining to exception.
* @see java.lang.Throwable#getMessage()
* @return message
* @since 3.0
*/
@Override
public String getMessage(){
return getFormattedExceptionMessage(super.getMessage());
}
/**
* {@inheritDoc}
*/
public String getFormattedExceptionMessage(String baseMessage) {
return this.exceptionContext.getFormattedExceptionMessage(baseMessage);
}
}

View File

@ -0,0 +1,129 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.SystemUtils;
/**
* Provides context feature for exceptions. Used by both checked and unchecked version of the contexted exceptions.
* @see ContextedRuntimeException
* @author D. Ashmore
* @since 3.0
*/
public class DefaultExceptionContext implements ExceptionContext {
private static final long serialVersionUID = 293747957535772807L;
/*
* This value list could really be obtained from the Map, however, some
* callers want to control the order of the list as it appears in the
* Message. The list allows that. name/value pairs will appear in
* the order that they're provided. D. Ashmore
*/
private List<String> contextKeyList = new ArrayList<String>();
private Map<String, Serializable> contextValueMap = new HashMap<String, Serializable>();
/**
* Adds information helpful to a developer in diagnosing and correcting
* the problem.
* @see ContextedException#addLabeledValue(String, Serializable)
* @param label a textual label associated with information
* @param value information needed to understand exception. May be null.
* @return this
* @since 3.0
*/
public ExceptionContext addLabeledValue(String label, Serializable value) {
this.contextKeyList.add(label);
this.contextValueMap.put(label, value);
return this;
}
/**
* Retrieves the value for a given label.
* @param label a textual label associated with information
* @return value information needed to understand exception. May be null.
* @since 3.0
*/
public Serializable getLabeledValue(String label) {
return this.contextValueMap.get(label);
}
/**
* Retrieves currently defined labels.
* @return labelSet
* @since 3.0
*/
public Set<String> getLabelSet() {
return this.contextValueMap.keySet();
}
/**
* Centralized message logic for both checked and unchecked version of
* context exceptions
* @param baseMessage message retained by super class
* @return message -- exception message
* @since 3.0
*/
public String getFormattedExceptionMessage(String baseMessage){
StringBuffer buffer = new StringBuffer(256);
if (baseMessage != null) {
buffer.append(baseMessage);
}
if (contextKeyList.size() > 0) {
buffer.append(SystemUtils.LINE_SEPARATOR);
buffer.append("Exception Context:");
buffer.append(SystemUtils.LINE_SEPARATOR);
buffer.append("\t");
Object value;
String valueStr;
for (String label: this.contextKeyList) {
buffer.append("[");
buffer.append(label);
buffer.append("=");
value = this.contextValueMap.get(label);
if (value == null) {
buffer.append("null");
}
else {
try {valueStr = value.toString();}
catch (Throwable t) {
valueStr = "Excepted on toString(): " +
ExceptionUtils.getStackTrace(t);
}
buffer.append(valueStr);
}
buffer.append("]");
buffer.append(SystemUtils.LINE_SEPARATOR);
buffer.append("\t");
}
buffer.append(SystemUtils.LINE_SEPARATOR);
buffer.append("\t---------------------------------");
}
return buffer.toString();
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.io.Serializable;
import java.util.Collections;
import java.util.Set;
/**
* Provides context information for exceptions. It is available as separate interface to allow
* it usage independently from the {@link ContextedException} and
* {@link ContextedRuntimeException}.
*
* @see ContextedException
* @see ContextedRuntimeException
* @author D. Ashmore
* @since 3.0
*/
public interface ExceptionContext extends Serializable {
/**
* Adds a context item along with a label.
* @param label label of item
* @param value value of item
* @return context itself to allow method chaining
* @since 3.0
*/
public ExceptionContext addLabeledValue(String label, Serializable value);
/**
* Provides context information associated with the given label.
* @param label label of item
* @return value value associated with label
* @since 3.0
*/
public Serializable getLabeledValue(String label);
/**
* Provides a set of labels that are currently in the context.
* @return labelSet labels currently used by the context
* @since 3.0
*/
public Set<String> getLabelSet();
/**
* Implementors provide the given base message with context label/value item
* information appended.
* @param baseMessage exception message <b>without</b> context information appended
* @return formattedMessage exception message <b>with</b> context information appended
* @since 3.0
*/
public String getFormattedExceptionMessage(String baseMessage);
}

View File

@ -18,6 +18,7 @@ package org.apache.commons.lang.exception;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@ -25,7 +26,9 @@ import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import net.jcip.annotations.GuardedBy;
@ -91,6 +94,31 @@ public class ExceptionUtils {
*/
private static final Method THROWABLE_INITCAUSE_METHOD;
/**
* An empty {@link ExceptionContext}.
* @since 3.0
*/
public static final ExceptionContext EMPTY_CONTEXT = new ExceptionContext() {
private static final long serialVersionUID = 1L;
public ExceptionContext addLabeledValue(String label, Serializable value) {
throw new UnsupportedOperationException();
}
public Serializable getLabeledValue(String label) {
return null;
}
public Set<String> getLabelSet() {
return Collections.<String>emptySet();
}
public String getFormattedExceptionMessage(String baseMessage) {
return baseMessage;
}
};
static {
Method causeMethod;
try {

View File

@ -16,10 +16,10 @@ limitations under the License.
-->
<html>
<body>
Provides JDK 1.4 style Nested Exception functionality for those on prior Java
versions.
<p>Includes a static utility to create version independent Nested
Exception which can handle JDK 1.4 Exceptions as well as others. </p>
Provides functionality for Exceptions.
<p>Contains the concept of an exception with context i.e. such an exception
will contain a map with keys and values. This provides an easy way to pass valuable
state information at exception time in useful form to a calling process.</p>
<p>Lastly, {@link org.apache.commons.lang.exception.ExceptionUtils}
also contains <code>Throwable</code> manipulation and examination routines.</p>
@since 1.0

View File

@ -0,0 +1,151 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.io.Serializable;
import java.util.Date;
import junit.framework.TestCase;
import org.apache.commons.lang.StringUtils;
/**
* JUnit tests for ContextedException.
* @author D. Ashmore
*
*/
public class ContextedExceptionTest extends TestCase {
private static final String TEST_MESSAGE_2 = "This is monotonous";
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();
String trace = ExceptionUtils.getStackTrace(contextedException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(StringUtils.isEmpty(message));
}
public void testContextedExceptionString() {
contextedException = new ContextedException(TEST_MESSAGE);
assertEquals(TEST_MESSAGE, contextedException.getMessage());
String trace = ExceptionUtils.getStackTrace(contextedException);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
}
public void testContextedExceptionThrowable() {
contextedException = new ContextedException(new Exception(TEST_MESSAGE));
String message = contextedException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(message.indexOf(TEST_MESSAGE)>=0);
}
public void testContextedExceptionStringThrowable() {
contextedException = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE));
String message = contextedException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(trace.indexOf(TEST_MESSAGE_2)>=0);
assertTrue(message.indexOf(TEST_MESSAGE_2)>=0);
}
public void testContextedExceptionStringThrowableContext() {
contextedException = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), new DefaultExceptionContext());
String message = contextedException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(trace.indexOf(TEST_MESSAGE_2)>=0);
assertTrue(message.indexOf(TEST_MESSAGE_2)>=0);
}
public void testAddLabeledValue() {
contextedException = new ContextedException(new Exception(TEST_MESSAGE))
.addLabeledValue("test1", null)
.addLabeledValue("test2", "some value")
.addLabeledValue("test Date", new Date())
.addLabeledValue("test Nbr", new Integer(5))
.addLabeledValue("test Poorly written obj", new ObjectWithFaultyToString());
String message = contextedException.getMessage();
assertTrue(message.indexOf(TEST_MESSAGE)>=0);
assertTrue(message.indexOf("test1")>=0);
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);
String contextMessage = contextedException.getFormattedExceptionMessage("");
assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
assertTrue(message.contains(contextMessage));
assertTrue(contextedException.getLabeledValue("test1") == null);
assertTrue(contextedException.getLabeledValue("test2").equals("some value"));
assertTrue(contextedException.getLabeledValue("crap") == null);
assertTrue(contextedException.getLabeledValue("test Poorly written obj") instanceof ObjectWithFaultyToString);
assertTrue(contextedException.getLabelSet().size() == 5);
assertTrue(contextedException.getLabelSet().contains("test1"));
assertTrue(contextedException.getLabelSet().contains("test2"));
assertTrue(contextedException.getLabelSet().contains("test Date"));
assertTrue(contextedException.getLabelSet().contains("test Nbr"));
assertTrue(contextedException.getLabelSet().contains("test Poorly written obj"));
assertTrue(!contextedException.getLabelSet().contains("crap"));
}
public void testNullExceptionPassing() {
contextedException = new ContextedException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), null)
.addLabeledValue("test1", null)
.addLabeledValue("test2", "some value")
.addLabeledValue("test Date", new Date())
.addLabeledValue("test Nbr", new Integer(5))
.addLabeledValue("test Poorly written obj", new ObjectWithFaultyToString());
String message = contextedException.getMessage();
assertTrue(message != null);
}
public void testGetMessage() {
testAddLabeledValue();
}
static class ObjectWithFaultyToString implements Serializable {
private static final long serialVersionUID = 3495843995332310458L;
@Override
public String toString() {
throw new RuntimeException("Crap");
}
}
}

View File

@ -0,0 +1,141 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.util.Date;
import junit.framework.TestCase;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ContextedExceptionTest.ObjectWithFaultyToString;
/**
* JUnit tests for ContextedRuntimeException.
* @author D. Ashmore
*
*/
public class ContextedRuntimeExceptionTest extends TestCase {
private static final String TEST_MESSAGE_2 = "This is monotonous";
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();
String trace = ExceptionUtils.getStackTrace(contextedRuntimeException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(StringUtils.isEmpty(message));
}
public void testContextedExceptionString() {
contextedRuntimeException = new ContextedRuntimeException(TEST_MESSAGE);
assertEquals(TEST_MESSAGE, contextedRuntimeException.getMessage());
String trace = ExceptionUtils.getStackTrace(contextedRuntimeException);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
}
public void testContextedExceptionThrowable() {
contextedRuntimeException = new ContextedRuntimeException(new Exception(TEST_MESSAGE));
String message = contextedRuntimeException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedRuntimeException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(message.indexOf(TEST_MESSAGE)>=0);
}
public void testContextedExceptionStringThrowable() {
contextedRuntimeException = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE));
String message = contextedRuntimeException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedRuntimeException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(trace.indexOf(TEST_MESSAGE_2)>=0);
assertTrue(message.indexOf(TEST_MESSAGE_2)>=0);
}
public void testContextedExceptionStringThrowableContext() {
contextedRuntimeException = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), new DefaultExceptionContext());
String message = contextedRuntimeException.getMessage();
String trace = ExceptionUtils.getStackTrace(contextedRuntimeException);
assertTrue(trace.indexOf("ContextedException")>=0);
assertTrue(trace.indexOf(TEST_MESSAGE)>=0);
assertTrue(trace.indexOf(TEST_MESSAGE_2)>=0);
assertTrue(message.indexOf(TEST_MESSAGE_2)>=0);
}
public void testAddLabeledValue() {
contextedRuntimeException = new ContextedRuntimeException(new Exception(TEST_MESSAGE))
.addLabeledValue("test1", null)
.addLabeledValue("test2", "some value")
.addLabeledValue("test Date", new Date())
.addLabeledValue("test Nbr", new Integer(5))
.addLabeledValue("test Poorly written obj", new ObjectWithFaultyToString());
String message = contextedRuntimeException.getMessage();
assertTrue(message.indexOf(TEST_MESSAGE)>=0);
assertTrue(message.indexOf("test1")>=0);
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);
String contextMessage = contextedRuntimeException.getFormattedExceptionMessage("");
assertTrue(contextMessage.indexOf(TEST_MESSAGE) == -1);
assertTrue(message.contains(contextMessage));
assertTrue(contextedRuntimeException.getLabeledValue("test1") == null);
assertTrue(contextedRuntimeException.getLabeledValue("test2").equals("some value"));
assertTrue(contextedRuntimeException.getLabeledValue("crap") == null);
assertTrue(contextedRuntimeException.getLabeledValue("test Poorly written obj") instanceof ObjectWithFaultyToString);
assertTrue(contextedRuntimeException.getLabelSet().size() == 5);
assertTrue(contextedRuntimeException.getLabelSet().contains("test1"));
assertTrue(contextedRuntimeException.getLabelSet().contains("test2"));
assertTrue(contextedRuntimeException.getLabelSet().contains("test Date"));
assertTrue(contextedRuntimeException.getLabelSet().contains("test Nbr"));
assertTrue(contextedRuntimeException.getLabelSet().contains("test Poorly written obj"));
assertTrue(!contextedRuntimeException.getLabelSet().contains("crap"));
}
public void testNullExceptionPassing() {
contextedRuntimeException = new ContextedRuntimeException(TEST_MESSAGE_2, new Exception(TEST_MESSAGE), null)
.addLabeledValue("test1", null)
.addLabeledValue("test2", "some value")
.addLabeledValue("test Date", new Date())
.addLabeledValue("test Nbr", new Integer(5))
.addLabeledValue("test Poorly written obj", new ObjectWithFaultyToString());
String message = contextedRuntimeException.getMessage();
assertTrue(message != null);
}
public void testGetMessage() {
testAddLabeledValue();
}
}

View File

@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang.exception;
import java.util.Date;
import org.apache.commons.lang.exception.ContextedExceptionTest.ObjectWithFaultyToString;
import junit.framework.TestCase;
/**
* JUnit tests for DefaultExceptionContext
* @author D. Ashmore
*
*/
public class DefaultExceptionContextTest extends TestCase {
private ExceptionContext defaultExceptionContext;
public DefaultExceptionContextTest(String name) {
super(name);
}
public void setUp() {
defaultExceptionContext = new DefaultExceptionContext()
.addLabeledValue("test1", null)
.addLabeledValue("test2", "some value")
.addLabeledValue("test Date", new Date())
.addLabeledValue("test Nbr", new Integer(5))
.addLabeledValue("test Poorly written obj", new ObjectWithFaultyToString());
}
public void testAddLabeledValue() {
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("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);
//contextedException.printStackTrace();
}
public void testFormattedExceptionMessageNull() {
defaultExceptionContext = new DefaultExceptionContext();
defaultExceptionContext.getFormattedExceptionMessage(null);
}
public void testGetLabeledValue() {
assertTrue(defaultExceptionContext.getLabeledValue("test1") == null);
assertTrue(defaultExceptionContext.getLabeledValue("test2").equals("some value"));
assertTrue(defaultExceptionContext.getLabeledValue("crap") == null);
assertTrue(defaultExceptionContext.getLabeledValue("test Poorly written obj") instanceof ObjectWithFaultyToString);
}
public void testGetLabelSet() {
assertTrue(defaultExceptionContext.getLabelSet().size() == 5);
assertTrue(defaultExceptionContext.getLabelSet().contains("test1"));
assertTrue(defaultExceptionContext.getLabelSet().contains("test2"));
assertTrue(defaultExceptionContext.getLabelSet().contains("test Date"));
assertTrue(defaultExceptionContext.getLabelSet().contains("test Nbr"));
assertTrue(defaultExceptionContext.getLabelSet().contains("test Poorly written obj"));
assertTrue(!defaultExceptionContext.getLabelSet().contains("crap"));
}
}