Skip to content

Commit fca9154

Browse files
committed
Second part of #668 refactoring
1 parent a2baece commit fca9154

File tree

1 file changed

+137
-2
lines changed

1 file changed

+137
-2
lines changed

src/main/java/tools/jackson/core/JacksonException.java

+137-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package tools.jackson.core;
22

3+
import java.io.Closeable;
34
import java.io.Serializable;
5+
import java.lang.reflect.InvocationTargetException;
46
import java.util.Collection;
7+
import java.util.LinkedList;
58
import java.util.Objects;
69

710
/**
@@ -10,11 +13,17 @@
1013
* Note that in Jackson 2.x this exception extended {@link java.io.IOException}
1114
* but in 3.x {@link RuntimeException}
1215
*/
13-
public abstract class JacksonException
16+
public class JacksonException
1417
extends RuntimeException
1518
{
1619
private final static long serialVersionUID = 3L; // eclipse complains otherwise
1720

21+
/**
22+
* Let's limit length of reference chain, to limit damage in cases
23+
* of infinite recursion.
24+
*/
25+
private final static int MAX_REFS_TO_LIST = 1000;
26+
1827
/**
1928
* Simple bean class used to contain references. References
2029
* can be added to indicate execution/reference path that
@@ -151,6 +160,20 @@ Object writeReplace() {
151160

152161
protected JsonLocation _location;
153162

163+
/**
164+
* Path through which problem that triggering throwing of
165+
* this exception was reached.
166+
*/
167+
protected LinkedList<Reference> _path;
168+
169+
/**
170+
* Underlying processor ({@link JsonParser} or {@link JsonGenerator}),
171+
* if known.
172+
*<p>
173+
* NOTE: typically not serializable hence <code>transient</code>
174+
*/
175+
protected transient Closeable _processor;
176+
154177
/*
155178
/**********************************************************************
156179
/* Life-cycle
@@ -192,6 +215,116 @@ public JacksonException clearLocation() {
192215
return this;
193216
}
194217

218+
/*
219+
/**********************************************************************
220+
/* Life-cycle: more advanced factory-like methods
221+
/**********************************************************************
222+
*/
223+
224+
/**
225+
* Method that can be called to either create a new DatabindException
226+
* (if underlying exception is not a DatabindException), or augment
227+
* given exception with given path/reference information.
228+
*
229+
* This version of method is called when the reference is through a
230+
* non-indexed object, such as a Map or POJO/bean.
231+
*/
232+
public static JacksonException wrapWithPath(Throwable src, Object refFrom,
233+
String refPropertyName) {
234+
return wrapWithPath(src, new Reference(refFrom, refPropertyName));
235+
}
236+
237+
/**
238+
* Method that can be called to either create a new DatabindException
239+
* (if underlying exception is not a DatabindException), or augment
240+
* given exception with given path/reference information.
241+
*
242+
* This version of method is called when the reference is through an
243+
* index, which happens with arrays and Collections.
244+
*/
245+
public static JacksonException wrapWithPath(Throwable src, Object refFrom, int index) {
246+
return wrapWithPath(src, new Reference(refFrom, index));
247+
}
248+
249+
/**
250+
* Method that can be called to either create a new DatabindException
251+
* (if underlying exception is not a DatabindException), or augment
252+
* given exception with given path/reference information.
253+
*/
254+
@SuppressWarnings("resource")
255+
public static JacksonException wrapWithPath(Throwable src, Reference ref)
256+
{
257+
JacksonException jme;
258+
if (src instanceof JacksonException) {
259+
jme = (JacksonException) src;
260+
} else {
261+
// [databind#2128]: try to avoid duplication
262+
String msg = _exceptionMessage(src);
263+
// Let's use a more meaningful placeholder if all we have is null
264+
if (msg == null || msg.isEmpty()) {
265+
msg = "(was "+src.getClass().getName()+")";
266+
}
267+
// 17-Aug-2015, tatu: Let's also pass the processor (parser/generator) along
268+
Closeable proc = null;
269+
if (src instanceof JacksonException) {
270+
Object proc0 = ((JacksonException) src).processor();
271+
if (proc0 instanceof Closeable) {
272+
proc = (Closeable) proc0;
273+
}
274+
}
275+
jme = new JacksonException(msg, src);
276+
jme._processor = proc;
277+
}
278+
jme.prependPath(ref);
279+
return jme;
280+
}
281+
282+
private static String _exceptionMessage(Throwable t) {
283+
if (t instanceof JacksonException) {
284+
return ((JacksonException) t).getOriginalMessage();
285+
}
286+
if (t instanceof InvocationTargetException && t.getCause() != null) {
287+
return t.getCause().getMessage();
288+
}
289+
return t.getMessage();
290+
}
291+
292+
/*
293+
/**********************************************************************
294+
/* Life-cycle: information augmentation (cannot use factory style, alas)
295+
/**********************************************************************
296+
*/
297+
298+
/**
299+
* Method called to prepend a reference information in front of
300+
* current path
301+
*/
302+
public JacksonException prependPath(Object referrer, String propertyName) {
303+
return prependPath(new Reference(referrer, propertyName));
304+
}
305+
306+
/**
307+
* Method called to prepend a reference information in front of
308+
* current path
309+
*/
310+
public JacksonException prependPath(Object referrer, int index) {
311+
return prependPath(new Reference(referrer, index));
312+
}
313+
314+
public JacksonException prependPath(Reference r)
315+
{
316+
if (_path == null) {
317+
_path = new LinkedList<Reference>();
318+
}
319+
// Also: let's not increase without bounds. Could choose either
320+
// head or tail; tail is easier (no need to ever remove), as
321+
// well as potentially more useful so let's use it:
322+
if (_path.size() < MAX_REFS_TO_LIST) {
323+
_path.addFirst(r);
324+
}
325+
return this;
326+
}
327+
195328
/*
196329
/**********************************************************************
197330
/* Extended API
@@ -238,7 +371,9 @@ public JacksonException clearLocation() {
238371
*
239372
* @return Originating processor, if available; {@code null} if not.
240373
*/
241-
public abstract Object processor();
374+
public Object processor() {
375+
return _processor;
376+
}
242377

243378
/*
244379
/**********************************************************************

0 commit comments

Comments
 (0)