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.AnnotatedParameter;
10 import com.fasterxml.jackson.databind.introspect.AnnotatedWithParams;
11 import com.fasterxml.jackson.databind.util.ClassUtil;
12
13 /**
14  * Default {@link ValueInstantiator} implementation, which supports
15  * Creator methods that can be indicated by standard Jackson
16  * annotations.
17  */

18 @JacksonStdImpl
19 public class StdValueInstantiator
20     extends ValueInstantiator
21     implements java.io.Serializable
22 {
23     private static final long serialVersionUID = 1L;
24
25     /**
26      * Type of values that are instantiated; used
27      * for error reporting purposes.
28      */

29     protected final String _valueTypeDesc;
30
31     /**
32      * @since 2.8
33      */

34     protected final Class<?> _valueClass;
35
36     // // // Default (no-args) construction
37
38     /**
39      * Default (no-argument) constructor to use for instantiation
40      * (with {@link #createUsingDefault})
41      */

42     protected AnnotatedWithParams _defaultCreator;
43
44     // // // With-args (property-based) construction
45
46     protected AnnotatedWithParams _withArgsCreator;
47     protected SettableBeanProperty[] _constructorArguments;
48
49     // // // Delegate construction
50     
51     protected JavaType _delegateType;
52     protected AnnotatedWithParams _delegateCreator;
53     protected SettableBeanProperty[] _delegateArguments;
54
55     // // // Array delegate construction
56
57     protected JavaType _arrayDelegateType;
58     protected AnnotatedWithParams _arrayDelegateCreator;
59     protected SettableBeanProperty[] _arrayDelegateArguments;
60     
61     // // // Scalar construction
62
63     protected AnnotatedWithParams _fromStringCreator;
64     protected AnnotatedWithParams _fromIntCreator;
65     protected AnnotatedWithParams _fromLongCreator;
66     protected AnnotatedWithParams _fromDoubleCreator;
67     protected AnnotatedWithParams _fromBooleanCreator;
68
69     // // // Incomplete creator
70     protected AnnotatedParameter  _incompleteParameter;
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
82     public StdValueInstantiator(DeserializationConfig config, Class<?> valueType) {
83         _valueTypeDesc = ClassUtil.nameOf(valueType);
84         _valueClass = (valueType == null) ? Object.class : valueType;
85     }
86
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      */

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         _fromDoubleCreator = src._fromDoubleCreator;
118         _fromBooleanCreator = src._fromBooleanCreator;
119     }
120
121     /**
122      * Method for setting properties related to instantiating values
123      * from JSON Object. We will choose basically only one approach (out of possible
124      * three), and clear other properties
125      */

126     public void configureFromObjectSettings(AnnotatedWithParams defaultCreator,
127             AnnotatedWithParams delegateCreator, JavaType delegateType, SettableBeanProperty[] delegateArgs,
128             AnnotatedWithParams withArgsCreator, SettableBeanProperty[] constructorArgs)
129     {
130         _defaultCreator = defaultCreator;
131         _delegateCreator = delegateCreator;
132         _delegateType = delegateType;
133         _delegateArguments = delegateArgs;
134         _withArgsCreator = withArgsCreator;
135         _constructorArguments = constructorArgs;
136     }
137
138     public void configureFromArraySettings(
139             AnnotatedWithParams arrayDelegateCreator,
140             JavaType arrayDelegateType,
141             SettableBeanProperty[] arrayDelegateArgs)
142     {
143         _arrayDelegateCreator = arrayDelegateCreator;
144         _arrayDelegateType = arrayDelegateType;
145         _arrayDelegateArguments = arrayDelegateArgs;
146     }
147
148     public void configureFromStringCreator(AnnotatedWithParams creator) {
149         _fromStringCreator = creator;
150     }
151
152     public void configureFromIntCreator(AnnotatedWithParams creator) {
153         _fromIntCreator = creator;
154     }
155
156     public void configureFromLongCreator(AnnotatedWithParams creator) {
157         _fromLongCreator = creator;
158     }
159
160     public void configureFromDoubleCreator(AnnotatedWithParams creator) {
161         _fromDoubleCreator = creator;
162     }
163
164     public void configureFromBooleanCreator(AnnotatedWithParams creator) {
165         _fromBooleanCreator = creator;
166     }
167
168     public void configureIncompleteParameter(AnnotatedParameter parameter) {
169         _incompleteParameter = parameter;
170     }
171     
172     /*
173     /**********************************************************
174     /* Public API implementation; metadata
175     /**********************************************************
176      */

177
178     @Override
179     public String getValueTypeDesc() {
180         return _valueTypeDesc;
181     }
182
183     @Override
184     public Class<?> getValueClass() {
185         return _valueClass;
186     }
187
188     @Override
189     public boolean canCreateFromString() {
190         return (_fromStringCreator != null);
191     }
192
193     @Override
194     public boolean canCreateFromInt() {
195         return (_fromIntCreator != null);
196     }
197
198     @Override
199     public boolean canCreateFromLong() {
200         return (_fromLongCreator != null);
201     }
202
203     @Override
204     public boolean canCreateFromDouble() {
205         return (_fromDoubleCreator != null);
206     }
207
208     @Override
209     public boolean canCreateFromBoolean() {
210         return (_fromBooleanCreator != null);
211     }
212
213     @Override
214     public boolean canCreateUsingDefault() {
215         return (_defaultCreator != null);
216     }
217
218     @Override
219     public boolean canCreateUsingDelegate() {
220         return (_delegateType != null);
221     }
222
223     @Override
224     public boolean canCreateUsingArrayDelegate() {
225         return (_arrayDelegateType != null);
226     }
227
228     @Override
229     public boolean canCreateFromObjectWith() {
230         return (_withArgsCreator != null);
231     }
232
233     @Override
234     public boolean canInstantiate() {
235         return canCreateUsingDefault()
236                 || canCreateUsingDelegate() || canCreateUsingArrayDelegate()
237                 || canCreateFromObjectWith() || canCreateFromString()
238                 || canCreateFromInt() || canCreateFromLong()
239                 || canCreateFromDouble() || canCreateFromBoolean();
240     }
241
242     @Override
243     public JavaType getDelegateType(DeserializationConfig config) {
244         return _delegateType;
245     }
246
247     @Override
248     public JavaType getArrayDelegateType(DeserializationConfig config) {
249         return _arrayDelegateType;
250     }
251
252     @Override
253     public SettableBeanProperty[] getFromObjectArguments(DeserializationConfig config) {
254         return _constructorArguments;
255     }
256     
257     /*
258     /**********************************************************
259     /* Public API implementation; instantiation from JSON Object
260     /**********************************************************
261      */

262     
263     @Override
264     public Object createUsingDefault(DeserializationContext ctxt) throws IOException
265     {
266         if (_defaultCreator == null) { // sanity-check; caller should check
267             return super.createUsingDefault(ctxt);
268         }
269         try {
270             return _defaultCreator.call();
271         } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions
272             return ctxt.handleInstantiationProblem(_valueClass, null, rewrapCtorProblem(ctxt, e));
273         }
274     }
275
276     @Override
277     public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) throws IOException
278     {
279         if (_withArgsCreator == null) { // sanity-check; caller should check
280             return super.createFromObjectWith(ctxt, args);
281         }
282         try {
283             return _withArgsCreator.call(args);
284         } catch (Exception e) { // 19-Apr-2017, tatu: Let's not catch Errors, just Exceptions
285             return ctxt.handleInstantiationProblem(_valueClass, args, rewrapCtorProblem(ctxt, e));
286         }
287     }
288
289     @Override
290     public Object createUsingDelegate(DeserializationContext ctxt, Object delegate) throws IOException
291     {
292         // 04-Oct-2016, tatu: Need delegation to work around [databind#1392]...
293         if (_delegateCreator == null) {
294             if (_arrayDelegateCreator != null) {
295                 return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate);
296             }
297         }
298         return _createUsingDelegate(_delegateCreator, _delegateArguments, ctxt, delegate);
299     }
300
301     @Override
302     public Object createUsingArrayDelegate(DeserializationContext ctxt, Object delegate) throws IOException
303     {
304         if (_arrayDelegateCreator == null) {
305             if (_delegateCreator != null) { // sanity-check; caller should check
306                 // fallback to the classic delegate creator
307                 return createUsingDelegate(ctxt, delegate);
308             }
309         }
310         return _createUsingDelegate(_arrayDelegateCreator, _arrayDelegateArguments, ctxt, delegate);
311     }
312
313     /*
314     /**********************************************************
315     /* Public API implementation; instantiation from JSON scalars
316     /**********************************************************
317      */

318
319     @Override
320     public Object createFromString(DeserializationContext ctxt, String value) throws IOException
321     {
322         if (_fromStringCreator == null) {
323             return _createFromStringFallbacks(ctxt, value);
324         }
325         try {
326             return _fromStringCreator.call1(value);
327         } catch (Throwable t) {
328             return ctxt.handleInstantiationProblem(_fromStringCreator.getDeclaringClass(),
329                     value, rewrapCtorProblem(ctxt, t));
330         }
331     }
332     
333     @Override
334     public Object createFromInt(DeserializationContext ctxt, int value) throws IOException
335     {
336         // First: "native" int methods work best:
337         if (_fromIntCreator != null) {
338             Object arg = Integer.valueOf(value);
339             try {
340                 return _fromIntCreator.call1(arg);
341             } catch (Throwable t0) {
342                 return ctxt.handleInstantiationProblem(_fromIntCreator.getDeclaringClass(),
343                         arg, rewrapCtorProblem(ctxt, t0));
344             }
345         }
346         // but if not, can do widening conversion
347         if (_fromLongCreator != null) {
348             Object arg = Long.valueOf(value);
349             try {
350                 return _fromLongCreator.call1(arg);
351             } catch (Throwable t0) {
352                 return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
353                         arg, rewrapCtorProblem(ctxt, t0));
354             }
355         }
356         return super.createFromInt(ctxt, value);
357     }
358
359     @Override
360     public Object createFromLong(DeserializationContext ctxt, long value) throws IOException
361     {
362         if (_fromLongCreator == null) {
363             return super.createFromLong(ctxt, value);
364         }
365         Object arg = Long.valueOf(value);
366         try {
367             return _fromLongCreator.call1(arg);
368         } catch (Throwable t0) {
369             return ctxt.handleInstantiationProblem(_fromLongCreator.getDeclaringClass(),
370                     arg, rewrapCtorProblem(ctxt, t0));
371         }
372     }
373
374     @Override
375     public Object createFromDouble(DeserializationContext ctxt, double value) throws IOException
376     {
377         if (_fromDoubleCreator == null) {
378             return super.createFromDouble(ctxt, value);
379         }
380         Object arg = Double.valueOf(value);
381         try {
382             return _fromDoubleCreator.call1(arg);
383         } catch (Throwable t0) {
384             return ctxt.handleInstantiationProblem(_fromDoubleCreator.getDeclaringClass(),
385                     arg, rewrapCtorProblem(ctxt, t0));
386         }
387     }
388
389     @Override
390     public Object createFromBoolean(DeserializationContext ctxt, boolean value) throws IOException
391     {
392         if (_fromBooleanCreator == null) {
393             return super.createFromBoolean(ctxt, value);
394         }
395         final Boolean arg = Boolean.valueOf(value);
396         try {
397             return _fromBooleanCreator.call1(arg);
398         } catch (Throwable t0) {
399             return ctxt.handleInstantiationProblem(_fromBooleanCreator.getDeclaringClass(),
400                     arg, rewrapCtorProblem(ctxt, t0));
401         }
402     }
403     
404     /*
405     /**********************************************************
406     /* Extended API: configuration mutators, accessors
407     /**********************************************************
408      */

409
410     @Override
411     public AnnotatedWithParams getDelegateCreator() {
412         return _delegateCreator;
413     }
414
415     @Override
416     public AnnotatedWithParams getArrayDelegateCreator() {
417         return _arrayDelegateCreator;
418     }
419
420     @Override
421     public AnnotatedWithParams getDefaultCreator() {
422         return _defaultCreator;
423     }
424
425     @Override
426     public AnnotatedWithParams getWithArgsCreator() {
427         return _withArgsCreator;
428     }
429
430     @Override
431     public AnnotatedParameter getIncompleteParameter() {
432         return _incompleteParameter;
433     }
434
435     /*
436     /**********************************************************
437     /* Internal methods
438     /**********************************************************
439      */

440
441     /**
442      * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
443      *  {@link #wrapAsJsonMappingException}
444      */

445     @Deprecated // since 2.7
446     protected JsonMappingException wrapException(Throwable t)
447     {
448         // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only
449         //   does so if and until `JsonMappingException` is found.
450         for (Throwable curr = t; curr != null; curr = curr.getCause()) {
451             if (curr instanceof JsonMappingException) {
452                 return (JsonMappingException) curr;
453             }
454         }
455         return new JsonMappingException(null,
456                 "Instantiation of "+getValueTypeDesc()+" value failed: "+ClassUtil.exceptionMessage(t), t);
457     }
458
459     /**
460      * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
461      *  {@link #wrapAsJsonMappingException}
462      */

463     @Deprecated // since 2.10
464     protected JsonMappingException unwrapAndWrapException(DeserializationContext ctxt, Throwable t)
465     {
466         // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only
467         //   does so if and until `JsonMappingException` is found.
468         for (Throwable curr = t; curr != null; curr = curr.getCause()) {
469             if (curr instanceof JsonMappingException) {
470                 return (JsonMappingException) curr;
471             }
472         }
473         return ctxt.instantiationException(getValueClass(), t);
474     }
475
476     /**
477      * Helper method that will return given {@link Throwable} case as
478      * a {@link JsonMappingException} (if it is of that type), or call
479      * {@link DeserializationContext#instantiationException(Class, Throwable)} to
480      * produce and return suitable {@link JsonMappingException}.
481      *
482      * @since 2.7
483      */

484     protected JsonMappingException wrapAsJsonMappingException(DeserializationContext ctxt,
485             Throwable t)
486     {
487         // 05-Nov-2015, tatu: Only avoid wrapping if already a JsonMappingException
488         if (t instanceof JsonMappingException) {
489             return (JsonMappingException) t;
490         }
491         return ctxt.instantiationException(getValueClass(), t);
492     }
493
494     /**
495      * Method that subclasses may call for standard handling of an exception thrown when
496      * calling constructor or factory method. Will unwrap {@link ExceptionInInitializerError}
497      * and {@link InvocationTargetException}s, then call {@link #wrapAsJsonMappingException}.
498      *
499      * @since 2.7
500      */

501     protected JsonMappingException rewrapCtorProblem(DeserializationContext ctxt,
502             Throwable t)
503     {
504         // 05-Nov-2015, tatu: Seems like there are really only 2 useless wrapper errors/exceptions,
505         //    so just peel those, and nothing else
506         if ((t instanceof ExceptionInInitializerError) // from static initialization block
507                 || (t instanceof InvocationTargetException) // from constructor/method
508                 ) {
509             Throwable cause = t.getCause();
510             if (cause != null) {
511                 t = cause;
512             }
513         }
514         return wrapAsJsonMappingException(ctxt, t);
515     }
516
517     /*
518     /**********************************************************
519     /* Helper methods
520     /**********************************************************
521      */

522
523     private Object _createUsingDelegate(AnnotatedWithParams delegateCreator,
524             SettableBeanProperty[] delegateArguments,
525             DeserializationContext ctxt,
526             Object delegate)
527             throws IOException
528     {
529         if (delegateCreator == null) { // sanity-check; caller should check
530             throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc());
531         }
532         try {
533             // First simple case: just delegate, no injectables
534             if (delegateArguments == null) {
535                 return delegateCreator.call1(delegate);
536             }
537             // And then the case with at least one injectable...
538             final int len = delegateArguments.length;
539             Object[] args = new Object[len];
540             for (int i = 0; i < len; ++i) {
541                 SettableBeanProperty prop = delegateArguments[i];
542                 if (prop == null) { // delegate
543                     args[i] = delegate;
544                 } else { // nope, injectable:
545                     args[i] = ctxt.findInjectableValue(prop.getInjectableValueId(), prop, null);
546                 }
547             }
548             // and then try calling with full set of arguments
549             return delegateCreator.call(args);
550         } catch (Throwable t) {
551             throw rewrapCtorProblem(ctxt, t);
552         }
553     }
554 }
555