• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.deser.std;
2 
3 import java.io.IOException;
4 import java.lang.reflect.InvocationTargetException;
5 
6 import com.fasterxml.jackson.databind.*;
7 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
8 import com.fasterxml.jackson.databind.deser.*;
9 import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
10 import com.fasterxml.jackson.databind.util.ClassUtil;
11 import java.math.BigDecimal;
12 import java.math.BigInteger;
13 
14 /**
15  * Default {@link ValueInstantiator} implementation, which supports
16  * Creator methods that can be indicated by standard Jackson
17  * annotations.
18  */
19 @JacksonStdImpl
20 public class StdValueInstantiator
21     extends ValueInstantiator
22     implements java.io.Serializable
23 {
24     private static final long serialVersionUID = 1L;
25 
26     /**
27      * Type of values that are instantiated; used
28      * for error reporting purposes.
29      */
30     protected final String _valueTypeDesc;
31 
32     /**
33      * @since 2.8
34      */
35     protected final Class<?> _valueClass;
36 
37     // // // Default (no-args) construction
38 
39     /**
40      * Default (no-argument) constructor to use for instantiation
41      * (with {@link #createUsingDefault})
42      */
43     protected AnnotatedWithParams _defaultCreator;
44 
45     // // // With-args (property-based) construction
46 
47     protected AnnotatedWithParams _withArgsCreator;
48     protected SettableBeanProperty[] _constructorArguments;
49 
50     // // // Delegate construction
51 
52     protected JavaType _delegateType;
53     protected AnnotatedWithParams _delegateCreator;
54     protected SettableBeanProperty[] _delegateArguments;
55 
56     // // // Array delegate construction
57 
58     protected JavaType _arrayDelegateType;
59     protected AnnotatedWithParams _arrayDelegateCreator;
60     protected SettableBeanProperty[] _arrayDelegateArguments;
61 
62     // // // Scalar construction
63 
64     protected AnnotatedWithParams _fromStringCreator;
65     protected AnnotatedWithParams _fromIntCreator;
66     protected AnnotatedWithParams _fromLongCreator;
67     protected AnnotatedWithParams _fromBigIntegerCreator;
68     protected AnnotatedWithParams _fromDoubleCreator;
69     protected AnnotatedWithParams _fromBigDecimalCreator;
70     protected AnnotatedWithParams _fromBooleanCreator;
71 
72     /*
73     /**********************************************************
74     /* Life-cycle
75     /**********************************************************
76      */
77 
78     /**
79      * @deprecated Since 2.7 use constructor that takes {@link JavaType} instead
80      */
81     @Deprecated
StdValueInstantiator(DeserializationConfig config, Class<?> valueType)82     public StdValueInstantiator(DeserializationConfig config, Class<?> valueType) {
83         _valueTypeDesc = ClassUtil.nameOf(valueType);
84         _valueClass = (valueType == null) ? Object.class : valueType;
85     }
86 
StdValueInstantiator(DeserializationConfig config, JavaType valueType)87     public StdValueInstantiator(DeserializationConfig config, JavaType valueType) {
88         _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.toString();
89         _valueClass = (valueType == null) ? Object.class : valueType.getRawClass();
90     }
91 
92     /**
93      * Copy-constructor that sub-classes can use when creating new instances
94      * by fluent-style construction
95      */
StdValueInstantiator(StdValueInstantiator src)96     protected StdValueInstantiator(StdValueInstantiator src)
97     {
98         _valueTypeDesc = src._valueTypeDesc;
99         _valueClass = src._valueClass;
100 
101         _defaultCreator = src._defaultCreator;
102 
103         _constructorArguments = src._constructorArguments;
104         _withArgsCreator = src._withArgsCreator;
105 
106         _delegateType = src._delegateType;
107         _delegateCreator = src._delegateCreator;
108         _delegateArguments = src._delegateArguments;
109 
110         _arrayDelegateType = src._arrayDelegateType;
111         _arrayDelegateCreator = src._arrayDelegateCreator;
112         _arrayDelegateArguments = src._arrayDelegateArguments;
113 
114         _fromStringCreator = src._fromStringCreator;
115         _fromIntCreator = src._fromIntCreator;
116         _fromLongCreator = src._fromLongCreator;
117         _fromBigIntegerCreator = src._fromBigIntegerCreator;
118         _fromDoubleCreator = src._fromDoubleCreator;
119         _fromBigDecimalCreator = src._fromBigDecimalCreator;
120         _fromBooleanCreator = src._fromBooleanCreator;
121     }
122 
123     /**
124      * Method for setting properties related to instantiating values
125      * from JSON Object. We will choose basically only one approach (out of possible
126      * three), and clear other properties
127      */
configureFromObjectSettings(AnnotatedWithParams defaultCreator, AnnotatedWithParams delegateCreator, JavaType delegateType, SettableBeanProperty[] delegateArgs, AnnotatedWithParams withArgsCreator, SettableBeanProperty[] constructorArgs)128     public void configureFromObjectSettings(AnnotatedWithParams defaultCreator,
129             AnnotatedWithParams delegateCreator, JavaType delegateType, SettableBeanProperty[] delegateArgs,
130             AnnotatedWithParams withArgsCreator, SettableBeanProperty[] constructorArgs)
131     {
132         _defaultCreator = defaultCreator;
133         _delegateCreator = delegateCreator;
134         _delegateType = delegateType;
135         _delegateArguments = delegateArgs;
136         _withArgsCreator = withArgsCreator;
137         _constructorArguments = constructorArgs;
138     }
139 
configureFromArraySettings( AnnotatedWithParams arrayDelegateCreator, JavaType arrayDelegateType, SettableBeanProperty[] arrayDelegateArgs)140     public void configureFromArraySettings(
141             AnnotatedWithParams arrayDelegateCreator,
142             JavaType arrayDelegateType,
143             SettableBeanProperty[] arrayDelegateArgs)
144     {
145         _arrayDelegateCreator = arrayDelegateCreator;
146         _arrayDelegateType = arrayDelegateType;
147         _arrayDelegateArguments = arrayDelegateArgs;
148     }
149 
configureFromStringCreator(AnnotatedWithParams creator)150     public void configureFromStringCreator(AnnotatedWithParams creator) {
151         _fromStringCreator = creator;
152     }
153 
configureFromIntCreator(AnnotatedWithParams creator)154     public void configureFromIntCreator(AnnotatedWithParams creator) {
155         _fromIntCreator = creator;
156     }
157 
configureFromLongCreator(AnnotatedWithParams creator)158     public void configureFromLongCreator(AnnotatedWithParams creator) {
159         _fromLongCreator = creator;
160     }
161 
configureFromBigIntegerCreator(AnnotatedWithParams creator)162     public void configureFromBigIntegerCreator(AnnotatedWithParams creator) { _fromBigIntegerCreator = creator; }
163 
configureFromDoubleCreator(AnnotatedWithParams creator)164     public void configureFromDoubleCreator(AnnotatedWithParams creator) {
165         _fromDoubleCreator = creator;
166     }
167 
configureFromBigDecimalCreator(AnnotatedWithParams creator)168     public void configureFromBigDecimalCreator(AnnotatedWithParams creator) { _fromBigDecimalCreator = creator; }
169 
configureFromBooleanCreator(AnnotatedWithParams creator)170     public void configureFromBooleanCreator(AnnotatedWithParams creator) {
171         _fromBooleanCreator = creator;
172     }
173 
174     /*
175     /**********************************************************
176     /* Public API implementation; metadata
177     /**********************************************************
178      */
179 
180     @Override
getValueTypeDesc()181     public String getValueTypeDesc() {
182         return _valueTypeDesc;
183     }
184 
185     @Override
getValueClass()186     public Class<?> getValueClass() {
187         return _valueClass;
188     }
189 
190     @Override
canCreateFromString()191     public boolean canCreateFromString() {
192         return (_fromStringCreator != null);
193     }
194 
195     @Override
canCreateFromInt()196     public boolean canCreateFromInt() {
197         return (_fromIntCreator != null);
198     }
199 
200     @Override
canCreateFromLong()201     public boolean canCreateFromLong() {
202         return (_fromLongCreator != null);
203     }
204 
205     @Override
canCreateFromBigInteger()206     public boolean canCreateFromBigInteger() { return _fromBigIntegerCreator != null; }
207 
208     @Override
canCreateFromDouble()209     public boolean canCreateFromDouble() {
210         return (_fromDoubleCreator != null);
211     }
212 
213     @Override
canCreateFromBigDecimal()214     public boolean canCreateFromBigDecimal() { return _fromBigDecimalCreator != null; }
215 
216     @Override
canCreateFromBoolean()217     public boolean canCreateFromBoolean() {
218         return (_fromBooleanCreator != null);
219     }
220 
221     @Override
canCreateUsingDefault()222     public boolean canCreateUsingDefault() {
223         return (_defaultCreator != null);
224     }
225 
226     @Override
canCreateUsingDelegate()227     public boolean canCreateUsingDelegate() {
228         return (_delegateType != null);
229     }
230 
231     @Override
canCreateUsingArrayDelegate()232     public boolean canCreateUsingArrayDelegate() {
233         return (_arrayDelegateType != null);
234     }
235 
236     @Override
canCreateFromObjectWith()237     public boolean canCreateFromObjectWith() {
238         return (_withArgsCreator != null);
239     }
240 
241     @Override
canInstantiate()242     public boolean canInstantiate() {
243         return canCreateUsingDefault()
244                 || canCreateUsingDelegate() || canCreateUsingArrayDelegate()
245                 || canCreateFromObjectWith() || canCreateFromString()
246                 || canCreateFromInt() || canCreateFromLong()
247                 || canCreateFromDouble() || canCreateFromBoolean();
248     }
249 
250     @Override
getDelegateType(DeserializationConfig config)251     public JavaType getDelegateType(DeserializationConfig config) {
252         return _delegateType;
253     }
254 
255     @Override
getArrayDelegateType(DeserializationConfig config)256     public JavaType getArrayDelegateType(DeserializationConfig config) {
257         return _arrayDelegateType;
258     }
259 
260     @Override
getFromObjectArguments(DeserializationConfig config)261     public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) {
262         return _constructorArguments;
263     }
264 
265     /*
266     /**********************************************************
267     /* Public API implementation; instantiation from JSON Object
268     /**********************************************************
269      */
270 
271     @Override
createUsingDefault(DeserializationContext ctxt)272     public Object createUsingDefault(DeserializationContext ctxt) throws IOException
273     {
274         if (_defaultCreator == null) { // sanity-check; caller should check
275             return super.createUsingDefault(ctxt);
276         }
277         try {
278             return _defaultCreator.call();
279         } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions
280             return ctxt.handleInstantiationProblem(_valueClass, null, rewrapCtorProblem(ctxt, e));
281         }
282     }
283 
284     @Override
createFromObjectWith(DeserializationContext ctxt, Object[] args)285     public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException
286     {
287         if (_withArgsCreator == null) { // sanity-check; caller should check
288             return super.createFromObjectWith(ctxt, args);
289         }
290         try {
291             return _withArgsCreator.call(args);
292         } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions
293             return ctxt.handleInstantiationProblem(_valueClass, args, rewrapCtorProblem(ctxt, e));
294         }
295     }
296 
297     @Override
createUsingDelegate(DeserializationContext ctxt, Object delegate)298     public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException
299     {
300         // 04-Oct-2016, tatu: Need delegation to work around [databind#1392]...
301         if (_delegateCreator == null) {
302             if (_arrayDelegateCreator != null) {
303                 return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate);
304             }
305         }
306         return _createUsingDelegate(_delegateCreator, _delegateArguments, ctxt, delegate);
307     }
308 
309     @Override
createUsingArrayDelegate(DeserializationContext ctxt, Object delegate)310     public Object createUsingArrayDelegate(DeserializationContext ctxt, Object delegate) throws IOException
311     {
312         if (_arrayDelegateCreator == null) {
313             if (_delegateCreator != null) { // sanity-check; caller should check
314                 // fallback to the classic delegate creator
315                 return createUsingDelegate(ctxt, delegate);
316             }
317         }
318         return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate);
319     }
320 
321     /*
322     /**********************************************************
323     /* Public API implementation; instantiation from JSON scalars
324     /**********************************************************
325      */
326 
327     @Override
createFromString(DeserializationContext ctxt, String value)328     public Object createFromString(DeserializationContext ctxt, String value) throws IOException
329     {
330         if (_fromStringCreator != null) {
331             try {
332                 return _fromStringCreator.call1(value);
333             } catch (Throwable t) {
334                 return ctxt.handleInstantiationProblem(_fromStringCreator.getDeclaringClass(),
335                         value, rewrapCtorProblem(ctxt, t));
336             }
337         }
338         return super.createFromString(ctxt, value);
339     }
340 
341     @Override
createFromInt(DeserializationContext ctxt, int value)342     public Object createFromInt(DeserializationContext ctxt, int value) throws IOException
343     {
344         // First: "native" int methods work best:
345         if (_fromIntCreator != null) {
346             Object arg = Integer.valueOf(value);
347             try {
348                 return _fromIntCreator.call1(arg);
349             } catch (Throwable t0) {
350                 return ctxt.handleInstantiationProblem(_fromIntCreator.getDeclaringClass(),
351                         arg, rewrapCtorProblem(ctxt, t0));
352             }
353         }
354         // but if not, can do widening conversion
355         if (_fromLongCreator != null) {
356             Object arg = Long.valueOf(value);
357             try {
358                 return _fromLongCreator.call1(arg);
359             } catch (Throwable t0) {
360                 return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
361                         arg, rewrapCtorProblem(ctxt, t0));
362             }
363         }
364 
365         if (_fromBigIntegerCreator != null) {
366             Object arg = BigInteger.valueOf(value);
367             try {
368                 return _fromBigIntegerCreator.call1(arg);
369             } catch (Throwable t0) {
370                 return ctxt.handleInstantiationProblem(_fromBigIntegerCreator.getDeclaringClass(),
371                                                        arg, rewrapCtorProblem(ctxt, t0)
372                 );
373             }
374         }
375 
376         return super.createFromInt(ctxt, value);
377     }
378 
379     @Override
createFromLong(DeserializationContext ctxt, long value)380     public Object createFromLong(DeserializationContext ctxt, long value) throws IOException
381     {
382         if (_fromLongCreator != null) {
383             Object arg = Long.valueOf(value);
384             try {
385                 return _fromLongCreator.call1(arg);
386             } catch (Throwable t0) {
387                 return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
388                                                        arg,
389                                                        rewrapCtorProblem(ctxt, t0)
390                 );
391             }
392         }
393 
394         if (_fromBigIntegerCreator != null) {
395             Object arg = BigInteger.valueOf(value);
396             try {
397                 return _fromBigIntegerCreator.call1(arg);
398             } catch (Throwable t0) {
399                 return ctxt.handleInstantiationProblem(_fromBigIntegerCreator.getDeclaringClass(),
400                                                        arg, rewrapCtorProblem(ctxt, t0)
401                 );
402             }
403         }
404 
405         return super.createFromLong(ctxt, value);
406     }
407 
408     @Override
createFromBigInteger(DeserializationContext ctxt, BigInteger value)409     public Object createFromBigInteger(DeserializationContext ctxt, BigInteger value) throws IOException
410     {
411         if (_fromBigDecimalCreator != null) {
412             try {
413                 return _fromBigIntegerCreator.call1(value);
414             } catch (Throwable t) {
415                 return ctxt.handleInstantiationProblem(_fromBigIntegerCreator.getDeclaringClass(),
416                                                        value, rewrapCtorProblem(ctxt, t)
417                 );
418             }
419         }
420 
421         return super.createFromBigInteger(ctxt, value);
422     }
423 
424     @Override
createFromDouble(DeserializationContext ctxt, double value)425     public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException
426     {
427         if(_fromDoubleCreator != null) {
428             Object arg = Double.valueOf(value);
429             try {
430                 return _fromDoubleCreator.call1(arg);
431             } catch (Throwable t0) {
432                 return ctxt.handleInstantiationProblem(_fromDoubleCreator.getDeclaringClass(),
433                                                        arg, rewrapCtorProblem(ctxt, t0));
434             }
435         }
436 
437         if (_fromBigDecimalCreator != null) {
438             Object arg = BigDecimal.valueOf(value);
439             try {
440                 return _fromBigDecimalCreator.call1(arg);
441             } catch (Throwable t0) {
442                 return ctxt.handleInstantiationProblem(_fromBigDecimalCreator.getDeclaringClass(),
443                                                        arg, rewrapCtorProblem(ctxt, t0));
444             }
445         }
446 
447         return super.createFromDouble(ctxt, value);
448     }
449 
450     @Override
createFromBigDecimal(DeserializationContext ctxt, BigDecimal value)451     public Object createFromBigDecimal(DeserializationContext ctxt, BigDecimal value) throws IOException
452     {
453         if (_fromBigDecimalCreator != null) {
454             try {
455                 return _fromBigDecimalCreator.call1(value);
456             } catch (Throwable t) {
457                 return ctxt.handleInstantiationProblem(_fromBigDecimalCreator.getDeclaringClass(),
458                                                        value, rewrapCtorProblem(ctxt, t)
459                 );
460             }
461         }
462 
463         return super.createFromBigDecimal(ctxt, value);
464     }
465 
466     @Override
createFromBoolean(DeserializationContext ctxt, boolean value)467     public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException
468     {
469         if (_fromBooleanCreator == null) {
470             return super.createFromBoolean(ctxt, value);
471         }
472         final Boolean arg = Boolean.valueOf(value);
473         try {
474             return _fromBooleanCreator.call1(arg);
475         } catch (Throwable t0) {
476             return ctxt.handleInstantiationProblem(_fromBooleanCreator.getDeclaringClass(),
477                     arg, rewrapCtorProblem(ctxt, t0));
478         }
479     }
480 
481     /*
482     /**********************************************************
483     /* Extended API: configuration mutators, accessors
484     /**********************************************************
485      */
486 
487     @Override
getDelegateCreator()488     public AnnotatedWithParams getDelegateCreator() {
489         return _delegateCreator;
490     }
491 
492     @Override
getArrayDelegateCreator()493     public AnnotatedWithParams getArrayDelegateCreator() {
494         return _arrayDelegateCreator;
495     }
496 
497     @Override
getDefaultCreator()498     public AnnotatedWithParams getDefaultCreator() {
499         return _defaultCreator;
500     }
501 
502     @Override
getWithArgsCreator()503     public AnnotatedWithParams getWithArgsCreator() {
504         return _withArgsCreator;
505     }
506 
507     /*
508     /**********************************************************
509     /* Internal methods
510     /**********************************************************
511      */
512 
513     /**
514      * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
515      *  {@link #wrapAsJsonMappingException}
516      */
517     @Deprecated // since 2.7
wrapException(Throwable t)518     protected JsonMappingException wrapException(Throwable t)
519     {
520         // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only
521         //   does so if and until `JsonMappingException` is found.
522         for (Throwable curr = t; curr != null; curr = curr.getCause()) {
523             if (curr instanceof JsonMappingException) {
524                 return (JsonMappingException) curr;
525             }
526         }
527         return new JsonMappingException(null,
528                 "Instantiation of "+getValueTypeDesc()+" value failed: "+ClassUtil.exceptionMessage(t), t);
529     }
530 
531     /**
532      * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
533      *  {@link #wrapAsJsonMappingException}
534      */
535     @Deprecated // since 2.10
unwrapAndWrapException(DeserializationContext ctxt, Throwable t)536     protected JsonMappingException unwrapAndWrapException(DeserializationContext ctxt, Throwable t)
537     {
538         // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only
539         //   does so if and until `JsonMappingException` is found.
540         for (Throwable curr = t; curr != null; curr = curr.getCause()) {
541             if (curr instanceof JsonMappingException) {
542                 return (JsonMappingException) curr;
543             }
544         }
545         return ctxt.instantiationException(getValueClass(), t);
546     }
547 
548     /**
549      * Helper method that will return given {@link Throwable} case as
550      * a {@link JsonMappingException} (if it is of that type), or call
551      * {@link DeserializationContext#instantiationException(Class, Throwable)} to
552      * produce and return suitable {@link JsonMappingException}.
553      *
554      * @since 2.7
555      */
wrapAsJsonMappingException(DeserializationContext ctxt, Throwable t)556     protected JsonMappingException wrapAsJsonMappingException(DeserializationContext ctxt,
557             Throwable t)
558     {
559         // 05-Nov-2015, tatu: Only avoid wrapping if already a JsonMappingException
560         if (t instanceof JsonMappingException) {
561             return (JsonMappingException) t;
562         }
563         return ctxt.instantiationException(getValueClass(), t);
564     }
565 
566     /**
567      * Method that subclasses may call for standard handling of an exception thrown when
568      * calling constructor or factory method. Will unwrap {@link ExceptionInInitializerError}
569      * and {@link InvocationTargetException}s, then call {@link #wrapAsJsonMappingException}.
570      *
571      * @since 2.7
572      */
rewrapCtorProblem(DeserializationContext ctxt, Throwable t)573     protected JsonMappingException rewrapCtorProblem(DeserializationContext ctxt,
574             Throwable t)
575     {
576         // 05-Nov-2015, tatu: Seems like there are really only 2 useless wrapper errors/exceptions,
577         //    so just peel those, and nothing else
578         if ((t instanceof ExceptionInInitializerError) // from static initialization block
579                 || (t instanceof InvocationTargetException) // from constructor/method
580                 ) {
581             Throwable cause = t.getCause();
582             if (cause != null) {
583                 t = cause;
584             }
585         }
586         return wrapAsJsonMappingException(ctxt, t);
587     }
588 
589     /*
590     /**********************************************************
591     /* Helper methods
592     /**********************************************************
593      */
594 
_createUsingDelegate(AnnotatedWithParams delegateCreator, SettableBeanProperty[] delegateArguments, DeserializationContext ctxt, Object delegate)595     private Object _createUsingDelegate(AnnotatedWithParams delegateCreator,
596             SettableBeanProperty[] delegateArguments,
597             DeserializationContext ctxt,
598             Object delegate)
599             throws IOException
600     {
601         if (delegateCreator == null) { // sanity-check; caller should check
602             throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc());
603         }
604         try {
605             // First simple case: just delegate, no injectables
606             if (delegateArguments == null) {
607                 return delegateCreator.call1(delegate);
608             }
609             // And then the case with at least one injectable...
610             final int len = delegateArguments.length;
611             Object[] args = new Object[len];
612             for (int i = 0; i < len; ++i) {
613                 SettableBeanProperty prop = delegateArguments[i];
614                 if (prop == null) { // delegate
615                     args[i] = delegate;
616                 } else { // nope, injectable:
617                     args[i] = ctxt.findInjectableValue(prop.getInjectableValueId(), prop, null);
618                 }
619             }
620             // and then try calling with full set of arguments
621             return delegateCreator.call(args);
622         } catch (Throwable t) {
623             throw rewrapCtorProblem(ctxt, t);
624         }
625     }
626 }
627