• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.cfg;
2 
3 import java.text.DateFormat;
4 import java.util.Locale;
5 import java.util.TimeZone;
6 
7 import com.fasterxml.jackson.core.Base64Variant;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
10 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
11 import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
12 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
13 import com.fasterxml.jackson.databind.type.TypeFactory;
14 import com.fasterxml.jackson.databind.util.StdDateFormat;
15 
16 /**
17  * Immutable container class used to store simple configuration
18  * settings for both serialization and deserialization.
19  * Since instances are fully immutable, instances can
20  * be freely shared and used without synchronization.
21  */
22 public final class BaseSettings
23     implements java.io.Serializable
24 {
25     private static final long serialVersionUID = 1L;
26 
27     /**
28      * We will use a default TimeZone as the baseline.
29      */
30     private static final TimeZone DEFAULT_TIMEZONE =
31             //  TimeZone.getDefault()
32             /* [databind#915] 05-Nov-2015, tatu: Changed to UTC, from earlier
33              * baseline of GMT (up to 2.6)
34              */
35             TimeZone.getTimeZone("UTC");
36 
37     /*
38     /**********************************************************
39     /* Configuration settings; introspection, related
40     /**********************************************************
41      */
42 
43     /**
44      * Introspector used to figure out Bean properties needed for bean serialization
45      * and deserialization. Overridable so that it is possible to change low-level
46      * details of introspection, like adding new annotation types.
47      */
48     protected final ClassIntrospector _classIntrospector;
49 
50     /**
51      * Introspector used for accessing annotation value based configuration.
52      */
53     protected final AnnotationIntrospector _annotationIntrospector;
54 
55     /**
56      * Custom property naming strategy in use, if any.
57      */
58     protected final PropertyNamingStrategy _propertyNamingStrategy;
59 
60     /**
61      * Specific factory used for creating {@link JavaType} instances;
62      * needed to allow modules to add more custom type handling
63      * (mostly to support types of non-Java JVM languages)
64      */
65     protected final TypeFactory _typeFactory;
66 
67     /*
68     /**********************************************************
69     /* Configuration settings; poly type resolution
70     /**********************************************************
71      */
72 
73     /**
74      * Builder used to create type resolver for serializing and deserializing
75      * values for which polymorphic type handling is needed.
76      */
77     protected final TypeResolverBuilder<?> _typeResolverBuilder;
78 
79     /**
80      * Validator that is used to limit allowed polymorphic subtypes, mostly
81      * for security reasons when dealing with untrusted content.
82      *
83      * @since 2.10
84      */
85     protected final PolymorphicTypeValidator _typeValidator;
86 
87     /*
88     /**********************************************************
89     /* Configuration settings; other
90     /**********************************************************
91      */
92 
93     /**
94      * Custom date format to use for deserialization. If specified, will be
95      * used instead of {@link com.fasterxml.jackson.databind.util.StdDateFormat}.
96      *<p>
97      * Note that the configured format object will be cloned once per
98      * deserialization process (first time it is needed)
99      */
100     protected final DateFormat _dateFormat;
101 
102     /**
103      * Object used for creating instances of handlers (serializers, deserializers,
104      * type and type id resolvers), given class to instantiate. This is typically
105      * used to do additional configuration (with dependency injection, for example)
106      * beyond simply construction of instances; or to use alternative constructors.
107      */
108     protected final HandlerInstantiator _handlerInstantiator;
109 
110     /**
111      * Default {@link java.util.Locale} used with serialization formats.
112      * Default value is {@link Locale#getDefault()}.
113      */
114     protected final Locale _locale;
115 
116     /**
117      * Default {@link java.util.TimeZone} used with serialization formats,
118      * if (and only if!) explicitly set by use; otherwise `null` to indicate
119      * "use default", which means "UTC" (from Jackson 2.7); earlier versions
120      * (up to 2.6) used "GMT".
121      *<p>
122      * Note that if a new value is set, timezone is also assigned to
123      * {@link #_dateFormat} of this object.
124      */
125     protected final TimeZone _timeZone;
126 
127     /**
128      * Explicitly default {@link Base64Variant} to use for handling
129      * binary data (<code>byte[]</code>), used with data formats
130      * that use base64 encoding (like JSON, CSV).
131      *
132      * @since 2.1
133      */
134     protected final Base64Variant _defaultBase64;
135 
136     /*
137     /**********************************************************
138     /* Construction
139     /**********************************************************
140      */
141 
142     /**
143      * @since 2.10
144      */
BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai, PropertyNamingStrategy pns, TypeFactory tf, TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi, Locale locale, TimeZone tz, Base64Variant defaultBase64, PolymorphicTypeValidator ptv)145     public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
146             PropertyNamingStrategy pns, TypeFactory tf,
147             TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
148             Locale locale, TimeZone tz, Base64Variant defaultBase64,
149             PolymorphicTypeValidator ptv)
150     {
151         _classIntrospector = ci;
152         _annotationIntrospector = ai;
153         _propertyNamingStrategy = pns;
154         _typeFactory = tf;
155         _typeResolverBuilder = typer;
156         _dateFormat = dateFormat;
157         _handlerInstantiator = hi;
158         _locale = locale;
159         _timeZone = tz;
160         _defaultBase64 = defaultBase64;
161         _typeValidator = ptv;
162     }
163 
164     @Deprecated // since 2.10
BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai, PropertyNamingStrategy pns, TypeFactory tf, TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi, Locale locale, TimeZone tz, Base64Variant defaultBase64)165     public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
166             PropertyNamingStrategy pns, TypeFactory tf,
167             TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
168             Locale locale, TimeZone tz, Base64Variant defaultBase64)
169     {
170         this(ci, ai, pns, tf, typer, dateFormat, hi, locale, tz, defaultBase64, null);
171     }
172 
173     /**
174      * Turns out we are not necessarily 100% stateless, alas, since {@link ClassIntrospector}
175      * typically has a cache. So this method is needed for deep copy() of Mapper.
176      *
177      * @since 2.9.6
178      */
copy()179     public BaseSettings copy() {
180         return new BaseSettings(_classIntrospector.copy(),
181             _annotationIntrospector,
182             _propertyNamingStrategy,
183             _typeFactory,
184             _typeResolverBuilder,
185             _dateFormat,
186             _handlerInstantiator,
187             _locale,
188             _timeZone,
189             _defaultBase64,
190             _typeValidator);
191 
192     }
193 
194     /*
195     /**********************************************************
196     /* Factory methods
197     /**********************************************************
198      */
199 
withClassIntrospector(ClassIntrospector ci)200     public BaseSettings withClassIntrospector(ClassIntrospector ci) {
201         if (_classIntrospector == ci) {
202             return this;
203         }
204         return new BaseSettings(ci, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
205                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
206                 _timeZone, _defaultBase64, _typeValidator);
207     }
208 
withAnnotationIntrospector(AnnotationIntrospector ai)209     public BaseSettings withAnnotationIntrospector(AnnotationIntrospector ai) {
210         if (_annotationIntrospector == ai) {
211             return this;
212         }
213         return new BaseSettings(_classIntrospector, ai, _propertyNamingStrategy, _typeFactory,
214                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
215                 _timeZone, _defaultBase64, _typeValidator);
216     }
217 
withInsertedAnnotationIntrospector(AnnotationIntrospector ai)218     public BaseSettings withInsertedAnnotationIntrospector(AnnotationIntrospector ai) {
219         return withAnnotationIntrospector(AnnotationIntrospectorPair.create(ai, _annotationIntrospector));
220     }
221 
withAppendedAnnotationIntrospector(AnnotationIntrospector ai)222     public BaseSettings withAppendedAnnotationIntrospector(AnnotationIntrospector ai) {
223         return withAnnotationIntrospector(AnnotationIntrospectorPair.create(_annotationIntrospector, ai));
224     }
225 
226     /*
227     public BaseSettings withVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) {
228         return new BaseSettings(_classIntrospector, _annotationIntrospector,
229                 _visibilityChecker.withVisibility(forMethod, visibility),
230                 _propertyNamingStrategy, _typeFactory,
231                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
232                 _timeZone, _defaultBase64, _typeValidator);
233     }
234     */
235 
withPropertyNamingStrategy(PropertyNamingStrategy pns)236     public BaseSettings withPropertyNamingStrategy(PropertyNamingStrategy pns) {
237         if (_propertyNamingStrategy == pns) {
238             return this;
239         }
240         return new BaseSettings(_classIntrospector, _annotationIntrospector, pns, _typeFactory,
241                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
242                 _timeZone, _defaultBase64, _typeValidator);
243     }
244 
withTypeFactory(TypeFactory tf)245     public BaseSettings withTypeFactory(TypeFactory tf) {
246         if (_typeFactory == tf) {
247             return this;
248         }
249         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, tf,
250                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
251                 _timeZone, _defaultBase64, _typeValidator);
252     }
253 
withTypeResolverBuilder(TypeResolverBuilder<?> typer)254     public BaseSettings withTypeResolverBuilder(TypeResolverBuilder<?> typer) {
255         if (_typeResolverBuilder == typer) {
256             return this;
257         }
258         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
259                 typer, _dateFormat, _handlerInstantiator, _locale,
260                 _timeZone, _defaultBase64, _typeValidator);
261     }
262 
withDateFormat(DateFormat df)263     public BaseSettings withDateFormat(DateFormat df) {
264         if (_dateFormat == df) {
265             return this;
266         }
267         // 26-Sep-2015, tatu: Related to [databind#939], let's try to force TimeZone if
268         //   (but only if!) it has been set explicitly.
269         if ((df != null) && hasExplicitTimeZone()) {
270             df = _force(df, _timeZone);
271         }
272         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
273                 _typeResolverBuilder, df, _handlerInstantiator, _locale,
274                 _timeZone, _defaultBase64, _typeValidator);
275     }
276 
withHandlerInstantiator(HandlerInstantiator hi)277     public BaseSettings withHandlerInstantiator(HandlerInstantiator hi) {
278         if (_handlerInstantiator == hi) {
279             return this;
280         }
281         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
282                 _typeResolverBuilder, _dateFormat, hi, _locale,
283                 _timeZone, _defaultBase64, _typeValidator);
284     }
285 
with(Locale l)286     public BaseSettings with(Locale l) {
287         if (_locale == l) {
288             return this;
289         }
290         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
291                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, l,
292                 _timeZone, _defaultBase64, _typeValidator);
293     }
294 
295     /**
296      * Fluent factory for constructing a new instance that uses specified TimeZone.
297      * Note that timezone used with also be assigned to configured {@link DateFormat},
298      * changing time formatting defaults.
299      */
with(TimeZone tz)300     public BaseSettings with(TimeZone tz)
301     {
302         if (tz == null) {
303             throw new IllegalArgumentException();
304         }
305         if (tz == _timeZone) {
306             return this;
307         }
308 
309         DateFormat df = _force(_dateFormat, tz);
310         return new BaseSettings(_classIntrospector, _annotationIntrospector,
311                 _propertyNamingStrategy, _typeFactory,
312                 _typeResolverBuilder, df, _handlerInstantiator, _locale,
313                 tz, _defaultBase64, _typeValidator);
314     }
315 
316     /**
317      * @since 2.1
318      */
with(Base64Variant base64)319     public BaseSettings with(Base64Variant base64) {
320         if (base64 == _defaultBase64) {
321             return this;
322         }
323         return new BaseSettings(_classIntrospector, _annotationIntrospector,
324                 _propertyNamingStrategy, _typeFactory,
325                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
326                 _timeZone, base64, _typeValidator);
327     }
328 
329     /**
330      * @since 2.10
331      */
with(PolymorphicTypeValidator v)332     public BaseSettings with(PolymorphicTypeValidator v) {
333         if (v == _typeValidator) {
334             return this;
335         }
336         return new BaseSettings(_classIntrospector, _annotationIntrospector,
337                 _propertyNamingStrategy, _typeFactory,
338                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
339                 _timeZone, _defaultBase64, v);
340     }
341 
342     /*
343     /**********************************************************
344     /* API
345     /**********************************************************
346      */
347 
getClassIntrospector()348     public ClassIntrospector getClassIntrospector() {
349         return _classIntrospector;
350     }
351 
getAnnotationIntrospector()352     public AnnotationIntrospector getAnnotationIntrospector() {
353         return _annotationIntrospector;
354     }
355 
getPropertyNamingStrategy()356     public PropertyNamingStrategy getPropertyNamingStrategy() {
357         return _propertyNamingStrategy;
358     }
359 
getTypeFactory()360     public TypeFactory getTypeFactory() {
361         return _typeFactory;
362     }
363 
getTypeResolverBuilder()364     public TypeResolverBuilder<?> getTypeResolverBuilder() {
365         return _typeResolverBuilder;
366     }
367 
368     /**
369      * @since 2.10
370      */
getPolymorphicTypeValidator()371     public PolymorphicTypeValidator getPolymorphicTypeValidator() {
372         return _typeValidator;
373     }
374 
getDateFormat()375     public DateFormat getDateFormat() {
376         return _dateFormat;
377     }
378 
getHandlerInstantiator()379     public HandlerInstantiator getHandlerInstantiator() {
380         return _handlerInstantiator;
381     }
382 
getLocale()383     public Locale getLocale() {
384         return _locale;
385     }
386 
getTimeZone()387     public TimeZone getTimeZone() {
388         TimeZone tz = _timeZone;
389         return (tz == null) ? DEFAULT_TIMEZONE : tz;
390     }
391 
392     /**
393      * Accessor that may be called to determine whether this settings object
394      * has been explicitly configured with a TimeZone (true), or is still
395      * relying on the default settings (false).
396      *
397      * @since 2.7
398      */
hasExplicitTimeZone()399     public boolean hasExplicitTimeZone() {
400         return (_timeZone != null);
401     }
402 
getBase64Variant()403     public Base64Variant getBase64Variant() {
404         return _defaultBase64;
405     }
406 
407     /*
408     /**********************************************************
409     /* Helper methods
410     /**********************************************************
411      */
412 
_force(DateFormat df, TimeZone tz)413     private DateFormat _force(DateFormat df, TimeZone tz)
414     {
415         if (df instanceof StdDateFormat) {
416             return ((StdDateFormat) df).withTimeZone(tz);
417         }
418         // we don't know if original format might be shared; better create a clone:
419         df = (DateFormat) df.clone();
420         df.setTimeZone(tz);
421         return df;
422     }
423 }
424