You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jo...@apache.org on 2009/08/09 19:46:13 UTC

svn commit: r802566 - in /commons/proper/lang/trunk/src: java/org/apache/commons/lang/exception/ test/org/apache/commons/lang/exception/

Author: joehni
Date: Sun Aug  9 17:46:13 2009
New Revision: 802566

URL: http://svn.apache.org/viewvc?rev=802566&view=rev
Log:
Add ExceptionContext package (LANG-497, contributed by Derek Ashmore).

Added:
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java   (with props)
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java   (with props)
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java   (with props)
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java   (with props)
    commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java   (with props)
    commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java   (with props)
    commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java   (with props)
Modified:
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
    commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/package.html

Added: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java (added)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java Sun Aug  9 17:46:13 2009
@@ -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);
+    }
+}

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Added: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java (added)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java Sun Aug  9 17:46:13 2009
@@ -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);
+    }
+}

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ContextedRuntimeException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Added: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java (added)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java Sun Aug  9 17:46:13 2009
@@ -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();
+    }
+    
+}
\ No newline at end of file

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/DefaultExceptionContext.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Added: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java (added)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java Sun Aug  9 17:46:13 2009
@@ -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);
+
+}
\ No newline at end of file

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionContext.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java?rev=802566&r1=802565&r2=802566&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java (original)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java Sun Aug  9 17:46:13 2009
@@ -18,6 +18,7 @@
 
 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.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 @@
      */
     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 {

Modified: commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/package.html
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/package.html?rev=802566&r1=802565&r2=802566&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/package.html (original)
+++ commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/package.html Sun Aug  9 17:46:13 2009
@@ -16,10 +16,10 @@
 -->
 <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

Added: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java (added)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java Sun Aug  9 17:46:13 2009
@@ -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");
+        }
+        
+    }
+
+}

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedExceptionTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Added: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java (added)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java Sun Aug  9 17:46:13 2009
@@ -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();
+    }
+    
+
+}

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ContextedRuntimeExceptionTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision

Added: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java?rev=802566&view=auto
==============================================================================
--- commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java (added)
+++ commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java Sun Aug  9 17:46:13 2009
@@ -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"));
+    }
+
+}

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/DefaultExceptionContextTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id HeadURL Revision