1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package javax.jdo;
24
25 import javax.jdo.spi.I18NHelper;
26
27 /** This is the root of all JDO Exceptions. It contains an optional detail
28 * message, an optional nested <code>Throwable</code> array and an optional failed object.
29 * @author Craig Russell
30 * @version 1.0.2
31 */
32 public class JDOException extends java.lang.RuntimeException {
33
34 /** This exception was generated because of an exception in the runtime library.
35 * @serial the nested <code>Throwable</code> array
36 */
37 Throwable[] nested;
38
39 /** This exception may be the result of incorrect parameters supplied
40 * to an API. This is the object from which the user can determine
41 * the cause of the problem.
42 * @serial the failed <code>Object</code>
43 */
44 Object failed;
45
46 /** The Internationalization message helper.
47 */
48 private static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle");
49
50 /** Flag indicating whether printStackTrace is being executed.
51 */
52 private boolean inPrintStackTrace = false;
53
54 /**
55 * Constructs a new <code>JDOException</code> without a detail message.
56 */
57 public JDOException() {
58 }
59
60
61 /**
62 * Constructs a new <code>JDOException</code> with the specified detail message.
63 * @param msg the detail message.
64 */
65 public JDOException(String msg) {
66 super(msg);
67 }
68
69 /** Constructs a new <code>JDOException</code> with the specified detail message
70 * and nested <code>Throwable</code>s.
71 * @param msg the detail message.
72 * @param nested the nested <code>Throwable[]</code>.
73 */
74 public JDOException(String msg, Throwable[] nested) {
75 super(msg);
76 this.nested = nested;
77 }
78
79 /** Constructs a new <code>JDOException</code> with the specified detail message
80 * and nested <code>Throwable</code>.
81 * @param msg the detail message.
82 * @param nested the nested <code>Throwable</code>.
83 */
84 public JDOException(String msg, Throwable nested) {
85 super(msg);
86 this.nested = new Throwable[] {nested};
87 }
88
89 /** Constructs a new <code>JDOException</code> with the specified detail message
90 * and failed object.
91 * @param msg the detail message.
92 * @param failed the failed object.
93 */
94 public JDOException(String msg, Object failed) {
95 super(msg);
96 this.failed = failed;
97 }
98
99 /** Constructs a new <code>JDOException</code> with the specified detail message,
100 * nested <code>Throwable</code>s, and failed object.
101 * @param msg the detail message.
102 * @param nested the nested <code>Throwable[]</code>.
103 * @param failed the failed object.
104 */
105 public JDOException(String msg, Throwable[] nested, Object failed) {
106 super(msg);
107 this.nested = nested;
108 this.failed = failed;
109 }
110
111 /** Constructs a new <code>JDOException</code> with the specified detail message,
112 * nested <code>Throwable</code>, and failed object.
113 * @param msg the detail message.
114 * @param nested the nested <code>Throwable</code>.
115 * @param failed the failed object.
116 */
117 public JDOException(String msg, Throwable nested, Object failed) {
118 super(msg);
119 this.nested = new Throwable[] {nested};
120 this.failed = failed;
121 }
122
123 /** The exception may include a failed object.
124 * @return the failed object.
125 */
126 public Object getFailedObject() {
127 return failed;
128 }
129
130 /** The exception may have been caused by multiple exceptions in the runtime.
131 * If multiple objects caused the problem, each failed object will have
132 * its own <code>Exception</code>.
133 * @return the nested Throwable array.
134 */
135 public Throwable[] getNestedExceptions() {
136 return nested;
137 }
138
139 /** Often there is only one nested exception, and this method returns it.
140 * If there are more than one, then this method returns the first nested
141 * exception. If there is no nested exception, then null is returned.
142 * @return the first or only nested Throwable.
143 * @since 1.0.1
144 */
145 public synchronized Throwable getCause() {
146
147
148
149
150 if (nested == null || nested.length == 0 || inPrintStackTrace) {
151 return null;
152 } else {
153 return nested[0];
154 }
155 }
156
157 /** JDK 1.4 includes a new chaining mechanism for Throwable, but since
158 * JDO has its own "legacy" chaining mechanism, the "standard" mechanism
159 * cannot be used. This method always throws a JDOFatalInternalException.
160 * @param cause ignored.
161 * @return never.
162 */
163 public Throwable initCause(Throwable cause) {
164 throw new JDOFatalInternalException(msg.msg("ERR_CannotInitCause"));
165 }
166
167 /** The <code>String</code> representation includes the name of the class,
168 * the descriptive comment (if any),
169 * the <code>String</code> representation of the failed <code>Object</code> (if any),
170 * and the <code>String</code> representation of the nested <code>Throwable</code>s (if any).
171 * @return the <code>String</code>.
172 */
173 public synchronized String toString() {
174 int len = nested==null?0:nested.length;
175
176 StringBuffer sb = new StringBuffer (10 + 100 * len);
177 sb.append (super.toString());
178
179 if (failed != null) {
180 sb.append ("\n").append (msg.msg ("MSG_FailedObject"));
181 String failedToString = null;
182 try {
183 failedToString = failed.toString();
184 } catch (Exception ex) {
185
186 Object objectId = JDOHelper.getObjectId(failed);
187 if (objectId == null) {
188 failedToString = msg.msg("MSG_ExceptionGettingFailedToString",
189 exceptionToString(ex));
190 }
191 else {
192
193 String objectIdToString = null;
194 try {
195 objectIdToString = objectId.toString();
196 }
197 catch (Exception ex2) {
198 objectIdToString = exceptionToString(ex2);
199 }
200 failedToString = msg.msg("MSG_ExceptionGettingFailedToStringObjectId",
201 exceptionToString(ex), objectIdToString);
202 }
203 }
204 sb.append (failedToString);
205 }
206
207
208 if (len > 0 && !inPrintStackTrace) {
209 sb.append ("\n").append (msg.msg ("MSG_NestedThrowables")).append ("\n");
210 Throwable exception = nested[0];
211 sb.append (exception==null?"null":exception.toString());
212 for (int i=1; i<len; ++i) {
213 sb.append ("\n");
214 exception = nested[i];
215 sb.append (exception==null?"null":exception.toString());
216 }
217 }
218 return sb.toString();
219 }
220
221 /**
222 * Prints this <code>JDOException</code> and its backtrace to the
223 * standard error output.
224 * Print nested Throwables' stack trace as well.
225 */
226 public void printStackTrace() {
227 printStackTrace (System.err);
228 }
229
230 /**
231 * Prints this <code>JDOException</code> and its backtrace to the
232 * specified print stream.
233 * Print nested Throwables' stack trace as well.
234 * @param s <code>PrintStream</code> to use for output
235 */
236 public synchronized void printStackTrace(java.io.PrintStream s) {
237 int len = nested==null?0:nested.length;
238 synchronized (s) {
239 inPrintStackTrace = true;
240 super.printStackTrace(s);
241 if (len > 0) {
242 s.println (msg.msg ("MSG_NestedThrowablesStackTrace"));
243 for (int i=0; i<len; ++i) {
244 Throwable exception = nested[i];
245 if (exception != null) {
246 exception.printStackTrace(s);
247 }
248 }
249 }
250 inPrintStackTrace = false;
251 }
252 }
253
254 /**
255 * Prints this <code>JDOException</code> and its backtrace to the specified
256 * print writer.
257 * Print nested Throwables' stack trace as well.
258 * @param s <code>PrintWriter</code> to use for output
259 */
260 public synchronized void printStackTrace(java.io.PrintWriter s) {
261 int len = nested==null?0:nested.length;
262 synchronized (s) {
263 inPrintStackTrace = true;
264 super.printStackTrace(s);
265 if (len > 0) {
266 s.println (msg.msg ("MSG_NestedThrowablesStackTrace"));
267 for (int i=0; i<len; ++i) {
268 Throwable exception = nested[i];
269 if (exception != null) {
270 exception.printStackTrace(s);
271 }
272 }
273 }
274 inPrintStackTrace = false;
275 }
276 }
277
278 /**
279 * Helper method returning a short description of the exception passed
280 * as an argument. The returned string has the format defined by
281 * Throwable.toString. If the exception has a non-null detail message
282 * string, then it returns the name of exception class concatenated
283 * with ": " concatenated with the detailed message. Otherwise it
284 * returns the name of exception class.
285 * @param ex the exception to be represented.
286 * @return a string representation of the exception passed as an argument.
287 */
288 private static String exceptionToString(Exception ex)
289 {
290 if (ex == null) return null;
291 String s = ex.getClass().getName();
292 String message = ex.getMessage();
293 return (message != null) ? (s + ": " + message) : s;
294 }
295 }
296