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