1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.apache.commons.httpclient.util;
30
31 import java.io.InterruptedIOException;
32 import java.lang.reflect.Method;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 /***
38 * The home for utility methods that handle various exception-related tasks.
39 *
40 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
41 * @author <a href="mailto:laura@lwerner.org">Laura Werner</a>
42 *
43 * @since 3.0
44 */
45 public class ExceptionUtil {
46
47 /*** Log object for this class. */
48 private static final Log LOG = LogFactory.getLog(ExceptionUtil.class);
49
50 /*** A reference to Throwable's initCause method, or null if it's not there in this JVM */
51 static private final Method INIT_CAUSE_METHOD = getInitCauseMethod();
52
53 /*** A reference to SocketTimeoutExceptionClass class, or null if it's not there in this JVM */
54 static private final Class SOCKET_TIMEOUT_CLASS = SocketTimeoutExceptionClass();
55
56 /***
57 * Returns a <code>Method<code> allowing access to
58 * {@link Throwable.initCause(Throwable) initCause} method of {@link Throwable},
59 * or <code>null</code> if the method
60 * does not exist.
61 *
62 * @return A <code>Method<code> for <code>Throwable.initCause</code>, or
63 * <code>null</code> if unavailable.
64 */
65 static private Method getInitCauseMethod() {
66 try {
67 Class[] paramsClasses = new Class[] { Throwable.class };
68 return Throwable.class.getMethod("initCause", paramsClasses);
69 } catch (NoSuchMethodException e) {
70 return null;
71 }
72 }
73
74 /***
75 * Returns <code>SocketTimeoutExceptionClass<code> or <code>null</code> if the class
76 * does not exist.
77 *
78 * @return <code>SocketTimeoutExceptionClass<code>, or <code>null</code> if unavailable.
79 */
80 static private Class SocketTimeoutExceptionClass() {
81 try {
82 return Class.forName("java.net.SocketTimeoutException");
83 } catch (ClassNotFoundException e) {
84 return null;
85 }
86 }
87
88 /***
89 * If we're running on JDK 1.4 or later, initialize the cause for the given throwable.
90 *
91 * @param throwable The throwable.
92 * @param cause The cause of the throwable.
93 */
94 public static void initCause(Throwable throwable, Throwable cause) {
95 if (INIT_CAUSE_METHOD != null) {
96 try {
97 INIT_CAUSE_METHOD.invoke(throwable, new Object[] { cause });
98 } catch (Exception e) {
99 LOG.warn("Exception invoking Throwable.initCause", e);
100 }
101 }
102 }
103
104 /***
105 * If SocketTimeoutExceptionClass is defined, returns <tt>true</tt> only if the
106 * exception is an instance of SocketTimeoutExceptionClass. If
107 * SocketTimeoutExceptionClass is undefined, always returns <tt>true</tt>.
108 *
109 * @param e an instance of InterruptedIOException class.
110 *
111 * @return <tt>true</tt> if the exception signals socket timeout, <tt>false</tt>
112 * otherwise.
113 */
114 public static boolean isSocketTimeoutException(final InterruptedIOException e) {
115 if (SOCKET_TIMEOUT_CLASS != null) {
116 return SOCKET_TIMEOUT_CLASS.isInstance(e);
117 } else {
118 return true;
119 }
120 }
121 }