Source Code Cross Referenced for ExceptionUtils.java in  » Library » Apache-common-lang » org » apache » commons » lang » exception » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache common lang » org.apache.commons.lang.exception 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.commons.lang.exception;
0018:
0019:        import java.io.PrintStream;
0020:        import java.io.PrintWriter;
0021:        import java.io.StringWriter;
0022:        import java.lang.reflect.Field;
0023:        import java.lang.reflect.InvocationTargetException;
0024:        import java.lang.reflect.Method;
0025:        import java.sql.SQLException;
0026:        import java.util.ArrayList;
0027:        import java.util.Arrays;
0028:        import java.util.List;
0029:        import java.util.StringTokenizer;
0030:
0031:        import org.apache.commons.lang.ArrayUtils;
0032:        import org.apache.commons.lang.ClassUtils;
0033:        import org.apache.commons.lang.NullArgumentException;
0034:        import org.apache.commons.lang.StringUtils;
0035:        import org.apache.commons.lang.SystemUtils;
0036:
0037:        /**
0038:         * <p>Provides utilities for manipulating and examining 
0039:         * <code>Throwable</code> objects.</p>
0040:         *
0041:         * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
0042:         * @author Dmitri Plotnikov
0043:         * @author Stephen Colebourne
0044:         * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
0045:         * @author Pete Gieser
0046:         * @since 1.0
0047:         * @version $Id: ExceptionUtils.java 437554 2006-08-28 06:21:41Z bayard $
0048:         */
0049:        public class ExceptionUtils {
0050:
0051:            /**
0052:             * <p>Used when printing stack frames to denote the start of a
0053:             * wrapped exception.</p>
0054:             *
0055:             * <p>Package private for accessibility by test suite.</p>
0056:             */
0057:            static final String WRAPPED_MARKER = " [wrapped] ";
0058:
0059:            /**
0060:             * <p>The names of methods commonly used to access a wrapped exception.</p>
0061:             */
0062:            private static String[] CAUSE_METHOD_NAMES = { "getCause",
0063:                    "getNextException", "getTargetException", "getException",
0064:                    "getSourceException", "getRootCause",
0065:                    "getCausedByException", "getNested", "getLinkedException",
0066:                    "getNestedException", "getLinkedCause", "getThrowable", };
0067:
0068:            /**
0069:             * <p>The Method object for Java 1.4 getCause.</p>
0070:             */
0071:            private static final Method THROWABLE_CAUSE_METHOD;
0072:
0073:            /**
0074:             * <p>The Method object for Java 1.4 initCause.</p>
0075:             */
0076:            private static final Method THROWABLE_INITCAUSE_METHOD;
0077:
0078:            static {
0079:                Method causeMethod;
0080:                try {
0081:                    causeMethod = Throwable.class.getMethod("getCause", null);
0082:                } catch (Exception e) {
0083:                    causeMethod = null;
0084:                }
0085:                THROWABLE_CAUSE_METHOD = causeMethod;
0086:                try {
0087:                    causeMethod = Throwable.class.getMethod("initCause",
0088:                            new Class[] { Throwable.class });
0089:                } catch (Exception e) {
0090:                    causeMethod = null;
0091:                }
0092:                THROWABLE_INITCAUSE_METHOD = causeMethod;
0093:            }
0094:
0095:            /**
0096:             * <p>
0097:             * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
0098:             * normally necessary.
0099:             * </p>
0100:             */
0101:            public ExceptionUtils() {
0102:                super ();
0103:            }
0104:
0105:            //-----------------------------------------------------------------------
0106:            /**
0107:             * <p>Adds to the list of method names used in the search for <code>Throwable</code>
0108:             * objects.</p>
0109:             * 
0110:             * @param methodName  the methodName to add to the list, <code>null</code>
0111:             *  and empty strings are ignored
0112:             * @since 2.0
0113:             */
0114:            public static void addCauseMethodName(String methodName) {
0115:                if (StringUtils.isNotEmpty(methodName)
0116:                        && !isCauseMethodName(methodName)) {
0117:                    List list = getCauseMethodNameList();
0118:                    if (list.add(methodName)) {
0119:                        CAUSE_METHOD_NAMES = toArray(list);
0120:                    }
0121:                }
0122:            }
0123:
0124:            /**
0125:             * <p>Removes from the list of method names used in the search for <code>Throwable</code>
0126:             * objects.</p>
0127:             * 
0128:             * @param methodName  the methodName to remove from the list, <code>null</code>
0129:             *  and empty strings are ignored
0130:             * @since 2.1
0131:             */
0132:            public static void removeCauseMethodName(String methodName) {
0133:                if (StringUtils.isNotEmpty(methodName)) {
0134:                    List list = getCauseMethodNameList();
0135:                    if (list.remove(methodName)) {
0136:                        CAUSE_METHOD_NAMES = toArray(list);
0137:                    }
0138:                }
0139:            }
0140:
0141:            /**
0142:             * <p>Sets the cause of a <code>Throwable</code> using introspection, allowing
0143:             * source code compatibility between pre-1.4 and post-1.4 Java releases.</p>
0144:             *
0145:             * <p>The typical use of this method is inside a constructor as in
0146:             * the following example:</p>
0147:             *
0148:             * <pre>
0149:             * import org.apache.commons.lang.exception.ExceptionUtils;
0150:             *  
0151:             * public class MyException extends Exception {
0152:             *  
0153:             *    public MyException(String msg) {
0154:             *       super(msg);
0155:             *    }
0156:             *
0157:             *    public MyException(String msg, Throwable cause) {
0158:             *       super(msg);
0159:             *       ExceptionUtils.setCause(this, cause);
0160:             *    }
0161:             * }
0162:             * </pre>
0163:             *
0164:             * @param target  the target <code>Throwable</code>
0165:             * @param cause  the <code>Throwable</code> to set in the target
0166:             * @return a <code>true</code> if the target has been modified
0167:             * @since 2.2
0168:             */
0169:            public static boolean setCause(Throwable target, Throwable cause) {
0170:                if (target == null) {
0171:                    throw new NullArgumentException("target");
0172:                }
0173:                Object[] causeArgs = new Object[] { cause };
0174:                boolean modifiedTarget = false;
0175:                if (THROWABLE_INITCAUSE_METHOD != null) {
0176:                    try {
0177:                        THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
0178:                        modifiedTarget = true;
0179:                    } catch (IllegalAccessException ignored) {
0180:                        // Exception ignored.
0181:                    } catch (InvocationTargetException ignored) {
0182:                        // Exception ignored.
0183:                    }
0184:                }
0185:                try {
0186:                    Method setCauseMethod = target.getClass().getMethod(
0187:                            "setCause", new Class[] { Throwable.class });
0188:                    setCauseMethod.invoke(target, causeArgs);
0189:                    modifiedTarget = true;
0190:                } catch (NoSuchMethodException ignored) {
0191:                    // Exception ignored.
0192:                } catch (IllegalAccessException ignored) {
0193:                    // Exception ignored.
0194:                } catch (InvocationTargetException ignored) {
0195:                    // Exception ignored.
0196:                }
0197:                return modifiedTarget;
0198:            }
0199:
0200:            /**
0201:             * Returns the given list as a <code>String[]</code>.
0202:             * @param list a list to transform.
0203:             * @return the given list as a <code>String[]</code>.
0204:             */
0205:            private static String[] toArray(List list) {
0206:                return (String[]) list.toArray(new String[list.size()]);
0207:            }
0208:
0209:            /**
0210:             * Returns {@link #CAUSE_METHOD_NAMES} as a List.
0211:             *
0212:             * @return {@link #CAUSE_METHOD_NAMES} as a List.
0213:             */
0214:            private static ArrayList getCauseMethodNameList() {
0215:                return new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
0216:            }
0217:
0218:            /**
0219:             * <p>Tests if the list of method names used in the search for <code>Throwable</code>
0220:             * objects include the given name.</p>
0221:             * 
0222:             * @param methodName  the methodName to search in the list.
0223:             * @return if the list of method names used in the search for <code>Throwable</code>
0224:             *  objects include the given name.
0225:             * @since 2.1
0226:             */
0227:            public static boolean isCauseMethodName(String methodName) {
0228:                return ArrayUtils.indexOf(CAUSE_METHOD_NAMES, methodName) >= 0;
0229:            }
0230:
0231:            //-----------------------------------------------------------------------
0232:            /**
0233:             * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
0234:             *
0235:             * <p>The method searches for methods with specific names that return a 
0236:             * <code>Throwable</code> object. This will pick up most wrapping exceptions,
0237:             * including those from JDK 1.4, and
0238:             * {@link org.apache.commons.lang.exception.NestableException NestableException}.
0239:             * The method names can be added to using {@link #addCauseMethodName(String)}.</p>
0240:             *
0241:             * <p>The default list searched for are:</p>
0242:             * <ul>
0243:             *  <li><code>getCause()</code></li>
0244:             *  <li><code>getNextException()</code></li>
0245:             *  <li><code>getTargetException()</code></li>
0246:             *  <li><code>getException()</code></li>
0247:             *  <li><code>getSourceException()</code></li>
0248:             *  <li><code>getRootCause()</code></li>
0249:             *  <li><code>getCausedByException()</code></li>
0250:             *  <li><code>getNested()</code></li>
0251:             * </ul>
0252:             * 
0253:             * <p>In the absence of any such method, the object is inspected for a
0254:             * <code>detail</code> field assignable to a <code>Throwable</code>.</p>
0255:             *
0256:             * <p>If none of the above is found, returns <code>null</code>.</p>
0257:             *
0258:             * @param throwable  the throwable to introspect for a cause, may be null
0259:             * @return the cause of the <code>Throwable</code>,
0260:             *  <code>null</code> if none found or null throwable input
0261:             * @since 1.0
0262:             */
0263:            public static Throwable getCause(Throwable throwable) {
0264:                return getCause(throwable, CAUSE_METHOD_NAMES);
0265:            }
0266:
0267:            /**
0268:             * <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
0269:             *
0270:             * <ol>
0271:             * <li>Try known exception types.</li>
0272:             * <li>Try the supplied array of method names.</li>
0273:             * <li>Try the field 'detail'.</li>
0274:             * </ol>
0275:             *
0276:             * <p>A <code>null</code> set of method names means use the default set.
0277:             * A <code>null</code> in the set of method names will be ignored.</p>
0278:             *
0279:             * @param throwable  the throwable to introspect for a cause, may be null
0280:             * @param methodNames  the method names, null treated as default set
0281:             * @return the cause of the <code>Throwable</code>,
0282:             *  <code>null</code> if none found or null throwable input
0283:             * @since 1.0
0284:             */
0285:            public static Throwable getCause(Throwable throwable,
0286:                    String[] methodNames) {
0287:                if (throwable == null) {
0288:                    return null;
0289:                }
0290:                Throwable cause = getCauseUsingWellKnownTypes(throwable);
0291:                if (cause == null) {
0292:                    if (methodNames == null) {
0293:                        methodNames = CAUSE_METHOD_NAMES;
0294:                    }
0295:                    for (int i = 0; i < methodNames.length; i++) {
0296:                        String methodName = methodNames[i];
0297:                        if (methodName != null) {
0298:                            cause = getCauseUsingMethodName(throwable,
0299:                                    methodName);
0300:                            if (cause != null) {
0301:                                break;
0302:                            }
0303:                        }
0304:                    }
0305:
0306:                    if (cause == null) {
0307:                        cause = getCauseUsingFieldName(throwable, "detail");
0308:                    }
0309:                }
0310:                return cause;
0311:            }
0312:
0313:            /**
0314:             * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
0315:             *
0316:             * <p>This method walks through the exception chain to the last element,
0317:             * "root" of the tree, using {@link #getCause(Throwable)}, and
0318:             * returns that exception.</p>
0319:             *
0320:             * <p>From version 2.2, this method handles recursive cause structures
0321:             * that might otherwise cause infinite loops. If the throwable parameter
0322:             * has a cause of itself, then null will be returned. If the throwable
0323:             * parameter cause chain loops, the last element in the chain before the
0324:             * loop is returned.</p>
0325:             *
0326:             * @param throwable  the throwable to get the root cause for, may be null
0327:             * @return the root cause of the <code>Throwable</code>,
0328:             *  <code>null</code> if none found or null throwable input
0329:             */
0330:            public static Throwable getRootCause(Throwable throwable) {
0331:                List list = getThrowableList(throwable);
0332:                return (list.size() < 2 ? null : (Throwable) list.get(list
0333:                        .size() - 1));
0334:            }
0335:
0336:            /**
0337:             * <p>Finds a <code>Throwable</code> for known types.</p>
0338:             * 
0339:             * <p>Uses <code>instanceof</code> checks to examine the exception,
0340:             * looking for well known types which could contain chained or
0341:             * wrapped exceptions.</p>
0342:             *
0343:             * @param throwable  the exception to examine
0344:             * @return the wrapped exception, or <code>null</code> if not found
0345:             */
0346:            private static Throwable getCauseUsingWellKnownTypes(
0347:                    Throwable throwable) {
0348:                if (throwable instanceof  Nestable) {
0349:                    return ((Nestable) throwable).getCause();
0350:                } else if (throwable instanceof  SQLException) {
0351:                    return ((SQLException) throwable).getNextException();
0352:                } else if (throwable instanceof  InvocationTargetException) {
0353:                    return ((InvocationTargetException) throwable)
0354:                            .getTargetException();
0355:                } else {
0356:                    return null;
0357:                }
0358:            }
0359:
0360:            /**
0361:             * <p>Finds a <code>Throwable</code> by method name.</p>
0362:             *
0363:             * @param throwable  the exception to examine
0364:             * @param methodName  the name of the method to find and invoke
0365:             * @return the wrapped exception, or <code>null</code> if not found
0366:             */
0367:            private static Throwable getCauseUsingMethodName(
0368:                    Throwable throwable, String methodName) {
0369:                Method method = null;
0370:                try {
0371:                    method = throwable.getClass().getMethod(methodName, null);
0372:                } catch (NoSuchMethodException ignored) {
0373:                    // exception ignored
0374:                } catch (SecurityException ignored) {
0375:                    // exception ignored
0376:                }
0377:
0378:                if (method != null
0379:                        && Throwable.class.isAssignableFrom(method
0380:                                .getReturnType())) {
0381:                    try {
0382:                        return (Throwable) method.invoke(throwable,
0383:                                ArrayUtils.EMPTY_OBJECT_ARRAY);
0384:                    } catch (IllegalAccessException ignored) {
0385:                        // exception ignored
0386:                    } catch (IllegalArgumentException ignored) {
0387:                        // exception ignored
0388:                    } catch (InvocationTargetException ignored) {
0389:                        // exception ignored
0390:                    }
0391:                }
0392:                return null;
0393:            }
0394:
0395:            /**
0396:             * <p>Finds a <code>Throwable</code> by field name.</p>
0397:             *
0398:             * @param throwable  the exception to examine
0399:             * @param fieldName  the name of the attribute to examine
0400:             * @return the wrapped exception, or <code>null</code> if not found
0401:             */
0402:            private static Throwable getCauseUsingFieldName(
0403:                    Throwable throwable, String fieldName) {
0404:                Field field = null;
0405:                try {
0406:                    field = throwable.getClass().getField(fieldName);
0407:                } catch (NoSuchFieldException ignored) {
0408:                    // exception ignored
0409:                } catch (SecurityException ignored) {
0410:                    // exception ignored
0411:                }
0412:
0413:                if (field != null
0414:                        && Throwable.class.isAssignableFrom(field.getType())) {
0415:                    try {
0416:                        return (Throwable) field.get(throwable);
0417:                    } catch (IllegalAccessException ignored) {
0418:                        // exception ignored
0419:                    } catch (IllegalArgumentException ignored) {
0420:                        // exception ignored
0421:                    }
0422:                }
0423:                return null;
0424:            }
0425:
0426:            //-----------------------------------------------------------------------
0427:            /**
0428:             * <p>Checks if the Throwable class has a <code>getCause</code> method.</p>
0429:             *
0430:             * <p>This is true for JDK 1.4 and above.</p>
0431:             *
0432:             * @return true if Throwable is nestable
0433:             * @since 2.0
0434:             */
0435:            public static boolean isThrowableNested() {
0436:                return THROWABLE_CAUSE_METHOD != null;
0437:            }
0438:
0439:            /**
0440:             * <p>Checks whether this <code>Throwable</code> class can store a cause.</p>
0441:             *
0442:             * <p>This method does <b>not</b> check whether it actually does store a cause.<p>
0443:             *
0444:             * @param throwable  the <code>Throwable</code> to examine, may be null
0445:             * @return boolean <code>true</code> if nested otherwise <code>false</code>
0446:             * @since 2.0
0447:             */
0448:            public static boolean isNestedThrowable(Throwable throwable) {
0449:                if (throwable == null) {
0450:                    return false;
0451:                }
0452:
0453:                if (throwable instanceof  Nestable) {
0454:                    return true;
0455:                } else if (throwable instanceof  SQLException) {
0456:                    return true;
0457:                } else if (throwable instanceof  InvocationTargetException) {
0458:                    return true;
0459:                } else if (isThrowableNested()) {
0460:                    return true;
0461:                }
0462:
0463:                Class cls = throwable.getClass();
0464:                for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
0465:                    try {
0466:                        Method method = cls.getMethod(CAUSE_METHOD_NAMES[i],
0467:                                null);
0468:                        if (method != null
0469:                                && Throwable.class.isAssignableFrom(method
0470:                                        .getReturnType())) {
0471:                            return true;
0472:                        }
0473:                    } catch (NoSuchMethodException ignored) {
0474:                        // exception ignored
0475:                    } catch (SecurityException ignored) {
0476:                        // exception ignored
0477:                    }
0478:                }
0479:
0480:                try {
0481:                    Field field = cls.getField("detail");
0482:                    if (field != null) {
0483:                        return true;
0484:                    }
0485:                } catch (NoSuchFieldException ignored) {
0486:                    // exception ignored
0487:                } catch (SecurityException ignored) {
0488:                    // exception ignored
0489:                }
0490:
0491:                return false;
0492:            }
0493:
0494:            //-----------------------------------------------------------------------
0495:            /**
0496:             * <p>Counts the number of <code>Throwable</code> objects in the
0497:             * exception chain.</p>
0498:             *
0499:             * <p>A throwable without cause will return <code>1</code>.
0500:             * A throwable with one cause will return <code>2</code> and so on.
0501:             * A <code>null</code> throwable will return <code>0</code>.</p>
0502:             *
0503:             * <p>From version 2.2, this method handles recursive cause structures
0504:             * that might otherwise cause infinite loops. The cause chain is
0505:             * processed until the end is reached, or until the next item in the
0506:             * chain is already in the result set.</p>
0507:             *
0508:             * @param throwable  the throwable to inspect, may be null
0509:             * @return the count of throwables, zero if null input
0510:             */
0511:            public static int getThrowableCount(Throwable throwable) {
0512:                return getThrowableList(throwable).size();
0513:            }
0514:
0515:            /**
0516:             * <p>Returns the list of <code>Throwable</code> objects in the
0517:             * exception chain.</p>
0518:             *
0519:             * <p>A throwable without cause will return an array containing
0520:             * one element - the input throwable.
0521:             * A throwable with one cause will return an array containing
0522:             * two elements. - the input throwable and the cause throwable.
0523:             * A <code>null</code> throwable will return an array of size zero.</p>
0524:             *
0525:             * <p>From version 2.2, this method handles recursive cause structures
0526:             * that might otherwise cause infinite loops. The cause chain is
0527:             * processed until the end is reached, or until the next item in the
0528:             * chain is already in the result set.</p>
0529:             *
0530:             * @see #getThrowableList(Throwable)
0531:             * @param throwable  the throwable to inspect, may be null
0532:             * @return the array of throwables, never null
0533:             */
0534:            public static Throwable[] getThrowables(Throwable throwable) {
0535:                List list = getThrowableList(throwable);
0536:                return (Throwable[]) list.toArray(new Throwable[list.size()]);
0537:            }
0538:
0539:            /**
0540:             * <p>Returns the list of <code>Throwable</code> objects in the
0541:             * exception chain.</p>
0542:             *
0543:             * <p>A throwable without cause will return a list containing
0544:             * one element - the input throwable.
0545:             * A throwable with one cause will return a list containing
0546:             * two elements. - the input throwable and the cause throwable.
0547:             * A <code>null</code> throwable will return a list of size zero.</p>
0548:             *
0549:             * <p>This method handles recursive cause structures that might
0550:             * otherwise cause infinite loops. The cause chain is processed until
0551:             * the end is reached, or until the next item in the chain is already
0552:             * in the result set.</p>
0553:             *
0554:             * @param throwable  the throwable to inspect, may be null
0555:             * @return the list of throwables, never null
0556:             * @since Commons Lang 2.2
0557:             */
0558:            public static List getThrowableList(Throwable throwable) {
0559:                List list = new ArrayList();
0560:                while (throwable != null && list.contains(throwable) == false) {
0561:                    list.add(throwable);
0562:                    throwable = ExceptionUtils.getCause(throwable);
0563:                }
0564:                return list;
0565:            }
0566:
0567:            //-----------------------------------------------------------------------
0568:            /**
0569:             * <p>Returns the (zero based) index of the first <code>Throwable</code>
0570:             * that matches the specified class (exactly) in the exception chain.
0571:             * Subclasses of the specified class do not match - see
0572:             * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
0573:             *
0574:             * <p>A <code>null</code> throwable returns <code>-1</code>.
0575:             * A <code>null</code> type returns <code>-1</code>.
0576:             * No match in the chain returns <code>-1</code>.</p>
0577:             *
0578:             * @param throwable  the throwable to inspect, may be null
0579:             * @param clazz  the class to search for, subclasses do not match, null returns -1
0580:             * @return the index into the throwable chain, -1 if no match or null input
0581:             */
0582:            public static int indexOfThrowable(Throwable throwable, Class clazz) {
0583:                return indexOf(throwable, clazz, 0, false);
0584:            }
0585:
0586:            /**
0587:             * <p>Returns the (zero based) index of the first <code>Throwable</code>
0588:             * that matches the specified type in the exception chain from
0589:             * a specified index.
0590:             * Subclasses of the specified class do not match - see
0591:             * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
0592:             *
0593:             * <p>A <code>null</code> throwable returns <code>-1</code>.
0594:             * A <code>null</code> type returns <code>-1</code>.
0595:             * No match in the chain returns <code>-1</code>.
0596:             * A negative start index is treated as zero.
0597:             * A start index greater than the number of throwables returns <code>-1</code>.</p>
0598:             *
0599:             * @param throwable  the throwable to inspect, may be null
0600:             * @param clazz  the class to search for, subclasses do not match, null returns -1
0601:             * @param fromIndex  the (zero based) index of the starting position,
0602:             *  negative treated as zero, larger than chain size returns -1
0603:             * @return the index into the throwable chain, -1 if no match or null input
0604:             */
0605:            public static int indexOfThrowable(Throwable throwable,
0606:                    Class clazz, int fromIndex) {
0607:                return indexOf(throwable, clazz, fromIndex, false);
0608:            }
0609:
0610:            //-----------------------------------------------------------------------
0611:            /**
0612:             * <p>Returns the (zero based) index of the first <code>Throwable</code>
0613:             * that matches the specified class or subclass in the exception chain.
0614:             * Subclasses of the specified class do match - see
0615:             * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
0616:             *
0617:             * <p>A <code>null</code> throwable returns <code>-1</code>.
0618:             * A <code>null</code> type returns <code>-1</code>.
0619:             * No match in the chain returns <code>-1</code>.</p>
0620:             *
0621:             * @param throwable  the throwable to inspect, may be null
0622:             * @param type  the type to search for, subclasses match, null returns -1
0623:             * @return the index into the throwable chain, -1 if no match or null input
0624:             * @since 2.1
0625:             */
0626:            public static int indexOfType(Throwable throwable, Class type) {
0627:                return indexOf(throwable, type, 0, true);
0628:            }
0629:
0630:            /**
0631:             * <p>Returns the (zero based) index of the first <code>Throwable</code>
0632:             * that matches the specified type in the exception chain from
0633:             * a specified index.
0634:             * Subclasses of the specified class do match - see
0635:             * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
0636:             *
0637:             * <p>A <code>null</code> throwable returns <code>-1</code>.
0638:             * A <code>null</code> type returns <code>-1</code>.
0639:             * No match in the chain returns <code>-1</code>.
0640:             * A negative start index is treated as zero.
0641:             * A start index greater than the number of throwables returns <code>-1</code>.</p>
0642:             *
0643:             * @param throwable  the throwable to inspect, may be null
0644:             * @param type  the type to search for, subclasses match, null returns -1
0645:             * @param fromIndex  the (zero based) index of the starting position,
0646:             *  negative treated as zero, larger than chain size returns -1
0647:             * @return the index into the throwable chain, -1 if no match or null input
0648:             * @since 2.1
0649:             */
0650:            public static int indexOfType(Throwable throwable, Class type,
0651:                    int fromIndex) {
0652:                return indexOf(throwable, type, fromIndex, true);
0653:            }
0654:
0655:            /**
0656:             * <p>Worker method for the <code>indexOfType</code> methods.</p>
0657:             *
0658:             * @param throwable  the throwable to inspect, may be null
0659:             * @param type  the type to search for, subclasses match, null returns -1
0660:             * @param fromIndex  the (zero based) index of the starting position,
0661:             *  negative treated as zero, larger than chain size returns -1
0662:             * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
0663:             * using references
0664:             * @return index of the <code>type</code> within throwables nested withing the specified <code>throwable</code>
0665:             */
0666:            private static int indexOf(Throwable throwable, Class type,
0667:                    int fromIndex, boolean subclass) {
0668:                if (throwable == null || type == null) {
0669:                    return -1;
0670:                }
0671:                if (fromIndex < 0) {
0672:                    fromIndex = 0;
0673:                }
0674:                Throwable[] throwables = ExceptionUtils
0675:                        .getThrowables(throwable);
0676:                if (fromIndex >= throwables.length) {
0677:                    return -1;
0678:                }
0679:                if (subclass) {
0680:                    for (int i = fromIndex; i < throwables.length; i++) {
0681:                        if (type.isAssignableFrom(throwables[i].getClass())) {
0682:                            return i;
0683:                        }
0684:                    }
0685:                } else {
0686:                    for (int i = fromIndex; i < throwables.length; i++) {
0687:                        if (type.equals(throwables[i].getClass())) {
0688:                            return i;
0689:                        }
0690:                    }
0691:                }
0692:                return -1;
0693:            }
0694:
0695:            //-----------------------------------------------------------------------
0696:            /**
0697:             * <p>Prints a compact stack trace for the root cause of a throwable
0698:             * to <code>System.err</code>.</p>
0699:             *
0700:             * <p>The compact stack trace starts with the root cause and prints
0701:             * stack frames up to the place where it was caught and wrapped.
0702:             * Then it prints the wrapped exception and continues with stack frames
0703:             * until the wrapper exception is caught and wrapped again, etc.</p>
0704:             *
0705:             * <p>The output of this method is consistent across JDK versions.
0706:             * Note that this is the opposite order to the JDK1.4 display.</p>
0707:             *
0708:             * <p>The method is equivalent to <code>printStackTrace</code> for throwables
0709:             * that don't have nested causes.</p>
0710:             *
0711:             * @param throwable  the throwable to output
0712:             * @since 2.0
0713:             */
0714:            public static void printRootCauseStackTrace(Throwable throwable) {
0715:                printRootCauseStackTrace(throwable, System.err);
0716:            }
0717:
0718:            /**
0719:             * <p>Prints a compact stack trace for the root cause of a throwable.</p>
0720:             *
0721:             * <p>The compact stack trace starts with the root cause and prints
0722:             * stack frames up to the place where it was caught and wrapped.
0723:             * Then it prints the wrapped exception and continues with stack frames
0724:             * until the wrapper exception is caught and wrapped again, etc.</p>
0725:             *
0726:             * <p>The output of this method is consistent across JDK versions.
0727:             * Note that this is the opposite order to the JDK1.4 display.</p>
0728:             *
0729:             * <p>The method is equivalent to <code>printStackTrace</code> for throwables
0730:             * that don't have nested causes.</p>
0731:             *
0732:             * @param throwable  the throwable to output, may be null
0733:             * @param stream  the stream to output to, may not be null
0734:             * @throws IllegalArgumentException if the stream is <code>null</code>
0735:             * @since 2.0
0736:             */
0737:            public static void printRootCauseStackTrace(Throwable throwable,
0738:                    PrintStream stream) {
0739:                if (throwable == null) {
0740:                    return;
0741:                }
0742:                if (stream == null) {
0743:                    throw new IllegalArgumentException(
0744:                            "The PrintStream must not be null");
0745:                }
0746:                String trace[] = getRootCauseStackTrace(throwable);
0747:                for (int i = 0; i < trace.length; i++) {
0748:                    stream.println(trace[i]);
0749:                }
0750:                stream.flush();
0751:            }
0752:
0753:            /**
0754:             * <p>Prints a compact stack trace for the root cause of a throwable.</p>
0755:             *
0756:             * <p>The compact stack trace starts with the root cause and prints
0757:             * stack frames up to the place where it was caught and wrapped.
0758:             * Then it prints the wrapped exception and continues with stack frames
0759:             * until the wrapper exception is caught and wrapped again, etc.</p>
0760:             *
0761:             * <p>The output of this method is consistent across JDK versions.
0762:             * Note that this is the opposite order to the JDK1.4 display.</p>
0763:             *
0764:             * <p>The method is equivalent to <code>printStackTrace</code> for throwables
0765:             * that don't have nested causes.</p>
0766:             *
0767:             * @param throwable  the throwable to output, may be null
0768:             * @param writer  the writer to output to, may not be null
0769:             * @throws IllegalArgumentException if the writer is <code>null</code>
0770:             * @since 2.0
0771:             */
0772:            public static void printRootCauseStackTrace(Throwable throwable,
0773:                    PrintWriter writer) {
0774:                if (throwable == null) {
0775:                    return;
0776:                }
0777:                if (writer == null) {
0778:                    throw new IllegalArgumentException(
0779:                            "The PrintWriter must not be null");
0780:                }
0781:                String trace[] = getRootCauseStackTrace(throwable);
0782:                for (int i = 0; i < trace.length; i++) {
0783:                    writer.println(trace[i]);
0784:                }
0785:                writer.flush();
0786:            }
0787:
0788:            //-----------------------------------------------------------------------
0789:            /**
0790:             * <p>Creates a compact stack trace for the root cause of the supplied
0791:             * <code>Throwable</code>.</p>
0792:             *
0793:             * <p>The output of this method is consistent across JDK versions.
0794:             * It consists of the root exception followed by each of its wrapping
0795:             * exceptions separated by '[wrapped]'. Note that this is the opposite
0796:             * order to the JDK1.4 display.</p>
0797:             *
0798:             * @param throwable  the throwable to examine, may be null
0799:             * @return an array of stack trace frames, never null
0800:             * @since 2.0
0801:             */
0802:            public static String[] getRootCauseStackTrace(Throwable throwable) {
0803:                if (throwable == null) {
0804:                    return ArrayUtils.EMPTY_STRING_ARRAY;
0805:                }
0806:                Throwable throwables[] = getThrowables(throwable);
0807:                int count = throwables.length;
0808:                ArrayList frames = new ArrayList();
0809:                List nextTrace = getStackFrameList(throwables[count - 1]);
0810:                for (int i = count; --i >= 0;) {
0811:                    List trace = nextTrace;
0812:                    if (i != 0) {
0813:                        nextTrace = getStackFrameList(throwables[i - 1]);
0814:                        removeCommonFrames(trace, nextTrace);
0815:                    }
0816:                    if (i == count - 1) {
0817:                        frames.add(throwables[i].toString());
0818:                    } else {
0819:                        frames.add(WRAPPED_MARKER + throwables[i].toString());
0820:                    }
0821:                    for (int j = 0; j < trace.size(); j++) {
0822:                        frames.add(trace.get(j));
0823:                    }
0824:                }
0825:                return (String[]) frames.toArray(new String[0]);
0826:            }
0827:
0828:            /**
0829:             * <p>Removes common frames from the cause trace given the two stack traces.</p>
0830:             *
0831:             * @param causeFrames  stack trace of a cause throwable
0832:             * @param wrapperFrames  stack trace of a wrapper throwable
0833:             * @throws IllegalArgumentException if either argument is null
0834:             * @since 2.0
0835:             */
0836:            public static void removeCommonFrames(List causeFrames,
0837:                    List wrapperFrames) {
0838:                if (causeFrames == null || wrapperFrames == null) {
0839:                    throw new IllegalArgumentException(
0840:                            "The List must not be null");
0841:                }
0842:                int causeFrameIndex = causeFrames.size() - 1;
0843:                int wrapperFrameIndex = wrapperFrames.size() - 1;
0844:                while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
0845:                    // Remove the frame from the cause trace if it is the same
0846:                    // as in the wrapper trace
0847:                    String causeFrame = (String) causeFrames
0848:                            .get(causeFrameIndex);
0849:                    String wrapperFrame = (String) wrapperFrames
0850:                            .get(wrapperFrameIndex);
0851:                    if (causeFrame.equals(wrapperFrame)) {
0852:                        causeFrames.remove(causeFrameIndex);
0853:                    }
0854:                    causeFrameIndex--;
0855:                    wrapperFrameIndex--;
0856:                }
0857:            }
0858:
0859:            //-----------------------------------------------------------------------
0860:            /**
0861:             * <p>A way to get the entire nested stack-trace of an throwable.</p>
0862:             *
0863:             * <p>The result of this method is highly dependent on the JDK version
0864:             * and whether the exceptions override printStackTrace or not.</p>
0865:             *
0866:             * @param throwable  the <code>Throwable</code> to be examined
0867:             * @return the nested stack trace, with the root cause first
0868:             * @since 2.0
0869:             */
0870:            public static String getFullStackTrace(Throwable throwable) {
0871:                StringWriter sw = new StringWriter();
0872:                PrintWriter pw = new PrintWriter(sw, true);
0873:                Throwable[] ts = getThrowables(throwable);
0874:                for (int i = 0; i < ts.length; i++) {
0875:                    ts[i].printStackTrace(pw);
0876:                    if (isNestedThrowable(ts[i])) {
0877:                        break;
0878:                    }
0879:                }
0880:                return sw.getBuffer().toString();
0881:            }
0882:
0883:            //-----------------------------------------------------------------------
0884:            /**
0885:             * <p>Gets the stack trace from a Throwable as a String.</p>
0886:             *
0887:             * <p>The result of this method vary by JDK version as this method
0888:             * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
0889:             * On JDK1.3 and earlier, the cause exception will not be shown
0890:             * unless the specified throwable alters printStackTrace.</p>
0891:             *
0892:             * @param throwable  the <code>Throwable</code> to be examined
0893:             * @return the stack trace as generated by the exception's
0894:             *  <code>printStackTrace(PrintWriter)</code> method
0895:             */
0896:            public static String getStackTrace(Throwable throwable) {
0897:                StringWriter sw = new StringWriter();
0898:                PrintWriter pw = new PrintWriter(sw, true);
0899:                throwable.printStackTrace(pw);
0900:                return sw.getBuffer().toString();
0901:            }
0902:
0903:            /**
0904:             * <p>Captures the stack trace associated with the specified
0905:             * <code>Throwable</code> object, decomposing it into a list of
0906:             * stack frames.</p>
0907:             *
0908:             * <p>The result of this method vary by JDK version as this method
0909:             * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
0910:             * On JDK1.3 and earlier, the cause exception will not be shown
0911:             * unless the specified throwable alters printStackTrace.</p>
0912:             *
0913:             * @param throwable  the <code>Throwable</code> to examine, may be null
0914:             * @return an array of strings describing each stack frame, never null
0915:             */
0916:            public static String[] getStackFrames(Throwable throwable) {
0917:                if (throwable == null) {
0918:                    return ArrayUtils.EMPTY_STRING_ARRAY;
0919:                }
0920:                return getStackFrames(getStackTrace(throwable));
0921:            }
0922:
0923:            //-----------------------------------------------------------------------
0924:            /**
0925:             * <p>Returns an array where each element is a line from the argument.</p>
0926:             *
0927:             * <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
0928:             *
0929:             * <p>Functionality shared between the
0930:             * <code>getStackFrames(Throwable)</code> methods of this and the
0931:             * {@link org.apache.commons.lang.exception.NestableDelegate} classes.</p>
0932:             *
0933:             * @param stackTrace  a stack trace String
0934:             * @return an array where each element is a line from the argument
0935:             */
0936:            static String[] getStackFrames(String stackTrace) {
0937:                String linebreak = SystemUtils.LINE_SEPARATOR;
0938:                StringTokenizer frames = new StringTokenizer(stackTrace,
0939:                        linebreak);
0940:                List list = new ArrayList();
0941:                while (frames.hasMoreTokens()) {
0942:                    list.add(frames.nextToken());
0943:                }
0944:                return toArray(list);
0945:            }
0946:
0947:            /**
0948:             * <p>Produces a <code>List</code> of stack frames - the message
0949:             * is not included. Only the trace of the specified exception is
0950:             * returned, any caused by trace is stripped.</p>
0951:             *
0952:             * <p>This works in most cases - it will only fail if the exception
0953:             * message contains a line that starts with:
0954:             * <code>&quot;&nbsp;&nbsp;&nbsp;at&quot;.</code></p>
0955:             * 
0956:             * @param t is any throwable
0957:             * @return List of stack frames
0958:             */
0959:            static List getStackFrameList(Throwable t) {
0960:                String stackTrace = getStackTrace(t);
0961:                String linebreak = SystemUtils.LINE_SEPARATOR;
0962:                StringTokenizer frames = new StringTokenizer(stackTrace,
0963:                        linebreak);
0964:                List list = new ArrayList();
0965:                boolean traceStarted = false;
0966:                while (frames.hasMoreTokens()) {
0967:                    String token = frames.nextToken();
0968:                    // Determine if the line starts with <whitespace>at
0969:                    int at = token.indexOf("at");
0970:                    if (at != -1 && token.substring(0, at).trim().length() == 0) {
0971:                        traceStarted = true;
0972:                        list.add(token);
0973:                    } else if (traceStarted) {
0974:                        break;
0975:                    }
0976:                }
0977:                return list;
0978:            }
0979:
0980:            //-----------------------------------------------------------------------
0981:            /**
0982:             * Gets a short message summarising the exception.
0983:             * <p>
0984:             * The message returned is of the form
0985:             * {ClassNameWithoutPackage}: {ThrowableMessage}
0986:             *
0987:             * @param th  the throwable to get a message for, null returns empty string
0988:             * @return the message, non-null
0989:             * @since Commons Lang 2.2
0990:             */
0991:            public static String getMessage(Throwable th) {
0992:                if (th == null) {
0993:                    return "";
0994:                }
0995:                String clsName = ClassUtils.getShortClassName(th, null);
0996:                String msg = th.getMessage();
0997:                return clsName + ": " + StringUtils.defaultString(msg);
0998:            }
0999:
1000:            //-----------------------------------------------------------------------
1001:            /**
1002:             * Gets a short message summarising the root cause exception.
1003:             * <p>
1004:             * The message returned is of the form
1005:             * {ClassNameWithoutPackage}: {ThrowableMessage}
1006:             *
1007:             * @param th  the throwable to get a message for, null returns empty string
1008:             * @return the message, non-null
1009:             * @since Commons Lang 2.2
1010:             */
1011:            public static String getRootCauseMessage(Throwable th) {
1012:                Throwable root = ExceptionUtils.getRootCause(th);
1013:                root = (root == null ? th : root);
1014:                return getMessage(root);
1015:            }
1016:
1017:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.