Coverage Report - org.mule.config.ExceptionHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
ExceptionHelper
0%
0/222
0%
0/106
0
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.config;
 8  
 
 9  
 import org.mule.api.MuleException;
 10  
 import org.mule.api.MuleRuntimeException;
 11  
 import org.mule.api.config.ExceptionReader;
 12  
 import org.mule.api.registry.ServiceType;
 13  
 import org.mule.config.i18n.CoreMessages;
 14  
 import org.mule.util.ClassUtils;
 15  
 import org.mule.util.MapUtils;
 16  
 import org.mule.util.SpiUtils;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.InputStream;
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.util.ArrayList;
 22  
 import java.util.HashMap;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 import java.util.Properties;
 27  
 
 28  
 import org.apache.commons.logging.Log;
 29  
 import org.apache.commons.logging.LogFactory;
 30  
 
 31  
 /**
 32  
  * <code>ExceptionHelper</code> provides a number of helper functions that can be
 33  
  * useful for dealing with Mule exceptions. This class has 3 core functions - <p/> 1.
 34  
  * ErrorCode lookup. A corresponding Mule error code can be found using for a given
 35  
  * Mule exception 2. Additional Error information such as Java doc url for a given
 36  
  * exception can be resolved using this class 3. Error code mappings can be looked up
 37  
  * by providing the the protocol to map to and the Mule exception.
 38  
  */
 39  
 
 40  
 public final class ExceptionHelper
 41  
 {
 42  
     /**
 43  
      * This is the property to set the error code to no the message it is the
 44  
      * property name the Transport provider uses set the set the error code on the
 45  
      * underlying message
 46  
      */
 47  
     public static final String ERROR_CODE_PROPERTY = "error.code.property";
 48  
 
 49  
     /**
 50  
      * logger used by this class
 51  
      */
 52  0
     protected static final Log logger = LogFactory.getLog(ExceptionHelper.class);
 53  
 
 54  0
     private static String J2SE_VERSION = "";
 55  
 
 56  
     /**
 57  
      * todo How do you get the j2ee version??
 58  
      */
 59  
     private static final String J2EE_VERSION = "1.3ee";
 60  
 
 61  0
     private static Properties errorDocs = new Properties();
 62  0
     private static Properties errorCodes = new Properties();
 63  0
     private static Map reverseErrorCodes = null;
 64  0
     private static Map errorMappings = new HashMap();
 65  
 
 66  0
     private static int exceptionThreshold = 0;
 67  0
     private static boolean verbose = true;
 68  
 
 69  0
     private static boolean initialised = false;
 70  
 
 71  
     /**
 72  
      * A list of the exception readers to use for different types of exceptions
 73  
      */
 74  0
     private static List<ExceptionReader> exceptionReaders = new ArrayList<ExceptionReader>();
 75  
 
 76  
     /**
 77  
      * The default ExceptionReader which will be used for most types of exceptions
 78  
      */
 79  0
     private static ExceptionReader defaultExceptionReader = new DefaultExceptionReader();
 80  
 
 81  
     static
 82  
     {
 83  0
         initialise();
 84  0
     }
 85  
 
 86  
     /**
 87  
      * Do not instanciate.
 88  
      */
 89  
     private ExceptionHelper()
 90  0
     {
 91  
         // no-op
 92  0
     }
 93  
 
 94  
     private static void initialise()
 95  
     {
 96  
         try
 97  
         {
 98  0
             if (initialised)
 99  
             {
 100  0
                 return;
 101  
             }
 102  
 
 103  0
             registerExceptionReader(new MuleExceptionReader());
 104  0
             registerExceptionReader(new NamingExceptionReader());
 105  0
             J2SE_VERSION = System.getProperty("java.specification.version");
 106  
 
 107  0
             String name = SpiUtils.SERVICE_ROOT + ServiceType.EXCEPTION.getPath()
 108  
                     + "/mule-exception-codes.properties";
 109  0
             InputStream in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name);
 110  0
             if (in == null)
 111  
             {
 112  0
                 throw new IllegalArgumentException("Failed to load resource: " + name);
 113  
             }
 114  0
             errorCodes.load(in);
 115  0
             in.close();
 116  
 
 117  0
             reverseErrorCodes = MapUtils.invertMap(errorCodes);
 118  
 
 119  0
             name = SpiUtils.SERVICE_ROOT + ServiceType.EXCEPTION.getPath()
 120  
                     + "/mule-exception-config.properties";
 121  0
             in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name);
 122  0
             if (in == null)
 123  
             {
 124  0
                 throw new IllegalArgumentException("Failed to load resource: " + name);
 125  
             }
 126  0
             errorDocs.load(in);
 127  0
             in.close();
 128  
 
 129  0
             initialised = true;
 130  
         }
 131  0
         catch (Exception e)
 132  
         {
 133  0
             throw new MuleRuntimeException(CoreMessages.failedToLoad("Exception resources"), e);
 134  0
         }
 135  0
     }
 136  
 
 137  
     public static int getErrorCode(Class exception)
 138  
     {
 139  0
         String code = errorCodes.getProperty(exception.getName(), "-1");
 140  0
         return Integer.parseInt(code);
 141  
     }
 142  
 
 143  
     public static Class getErrorClass(int code)
 144  
     {
 145  0
         String key = String.valueOf(code);
 146  0
         Object clazz = reverseErrorCodes.get(key);
 147  0
         if (clazz == null)
 148  
         {
 149  0
             return null;
 150  
         }
 151  0
         else if (clazz instanceof Class)
 152  
         {
 153  0
             return (Class) clazz;
 154  
         }
 155  
         else
 156  
         {
 157  
             try
 158  
             {
 159  0
                 clazz = ClassUtils.loadClass(clazz.toString(), ExceptionHelper.class);
 160  
             }
 161  0
             catch (ClassNotFoundException e)
 162  
             {
 163  0
                 logger.error(e.getMessage(), e);
 164  0
                 return null;
 165  0
             }
 166  0
             reverseErrorCodes.put(key, clazz);
 167  0
             return (Class) clazz;
 168  
         }
 169  
     }
 170  
 
 171  
     private static Properties getErrorMappings(String protocol)
 172  
     {
 173  0
         Object m = errorMappings.get(protocol);
 174  0
         if (m != null)
 175  
         {
 176  0
             if (m instanceof Properties)
 177  
             {
 178  0
                 return (Properties) m;
 179  
             }
 180  
             else
 181  
             {
 182  0
                 return null;
 183  
             }
 184  
         }
 185  
         else
 186  
         {
 187  0
             String name = SpiUtils.SERVICE_ROOT + ServiceType.EXCEPTION.getPath() + "/" + protocol + "-exception-mappings.properties";
 188  0
             InputStream in = ExceptionHelper.class.getClassLoader().getResourceAsStream(name);
 189  0
             if (in == null)
 190  
             {
 191  0
                 errorMappings.put(protocol, "not found");
 192  0
                 if (logger.isDebugEnabled())
 193  
                 {
 194  0
                     logger.debug("Failed to load error mappings from: " + name
 195  
                             + " This may be because there are no error code mappings for protocol: "
 196  
                             + protocol);
 197  
                 }
 198  0
                 return null;
 199  
             }
 200  
 
 201  0
             Properties p = new Properties();
 202  
             try
 203  
             {
 204  0
                 p.load(in);
 205  0
                 in.close();
 206  
             }
 207  0
             catch (IOException iox)
 208  
             {
 209  0
                 throw new IllegalArgumentException("Failed to load resource: " + name);
 210  0
             }
 211  
 
 212  0
             errorMappings.put(protocol, p);
 213  0
             return p;
 214  
         }
 215  
     }
 216  
 
 217  
     public static String getErrorCodePropertyName(String protocol)
 218  
     {
 219  0
         protocol = protocol.toLowerCase();
 220  0
         Properties mappings = getErrorMappings(protocol);
 221  0
         if (mappings == null)
 222  
         {
 223  0
             return null;
 224  
         }
 225  0
         return mappings.getProperty(ERROR_CODE_PROPERTY);
 226  
     }
 227  
 
 228  
     public static String getErrorMapping(String protocol, Class exception)
 229  
     {
 230  0
         protocol = protocol.toLowerCase();
 231  0
         Properties mappings = getErrorMappings(protocol);
 232  0
         if (mappings == null)
 233  
         {
 234  0
             logger.info("No mappings found for protocol: " + protocol);
 235  0
             return String.valueOf(getErrorCode(exception));
 236  
         }
 237  
 
 238  0
         Class clazz = exception;
 239  0
         String code = null;
 240  0
         while (!clazz.equals(Object.class))
 241  
         {
 242  0
             code = mappings.getProperty(clazz.getName());
 243  0
             if (code == null)
 244  
             {
 245  0
                 clazz = clazz.getSuperclass();
 246  
             }
 247  
             else
 248  
             {
 249  0
                 return code;
 250  
             }
 251  
         }
 252  0
         code = String.valueOf(getErrorCode(exception));
 253  
         // Finally lookup mapping based on error code and return the Mule error
 254  
         // code if a match is not found
 255  0
         return mappings.getProperty(code, code);
 256  
     }
 257  
 
 258  
     public static String getJavaDocUrl(Class<?> exception)
 259  
     {
 260  0
         return getDocUrl("javadoc.", exception.getName());
 261  
     }
 262  
 
 263  
     public static String getDocUrl(Class<?> exception)
 264  
     {
 265  0
         return getDocUrl("doc.", exception.getName());
 266  
     }
 267  
 
 268  
     private static String getDocUrl(String prefix, String packageName)
 269  
     {
 270  0
         String key = prefix;
 271  0
         if (packageName.startsWith("java.") || packageName.startsWith("javax."))
 272  
         {
 273  0
             key += J2SE_VERSION;
 274  
         }
 275  0
         String url = getUrl(key, packageName);
 276  0
         if (url == null && (packageName.startsWith("java.") || packageName.startsWith("javax.")))
 277  
         {
 278  0
             key = prefix + J2EE_VERSION;
 279  0
             url = getUrl(key, packageName);
 280  
         }
 281  0
         if (url != null)
 282  
         {
 283  0
             if (!url.endsWith("/"))
 284  
             {
 285  0
                 url += "/";
 286  
             }
 287  0
             String s = packageName.replaceAll("[.]", "/");
 288  0
             s += ".html";
 289  0
             url += s;
 290  
         }
 291  0
         return url;
 292  
     }
 293  
 
 294  
     private static String getUrl(String key, String packageName)
 295  
     {
 296  0
         String url = null;
 297  0
         if (!key.endsWith("."))
 298  
         {
 299  0
             key += ".";
 300  
         }
 301  0
         while (packageName.length() > 0)
 302  
         {
 303  0
             url = errorDocs.getProperty(key + packageName, null);
 304  0
             if (url == null)
 305  
             {
 306  0
                 int i = packageName.lastIndexOf(".");
 307  0
                 if (i == -1)
 308  
                 {
 309  0
                     packageName = "";
 310  
                 }
 311  
                 else
 312  
                 {
 313  0
                     packageName = packageName.substring(0, i);
 314  
                 }
 315  0
             }
 316  
             else
 317  
             {
 318  
                 break;
 319  
             }
 320  
         }
 321  0
         return url;
 322  
     }
 323  
 
 324  
     public static Throwable getRootException(Throwable t)
 325  
     {
 326  0
         Throwable cause = t;
 327  0
         Throwable root = null;
 328  0
         while (cause != null)
 329  
         {
 330  0
             root = cause;
 331  0
             cause = getExceptionReader(cause).getCause(cause);
 332  
             // address some misbehaving exceptions, avoid endless loop
 333  0
             if (t == cause)
 334  
             {
 335  0
                 break;
 336  
             }
 337  
         }
 338  
 
 339  0
         return DefaultMuleConfiguration.fullStackTraces ? root : sanitize(root);
 340  
     }
 341  
 
 342  
     public static Throwable sanitizeIfNeeded(Throwable t)
 343  
     {
 344  0
         return DefaultMuleConfiguration.fullStackTraces ? t : sanitize(t);
 345  
     }
 346  
 
 347  
     /**
 348  
      * Removes some internal Mule entries from the stacktrace. Modifies the
 349  
      * passed-in throwable stacktrace.
 350  
      */
 351  
     public static Throwable sanitize(Throwable t)
 352  
     {
 353  0
         if (t == null)
 354  
         {
 355  0
             return null;
 356  
         }
 357  0
         StackTraceElement[] trace = t.getStackTrace();
 358  0
         List<StackTraceElement> newTrace = new ArrayList<StackTraceElement>();
 359  0
         for (StackTraceElement stackTraceElement : trace)
 360  
         {
 361  0
             if (!isMuleInternalClass(stackTraceElement.getClassName()))
 362  
             {
 363  0
                 newTrace.add(stackTraceElement);
 364  
             }
 365  
         }
 366  
 
 367  0
         StackTraceElement[] clean = new StackTraceElement[newTrace.size()];
 368  0
         newTrace.toArray(clean);
 369  0
         t.setStackTrace(clean);
 370  
 
 371  0
         Throwable cause = t.getCause();
 372  0
         while (cause != null)
 373  
         {
 374  0
             sanitize(cause);
 375  0
             cause = cause.getCause();
 376  
         }
 377  
 
 378  0
         return t;
 379  
     }
 380  
 
 381  
 
 382  
     /**
 383  
      * Removes some internal Mule entries from the stacktrace. Modifies the
 384  
      * passed-in throwable stacktrace.
 385  
      */
 386  
     public static Throwable summarise(Throwable t, int depth)
 387  
     {
 388  0
         t = sanitize(t);
 389  0
         StackTraceElement[] trace = t.getStackTrace();
 390  
 
 391  0
         int newStackDepth = Math.min(trace.length, depth);
 392  0
         StackTraceElement[] newTrace = new StackTraceElement[newStackDepth];
 393  
 
 394  0
         System.arraycopy(trace, 0, newTrace, 0, newStackDepth);
 395  0
         t.setStackTrace(newTrace);
 396  
         
 397  0
         return t;
 398  
     }
 399  
 
 400  
     private static boolean isMuleInternalClass(String className)
 401  
     {
 402  
         /*
 403  
            Sacrifice the code quality for the sake of keeping things simple -
 404  
            the alternative would be to pass MuleContext into every exception constructor.
 405  
         */
 406  0
         for (String mulePackage : DefaultMuleConfiguration.stackTraceFilter)
 407  
         {
 408  0
             if (className.startsWith(mulePackage))
 409  
             {
 410  0
                 return true;
 411  
             }
 412  
         }
 413  0
         return false;
 414  
     }
 415  
 
 416  
     public static Throwable getRootParentException(Throwable t)
 417  
     {
 418  0
         Throwable cause = t;
 419  0
         Throwable parent = t;
 420  0
         while (cause != null)
 421  
         {
 422  0
             if (cause.getCause() == null)
 423  
             {
 424  0
                 return parent;
 425  
             }
 426  0
             parent = cause;
 427  0
             cause = getExceptionReader(cause).getCause(cause);
 428  
             // address some misbehaving exceptions, avoid endless loop
 429  0
             if (t == cause)
 430  
             {
 431  0
                 break;
 432  
             }
 433  
         }
 434  0
         return t;
 435  
     }
 436  
 
 437  
     public static MuleException getRootMuleException(Throwable t)
 438  
     {
 439  0
         Throwable cause = t;
 440  0
         MuleException exception = null;
 441  0
         while (cause != null)
 442  
         {
 443  0
             if (cause instanceof MuleException)
 444  
             {
 445  0
                 exception = (MuleException) cause;
 446  
             }
 447  0
             final Throwable tempCause = getExceptionReader(cause).getCause(cause);
 448  0
             if (DefaultMuleConfiguration.fullStackTraces)
 449  
             {
 450  0
                 cause = tempCause;
 451  
             }
 452  
             else
 453  
             {
 454  0
                 cause = ExceptionHelper.sanitize(tempCause);
 455  
             }
 456  
             // address some misbehaving exceptions, avoid endless loop
 457  0
             if (t == cause)
 458  
             {
 459  0
                 break;
 460  
             }
 461  0
         }
 462  0
         return exception;
 463  
     }
 464  
 
 465  
     public static List getExceptionsAsList(Throwable t)
 466  
     {
 467  0
         List exceptions = new ArrayList();
 468  0
         Throwable cause = t;
 469  0
         while (cause != null)
 470  
         {
 471  0
             exceptions.add(0, cause);
 472  0
             cause = getExceptionReader(cause).getCause(cause);
 473  
             // address some misbehaving exceptions, avoid endless loop
 474  0
             if (t == cause)
 475  
             {
 476  0
                 break;
 477  
             }
 478  
         }
 479  0
         return exceptions;
 480  
     }
 481  
 
 482  
     public static Map getExceptionInfo(Throwable t)
 483  
     {
 484  0
         Map info = new HashMap();
 485  0
         Throwable cause = t;
 486  0
         while (cause != null)
 487  
         {
 488  0
             info.putAll(getExceptionReader(cause).getInfo(cause));
 489  0
             cause = getExceptionReader(cause).getCause(cause);
 490  
             // address some misbehaving exceptions, avoid endless loop
 491  0
             if (t == cause)
 492  
             {
 493  0
                 break;
 494  
             }
 495  
         }
 496  0
         return info;
 497  
     }
 498  
 
 499  
     public static String getExceptionStack(Throwable t)
 500  
     {
 501  0
         StringBuffer buf = new StringBuffer();
 502  
         // get exception stack
 503  0
         List exceptions = getExceptionsAsList(t);
 504  
 
 505  0
         int i = 1;
 506  0
         for (Iterator iterator = exceptions.iterator(); iterator.hasNext(); i++)
 507  
         {
 508  0
             if (i > exceptionThreshold && exceptionThreshold > 0)
 509  
             {
 510  0
                 buf.append("(").append(exceptions.size() - i + 1).append(" more...)");
 511  0
                 break;
 512  
             }
 513  0
             Throwable throwable = (Throwable) iterator.next();
 514  0
             ExceptionReader er = getExceptionReader(throwable);
 515  0
             buf.append(i).append(". ").append(er.getMessage(throwable)).append(" (");
 516  0
             buf.append(throwable.getClass().getName()).append(")\n");
 517  0
             if (verbose && throwable.getStackTrace().length > 0)
 518  
             {
 519  0
                 StackTraceElement e = throwable.getStackTrace()[0];
 520  0
                 buf.append("  ")
 521  
                         .append(e.getClassName())
 522  
                         .append(":")
 523  
                         .append(e.getLineNumber())
 524  
                         .append(" (")
 525  
                         .append(getJavaDocUrl(throwable.getClass()))
 526  
                         .append(")\n");
 527  
             }
 528  
         }
 529  0
         return buf.toString();
 530  
     }
 531  
 
 532  
     /**
 533  
      * Registers an exception reader with Mule
 534  
      *
 535  
      * @param reader the reader to register.
 536  
      */
 537  
     public static void registerExceptionReader(ExceptionReader reader)
 538  
     {
 539  0
         exceptionReaders.add(reader);
 540  0
     }
 541  
 
 542  
     /**
 543  
      * Gets an exception reader for the exception
 544  
      *
 545  
      * @param t the exception to get a reader for
 546  
      * @return either a specific reader or an instance of DefaultExceptionReader.
 547  
      *         This method never returns null;
 548  
      */
 549  
     public static ExceptionReader getExceptionReader(Throwable t)
 550  
     {
 551  0
         for (ExceptionReader exceptionReader : exceptionReaders)
 552  
         {
 553  0
             if (exceptionReader.getExceptionType().isInstance(t))
 554  
             {
 555  0
                 return exceptionReader;
 556  
             }
 557  
         }
 558  0
         return defaultExceptionReader;
 559  
     }
 560  
 
 561  
     public static String writeException(Throwable t)
 562  
     {
 563  0
         ExceptionReader er = getExceptionReader(t);
 564  0
         StringBuffer msg = new StringBuffer();
 565  0
         msg.append(er.getMessage(t)).append(". Type: ").append(t.getClass());
 566  0
         return msg.toString();
 567  
     }
 568  
 
 569  
     public static <T extends Throwable>T unwrap(T t)
 570  
     {
 571  0
         if(t instanceof InvocationTargetException)
 572  
         {
 573  0
             return (T)((InvocationTargetException)t).getTargetException();
 574  
         }
 575  0
         return t;
 576  
 
 577  
     }
 578  
 }