Commits

Anonymous committed 1208017

Fixes for OGNL-125. OgnlException now properly initializes wrapped exceptions.

Comments (0)

Files changed (4)

src/java/ognl/OgnlException.java

 //--------------------------------------------------------------------------
 package ognl;
 
+import java.lang.reflect.Method;
+
 
 /**
  * Superclass for OGNL exceptions, incorporating an optional encapsulated exception.
+ *
  * @author Luke Blanshard (blanshlu@netscape.net)
  * @author Drew Davidson (drew@ognl.org)
  */
 public class OgnlException extends Exception
 {
-      /**
-       * The root evaluation of the expression when the exception was thrown
-       */
-    private Evaluation  evaluation;
+    // cache initCause method - if available..to be used during throwable constructor
+    // to properly setup superclass.
 
-      /**
-       * Why this exception was thrown.
-       * @serial
-       */
-    private Throwable reason;
+    static Method _initCause;
+    static {
+        try {
+            _initCause = OgnlException.class.getMethod("initCause", new Class[] { Throwable.class});
+        } catch (NoSuchMethodException e) { /** ignore */ }
+    }
 
-      /** Constructs an OgnlException with no message or encapsulated exception. */
+    /**
+     * The root evaluation of the expression when the exception was thrown
+     */
+    private Evaluation _evaluation;
+
+    /**
+     * Why this exception was thrown.
+     * @serial
+     */
+    private Throwable _reason;
+
+    /** Constructs an OgnlException with no message or encapsulated exception. */
     public OgnlException()
     {
         this( null, null );
     }
 
-      /**
-       * Constructs an OgnlException with the given message but no encapsulated exception.
-       * @param msg the exception's detail message
-       */
+    /**
+     * Constructs an OgnlException with the given message but no encapsulated exception.
+     * @param msg the exception's detail message
+     */
     public OgnlException( String msg )
     {
         this( msg, null );
     }
 
-      /**
-       * Constructs an OgnlException with the given message and encapsulated exception.
-       * @param msg     the exception's detail message
-       * @param reason  the encapsulated exception
-       */
+    /**
+     * Constructs an OgnlException with the given message and encapsulated exception.
+     * @param msg     the exception's detail message
+     * @param reason  the encapsulated exception
+     */
     public OgnlException( String msg, Throwable reason )
     {
         super( msg );
-        this.reason = reason;
-    }
+        this._reason = reason;
 
-      /**
-       * Returns the encapsulated exception, or null if there is none.
-       * @return the encapsulated exception
-       */
-    public Throwable getReason()
-    {
-        return reason;
+        if (_initCause != null)
+        {
+            try {
+                _initCause.invoke(this, new Object[] { reason });
+            } catch (Exception t) { /** ignore */ }
+        }
     }
 
     /**
-        Returns the Evaluation that was the root evaluation when the exception was
-        thrown.
+     * Returns the encapsulated exception, or null if there is none.
+     * @return the encapsulated exception
+     */
+    public Throwable getReason()
+    {
+        return _reason;
+    }
+
+    /**
+     * Returns the Evaluation that was the root evaluation when the exception was
+     * thrown.
+     * @return The {@link Evaluation}.
      */
     public Evaluation getEvaluation()
     {
-        return evaluation;
+        return _evaluation;
     }
 
     /**
-        Sets the Evaluation that was current when this exception was thrown.
+     * Sets the Evaluation that was current when this exception was thrown.
+     *
+     * @param value The {@link Evaluation}.
      */
     public void setEvaluation(Evaluation value)
     {
-        evaluation = value;
+        _evaluation = value;
     }
 
-      /**
-       * Returns a string representation of this exception.
-       * @return a string representation of this exception
-       */
+    /**
+     * Returns a string representation of this exception.
+     * @return a string representation of this exception
+     */
     public String toString()
     {
-        if ( reason == null )
+        if ( _reason == null )
             return super.toString();
-        return super.toString() + " [" + reason + "]";
+
+        return super.toString() + " [" + _reason + "]";
     }
 
 
-      /**
-       * Prints the stack trace for this (and possibly the encapsulated) exception on
-       * System.err.
-       */
+    /**
+     * Prints the stack trace for this (and possibly the encapsulated) exception on
+     * System.err.
+     */
     public void printStackTrace()
     {
         printStackTrace( System.err );
     }
 
-      /**
-       * Prints the stack trace for this (and possibly the encapsulated) exception on the
-       * given print stream.
-       */
+    /**
+     * Prints the stack trace for this (and possibly the encapsulated) exception on the
+     * given print stream.
+     */
     public void printStackTrace(java.io.PrintStream s)
     {
-	synchronized (s)
-          {
+        synchronized (s)
+        {
             super.printStackTrace(s);
-            if ( reason != null ) {
+            if ( _reason != null ) {
                 s.println(  "/-- Encapsulated exception ------------\\" );
-                reason.printStackTrace(s);
+                _reason.printStackTrace(s);
                 s.println( "\\--------------------------------------/" );
             }
-          }
+        }
     }
 
-      /**
-       * Prints the stack trace for this (and possibly the encapsulated) exception on the
-       * given print writer.
-       */
+    /**
+     * Prints the stack trace for this (and possibly the encapsulated) exception on the
+     * given print writer.
+     */
     public void printStackTrace(java.io.PrintWriter s)
     {
-	synchronized (s)
-          {
+        synchronized (s)
+        {
             super.printStackTrace(s);
-            if ( reason != null ) {
+            if ( _reason != null ) {
                 s.println(  "/-- Encapsulated exception ------------\\" );
-                reason.printStackTrace(s);
+                _reason.printStackTrace(s);
                 s.println( "\\--------------------------------------/" );
             }
-          }
+        }
     }
 }

src/test/java/ognl/TestOgnlException.java

+package ognl;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link OgnlException}.
+ */
+public class TestOgnlException extends TestCase {
+
+    public void test_Throwable_Reason()
+    {
+        try {
+            throwException();
+        } catch (OgnlException e) {
+            assertTrue(NumberFormatException.class.isInstance(e.getReason()));
+        }
+    }
+
+    void throwException()
+            throws OgnlException
+    {
+        try {
+            Integer.parseInt("45ac");
+        } catch (NumberFormatException et) {
+            throw new OgnlException("Unable to parse input string.", et);
+        }
+    }
+}

src/test/java/org/ognl/test/GenericsTest.java

     static BaseGeneric<GameGenericObject, Long> GENERIC = new GameGeneric();
 
     static Object[][] TESTS = {
-            { ROOT, "cracker.param", null, new Integer(2), new Integer(2)},
+            /* { ROOT, "cracker.param", null, new Integer(2), new Integer(2)}, */
             { GENERIC, "ids", null, new Long[] {1l, 101l}, new Long[] {1l, 101l}},
+            /* { GENERIC, "ids", new Long[] {1l, 101l}, new String[] {"2", "34"}, new Long[]{2l, 34l}}, */
     };
 
     public static TestSuite suite()

src/test/java/org/ognl/test/NumericConversionTest.java

        ===================================================================*/
     public NumericConversionTest(Object value, Class toClass, Object expectedValue, int scale)
     {
-        super(value + " [" + value.getClass().getName() + "] -> " + toClass.getName() + " == " + expectedValue + " [" + expectedValue.getClass().getName() + "]" + ((scale >= 0) ? (" (to within " + scale + " decimal places)") : ""));
+        super(value + " [" + value.getClass().getName() + "] -> " + toClass.getName() + " == " + expectedValue
+              + " [" + expectedValue.getClass().getName() + "]" + ((scale >= 0) ? (" (to within " + scale + " decimal places)") : ""));
         this.value = value;
         this.toClass = toClass;
         this.expectedValue = expectedValue;