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