You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@axis.apache.org by ba...@apache.org on 2011/02/27 15:11:00 UTC

svn commit: r1075057 - in /axis/axis2/java/core/trunk/modules/jaxws: src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java

Author: barrettj
Date: Sun Feb 27 14:11:00 2011
New Revision: 1075057

URL: http://svn.apache.org/viewvc?rev=1075057&view=rev
Log:
Prevent index out of bounds exception, or any exception, from attempting to log.  Add TDD/UT for same.

Added:
    axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java
Modified:
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java?rev=1075057&r1=1075056&r2=1075057&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/WebServiceExceptionLogger.java Sun Feb 27 14:11:00 2011
@@ -52,68 +52,80 @@ public class WebServiceExceptionLogger {
                            Class serviceImplClass,
                            Object serviceInstance,
                            Object[] args) {
-        
-        // Must have debug or error logging enabled
-        if (!log.isDebugEnabled() && !log.isErrorEnabled()) {
-            return;
-        }
-        
-        // Get the root of the exception
-        Throwable rootT = null;
-        if (throwable instanceof InvocationTargetException) {
-            rootT = ((InvocationTargetException) throwable).getTargetException();
-        }
-        
-        
-        String name = rootT.getClass().getName();
-        String stack = stackToString(rootT);
-        
-        // Determine if this is a checked exception or non-checked exception
-        Class checkedException = JavaUtils.getCheckedException(rootT, method);
-        
-        if (checkedException == null) {
-            // Only log errors for non-checked exceptions
-            if (log.isErrorEnabled()) {
-                String text = "";
-                if (logFully) {
-                    text = Messages.getMessage("failureLogger", name, rootT.toString());
-                   
-                } else {
-                    text = Messages.getMessage("failureLogger", name, stack);
-                }
-                log.error(text);
+
+        // No matter what happens in this logging method, do not surface that exception.  We don't want a logging
+        // failure to mask the real exception we are trying to log or affect subsequent processing.
+        try {
+                
+            // Must have debug or error logging enabled
+            if (!log.isDebugEnabled() && !log.isErrorEnabled()) {
+                return;
             }
             
-        } 
-        
-        // Full logging if debug is enabled.
-        if (log.isDebugEnabled()) {
-            log.debug("Exception invoking a method of " + serviceImplClass.toString()
-                    + " of instance " + serviceInstance.toString());
-            log.debug("Exception type thrown: " + throwable.getClass().getName());
-            if (rootT != null) {
-                log.debug("Root Exception type thrown: " + rootT.getClass().getName());
-            }
-            if (checkedException != null) {
-                log.debug("The exception is an instance of checked exception: " + 
-                          checkedException.getName());
+            // Get the root of the exception
+            Throwable rootT = null;
+            if (throwable instanceof InvocationTargetException) {
+                rootT = ((InvocationTargetException) throwable).getTargetException();
+            } else {
+                rootT = throwable;
             }
             
-            // Extra trace if ElementNSImpl incompatibility problem.
-            // The incompatibility exception occurs if the JAXB Unmarshaller 
-            // unmarshals to a dom element instead of a generated object.  This can 
-            // result in class cast exceptions.  The solution is usually a missing
-            // @XmlSeeAlso annotation in the jaxws or jaxb classes. 
-            if (rootT.toString().contains("org.apache.xerces.dom.ElementNSImpl incompatible")) {
-            	log.debug("This exception may be due to a missing @XmlSeeAlso in the client's jaxws or" +
-            			" jaxb classes.");
+            String name = rootT.getClass().getName();
+            log.debug("693210: root Throwable, may cause index error: " + rootT.toString(), rootT);
+            String stack = stackToString(rootT);
+            
+            // Determine if this is a checked exception or non-checked exception
+            Class checkedException = JavaUtils.getCheckedException(rootT, method);
+            
+            if (checkedException == null) {
+                // Only log errors for non-checked exceptions
+                if (log.isErrorEnabled()) {
+                    String text = "";
+                    if (logFully) {
+                        text = Messages.getMessage("failureLogger", name, rootT.toString());
+                       
+                    } else {
+                        text = Messages.getMessage("failureLogger", name, stack);
+                    }
+                    log.error(text);
+                }
+                
+            } 
+            
+            // Full logging if debug is enabled.
+            if (log.isDebugEnabled()) {
+                log.debug("Exception invoking a method of " + serviceImplClass.toString()
+                        + " of instance " + serviceInstance.toString());
+                log.debug("Exception type thrown: " + throwable.getClass().getName());
+                if (rootT != null) {
+                    log.debug("Root Exception type thrown: " + rootT.getClass().getName());
+                }
+                if (checkedException != null) {
+                    log.debug("The exception is an instance of checked exception: " + 
+                              checkedException.getName());
+                }
+                
+                // Extra trace if ElementNSImpl incompatibility problem.
+                // The incompatibility exception occurs if the JAXB Unmarshaller 
+                // unmarshals to a dom element instead of a generated object.  This can 
+                // result in class cast exceptions.  The solution is usually a missing
+                // @XmlSeeAlso annotation in the jaxws or jaxb classes. 
+                if (rootT.toString().contains("org.apache.xerces.dom.ElementNSImpl incompatible")) {
+                	log.debug("This exception may be due to a missing @XmlSeeAlso in the client's jaxws or" +
+                			" jaxb classes.");
+                }
+                log.debug("Method = " + method.toGenericString());
+                for (int i = 0; i < args.length; i++) {
+                    String value =
+                            (args[i] == null) ? "null"
+                                    : args[i].getClass().toString();
+                    log.debug(" Argument[" + i + "] is " + value);
+                }
             }
-            log.debug("Method = " + method.toGenericString());
-            for (int i = 0; i < args.length; i++) {
-                String value =
-                        (args[i] == null) ? "null"
-                                : args[i].getClass().toString();
-                log.debug(" Argument[" + i + "] is " + value);
+        } catch (Throwable t) {
+            if (log.isDebugEnabled()) {
+                log.debug("Caught throwable in logger", t);
+                log.debug("While attempting to log original exception", throwable);
             }
         }
         return;
@@ -126,15 +138,18 @@ public class WebServiceExceptionLogger {
      * @param e
      * @return
      */
-    private static String stackToString(Throwable e) {
+    static String stackToString(Throwable e) {
         java.io.StringWriter sw = new java.io.StringWriter();
         java.io.BufferedWriter bw = new java.io.BufferedWriter(sw);
         java.io.PrintWriter pw = new java.io.PrintWriter(bw);
         e.printStackTrace(pw);
         pw.close();
         String text = sw.getBuffer().toString();
-        // Jump past the throwable
-        text = text.substring(text.indexOf("at"));
+        // Jump past the name of the throwable cause in the stack
+        int indexOfThrowable = text.indexOf("at");
+        if (indexOfThrowable > 0) {
+            text = text.substring(indexOfThrowable);
+        }
         return text;
     }
     

Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java?rev=1075057&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/WebServiceExceptionLoggerTests.java Sun Feb 27 14:11:00 2011
@@ -0,0 +1,112 @@
+/*
+ * 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.axis2.jaxws;
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+/**
+ * Validate the WebServiceExeptionLogger
+ */
+public class WebServiceExceptionLoggerTests extends TestCase {
+    
+    /**
+     * Validate that if we pass in an exception without any stack information, it does not cause an exception.
+     */
+    public void testNoStack() {
+        
+        ServiceClass serviceClass = new ServiceClass();
+        Method method = null;
+        try {
+            method = ImplClass.class.getDeclaredMethod("implMethod");
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Test implementation error: unable to get test class method due to exception: " + e.toString());
+        }
+        Exception rootCause = new EmptyStackTraceException();
+        InvocationTargetException invTargetExc = new InvocationTargetException(rootCause);
+        WebServiceExceptionLogger.log(method, 
+                invTargetExc,
+                false,
+                ImplClass.class,
+                serviceClass,
+                null);
+    }
+    
+    /**
+     * Validate that a exception that is not of type InvocationTargetException does not cause any issues in the logger.
+     */
+    public void testNonInvocationTargetException() {
+        
+        ServiceClass serviceClass = new ServiceClass();
+        Method method = null;
+        try {
+            method = ImplClass.class.getDeclaredMethod("implMethod");
+        } catch (Exception e) {
+            e.printStackTrace();
+            fail("Test implementation error: unable to get test class method due to exception: " + e.toString());
+        }
+        Exception rootCause = new NonemptyStackTraceException();
+        WebServiceExceptionLogger.log(method, 
+                rootCause,
+                false,
+                ImplClass.class,
+                serviceClass,
+                null);
+    }
+    
+    /**
+     * Validate the stackToString method works if there is no stack returned by the exception passed in.  It is necessary
+     * to validate this method directly since the WebServcieExceptionLogger.log method will catch all exceptions so it
+     * will never fail.
+     */
+    public void testStackToStrig_NoStack() {
+        String returnedStack = WebServiceExceptionLogger.stackToString(new EmptyStackTraceException());
+        // If we don't get an exception, then this test passes.
+    }
+    
+    /**
+     * Validate that the returned stack skips over the original throwable's name.
+     */
+    public void testStackToString() {
+        Exception nonEmpty = new NonemptyStackTraceException();
+        String returnedStack = WebServiceExceptionLogger.stackToString(nonEmpty);
+        assertFalse("Returned stack did not skip the original throwable", returnedStack.contains("NonemptyStackTraceException"));
+    }
+    
+    class ImplClass {
+        
+        public String implMethod() { return "foo"; }
+        
+    }
+    
+    class ServiceClass {
+        
+    }
+    
+    class EmptyStackTraceException extends Exception {
+        public void printStackTrace(PrintWriter err) { }
+    }
+    
+    class NonemptyStackTraceException extends Exception {
+    }
+}