package com.fasterxml.jackson.databind;

import java.lang.reflect.Type;
import java.util.Locale;
import java.util.TimeZone;

import com.fasterxml.jackson.annotation.*;

import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator.Validity;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.fasterxml.jackson.databind.util.Converter;

Shared base class for DeserializationContext and SerializerProvider, context objects passed through data-binding process. Designed so that some of implementations can rely on shared aspects like access to secondary contextual objects like type factories or handler instantiators.
Since:2.2
/** * Shared base class for {@link DeserializationContext} and * {@link SerializerProvider}, context objects passed through data-binding * process. Designed so that some of implementations can rely on shared * aspects like access to secondary contextual objects like type factories * or handler instantiators. * * @since 2.2 */
public abstract class DatabindContext {
Let's limit length of error messages, for cases where underlying data may be very large -- no point in spamming logs with megabytes of meaningless data.
Since:2.9
/** * Let's limit length of error messages, for cases where underlying data * may be very large -- no point in spamming logs with megabytes of meaningless * data. * * @since 2.9 */
private final static int MAX_ERROR_STR_LEN = 500; /* /********************************************************** /* Generic config access /********************************************************** */
Accessor to currently active configuration (both per-request configs and per-mapper config).
/** * Accessor to currently active configuration (both per-request configs * and per-mapper config). */
public abstract MapperConfig<?> getConfig();
Convenience method for accessing serialization view in use (if any); equivalent to:
  getConfig().getAnnotationIntrospector();
/** * Convenience method for accessing serialization view in use (if any); equivalent to: *<pre> * getConfig().getAnnotationIntrospector(); *</pre> */
public abstract AnnotationIntrospector getAnnotationIntrospector(); /* /********************************************************** /* Access to specific config settings /********************************************************** */
Convenience method for checking whether specified serialization feature is enabled or not. Shortcut for:
 getConfig().isEnabled(feature);
/** * Convenience method for checking whether specified serialization * feature is enabled or not. * Shortcut for: *<pre> * getConfig().isEnabled(feature); *</pre> */
public abstract boolean isEnabled(MapperFeature feature);
Convenience method for accessing serialization view in use (if any); equivalent to:
  getConfig().canOverrideAccessModifiers();
/** * Convenience method for accessing serialization view in use (if any); equivalent to: *<pre> * getConfig().canOverrideAccessModifiers(); *</pre> */
public abstract boolean canOverrideAccessModifiers();
Accessor for locating currently active view, if any; returns null if no view has been set.
/** * Accessor for locating currently active view, if any; * returns null if no view has been set. */
public abstract Class<?> getActiveView();
Since:2.6
/** * @since 2.6 */
public abstract Locale getLocale();
Since:2.6
/** * @since 2.6 */
public abstract TimeZone getTimeZone();
Since:2.7
/** * @since 2.7 */
public abstract JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType); /* /********************************************************** /* Generic attributes (2.3+) /********************************************************** */
Method for accessing attributes available in this context. Per-call attributes have highest precedence; attributes set via ObjectReader or ObjectWriter have lower precedence.
Params:
  • key – Key of the attribute to get
Returns:Value of the attribute, if any; null otherwise
Since:2.3
/** * Method for accessing attributes available in this context. * Per-call attributes have highest precedence; attributes set * via {@link ObjectReader} or {@link ObjectWriter} have lower * precedence. * * @param key Key of the attribute to get * @return Value of the attribute, if any; null otherwise * * @since 2.3 */
public abstract Object getAttribute(Object key);
Method for setting per-call value of given attribute. This will override any previously defined value for the attribute within this context.
Params:
  • key – Key of the attribute to set
  • value – Value to set attribute to
Returns:This context object, to allow chaining
Since:2.3
/** * Method for setting per-call value of given attribute. * This will override any previously defined value for the * attribute within this context. * * @param key Key of the attribute to set * @param value Value to set attribute to * * @return This context object, to allow chaining * * @since 2.3 */
public abstract DatabindContext setAttribute(Object key, Object value); /* /********************************************************** /* Type instantiation/resolution /********************************************************** */
Convenience method for constructing JavaType for given JDK type (usually Class)
/** * Convenience method for constructing {@link JavaType} for given JDK * type (usually {@link java.lang.Class}) */
public JavaType constructType(Type type) { if (type == null) { return null; } return getTypeFactory().constructType(type); }
Convenience method for constructing subtypes, retaining generic type parameter (if any)
/** * Convenience method for constructing subtypes, retaining generic * type parameter (if any) */
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) { // simple optimization to avoid costly introspection if type-erased type does NOT differ if (baseType.getRawClass() == subclass) { return baseType; } return getConfig().constructSpecializedType(baseType, subclass); }
Lookup method called when code needs to resolve class name from input; usually simple lookup. Note that unlike resolveAndValidateSubType this method DOES NOT validate subtype against configured PolymorphicTypeValidator: usually because such check has already been made.
Since:2.9
/** * Lookup method called when code needs to resolve class name from input; * usually simple lookup. * Note that unlike {@link #resolveAndValidateSubType} this method DOES NOT * validate subtype against configured {@link PolymorphicTypeValidator}: usually * because such check has already been made. * * @since 2.9 */
public JavaType resolveSubType(JavaType baseType, String subClassName) throws JsonMappingException { // 30-Jan-2010, tatu: Most ids are basic class names; so let's first // check if any generics info is added; and only then ask factory // to do translation when necessary if (subClassName.indexOf('<') > 0) { // note: may want to try combining with specialization (esp for EnumMap)? // 17-Aug-2017, tatu: As per [databind#1735] need to ensure assignment // compatibility -- needed later anyway, and not doing so may open // security issues. JavaType t = getTypeFactory().constructFromCanonical(subClassName); if (t.isTypeOrSubTypeOf(baseType.getRawClass())) { return t; } } else { Class<?> cls; try { cls = getTypeFactory().findClass(subClassName); } catch (ClassNotFoundException e) { // let caller handle this problem return null; } catch (Exception e) { throw invalidTypeIdException(baseType, subClassName, String.format( "problem: (%s) %s", e.getClass().getName(), ClassUtil.exceptionMessage(e))); } if (baseType.isTypeOrSuperTypeOf(cls)) { return getTypeFactory().constructSpecializedType(baseType, cls); } } throw invalidTypeIdException(baseType, subClassName, "Not a subtype"); }
Lookup method similar to resolveSubType but one that also validates that resulting subtype is valid according to given PolymorphicTypeValidator.
Since:2.10
/** * Lookup method similar to {@link #resolveSubType} but one that also validates * that resulting subtype is valid according to given {@link PolymorphicTypeValidator}. * * @since 2.10 */
public JavaType resolveAndValidateSubType(JavaType baseType, String subClass, PolymorphicTypeValidator ptv) throws JsonMappingException { // Off-line the special case of generic (parameterized) type: final int ltIndex = subClass.indexOf('<'); if (ltIndex > 0) { return _resolveAndValidateGeneric(baseType, subClass, ptv, ltIndex); } final MapperConfig<?> config = getConfig(); PolymorphicTypeValidator.Validity vld = ptv.validateSubClassName(config, baseType, subClass); if (vld == Validity.DENIED) { return _throwSubtypeNameNotAllowed(baseType, subClass, ptv); } final Class<?> cls; try { cls = getTypeFactory().findClass(subClass); } catch (ClassNotFoundException e) { // let caller handle this problem return null; } catch (Exception e) { throw invalidTypeIdException(baseType, subClass, String.format( "problem: (%s) %s", e.getClass().getName(), ClassUtil.exceptionMessage(e))); } if (!baseType.isTypeOrSuperTypeOf(cls)) { return _throwNotASubtype(baseType, subClass); } final JavaType subType = config.getTypeFactory().constructSpecializedType(baseType, cls); // May skip check if type was allowed by subclass name already if (vld == Validity.INDETERMINATE) { vld = ptv.validateSubType(config, baseType, subType); if (vld != Validity.ALLOWED) { return _throwSubtypeClassNotAllowed(baseType, subClass, ptv); } } return subType; } private JavaType _resolveAndValidateGeneric(JavaType baseType, String subClass, PolymorphicTypeValidator ptv, int ltIndex) throws JsonMappingException { final MapperConfig<?> config = getConfig(); // 24-Apr-2019, tatu: Not 100% sure if we should pass name with type parameters // or not, but guessing it's more convenient not to have to worry about it so // strip out PolymorphicTypeValidator.Validity vld = ptv.validateSubClassName(config, baseType, subClass.substring(0, ltIndex)); if (vld == Validity.DENIED) { return _throwSubtypeNameNotAllowed(baseType, subClass, ptv); } JavaType subType = getTypeFactory().constructFromCanonical(subClass); if (!subType.isTypeOrSubTypeOf(baseType.getRawClass())) { return _throwNotASubtype(baseType, subClass); } // Unless we were approved already by name, check that actual sub-class acceptable: if (vld != Validity.ALLOWED) { if (ptv.validateSubType(config, baseType, subType) != Validity.ALLOWED) { return _throwSubtypeClassNotAllowed(baseType, subClass, ptv); } } return subType; } protected <T> T _throwNotASubtype(JavaType baseType, String subType) throws JsonMappingException { throw invalidTypeIdException(baseType, subType, "Not a subtype"); } protected <T> T _throwSubtypeNameNotAllowed(JavaType baseType, String subType, PolymorphicTypeValidator ptv) throws JsonMappingException { throw invalidTypeIdException(baseType, subType, "Configured `PolymorphicTypeValidator` (of type "+ClassUtil.classNameOf(ptv)+") denied resolution"); } protected <T> T _throwSubtypeClassNotAllowed(JavaType baseType, String subType, PolymorphicTypeValidator ptv) throws JsonMappingException { throw invalidTypeIdException(baseType, subType, "Configured `PolymorphicTypeValidator` (of type "+ClassUtil.classNameOf(ptv)+") denied resolution"); }
Helper method for constructing exception to indicate that given type id could not be resolved to a valid subtype of specified base type. Most commonly called during polymorphic deserialization.

Note that most of the time this method should NOT be called directly: instead, method handleUnknownTypeId() should be called which will call this method if necessary.

Since:2.9
/** * Helper method for constructing exception to indicate that given type id * could not be resolved to a valid subtype of specified base type. * Most commonly called during polymorphic deserialization. *<p> * Note that most of the time this method should NOT be called directly: instead, * method <code>handleUnknownTypeId()</code> should be called which will call this method * if necessary. * * @since 2.9 */
protected abstract JsonMappingException invalidTypeIdException(JavaType baseType, String typeId, String extraDesc); public abstract TypeFactory getTypeFactory(); /* /********************************************************** /* Helper object construction /********************************************************** */ public ObjectIdGenerator<?> objectIdGeneratorInstance(Annotated annotated, ObjectIdInfo objectIdInfo) throws JsonMappingException { Class<?> implClass = objectIdInfo.getGeneratorType(); final MapperConfig<?> config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); ObjectIdGenerator<?> gen = (hi == null) ? null : hi.objectIdGeneratorInstance(config, annotated, implClass); if (gen == null) { gen = (ObjectIdGenerator<?>) ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers()); } return gen.forScope(objectIdInfo.getScope()); } public ObjectIdResolver objectIdResolverInstance(Annotated annotated, ObjectIdInfo objectIdInfo) { Class<? extends ObjectIdResolver> implClass = objectIdInfo.getResolverType(); final MapperConfig<?> config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); ObjectIdResolver resolver = (hi == null) ? null : hi.resolverIdGeneratorInstance(config, annotated, implClass); if (resolver == null) { resolver = ClassUtil.createInstance(implClass, config.canOverrideAccessModifiers()); } return resolver; }
Helper method to use to construct a Converter, given a definition that may be either actual converter instance, or Class for instantiating one.
Since:2.2
/** * Helper method to use to construct a {@link Converter}, given a definition * that may be either actual converter instance, or Class for instantiating one. * * @since 2.2 */
@SuppressWarnings("unchecked") public Converter<Object,Object> converterInstance(Annotated annotated, Object converterDef) throws JsonMappingException { if (converterDef == null) { return null; } if (converterDef instanceof Converter<?,?>) { return (Converter<Object,Object>) converterDef; } if (!(converterDef instanceof Class)) { throw new IllegalStateException("AnnotationIntrospector returned Converter definition of type " +converterDef.getClass().getName()+"; expected type Converter or Class<Converter> instead"); } Class<?> converterClass = (Class<?>)converterDef; // there are some known "no class" markers to consider too: if (converterClass == Converter.None.class || ClassUtil.isBogusClass(converterClass)) { return null; } if (!Converter.class.isAssignableFrom(converterClass)) { throw new IllegalStateException("AnnotationIntrospector returned Class " +converterClass.getName()+"; expected Class<Converter>"); } final MapperConfig<?> config = getConfig(); HandlerInstantiator hi = config.getHandlerInstantiator(); Converter<?,?> conv = (hi == null) ? null : hi.converterInstance(config, annotated, converterClass); if (conv == null) { conv = (Converter<?,?>) ClassUtil.createInstance(converterClass, config.canOverrideAccessModifiers()); } return (Converter<Object,Object>) conv; } /* /********************************************************** /* Error reporting /********************************************************** */
Helper method called to indicate a generic problem that stems from type definition(s), not input data, or input/output state; typically this means throwing a InvalidDefinitionException.
Since:2.9
/** * Helper method called to indicate a generic problem that stems from type * definition(s), not input data, or input/output state; typically this * means throwing a {@link com.fasterxml.jackson.databind.exc.InvalidDefinitionException}. * * @since 2.9 */
public abstract <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException;
Since:2.9
/** * @since 2.9 */
public <T> T reportBadDefinition(Class<?> type, String msg) throws JsonMappingException { return reportBadDefinition(constructType(type), msg); } /* /********************************************************** /* Helper methods /********************************************************** */
Since:2.9
/** * @since 2.9 */
protected final String _format(String msg, Object... msgArgs) { if (msgArgs.length > 0) { return String.format(msg, msgArgs); } return msg; }
Since:2.9
/** * @since 2.9 */
protected final String _truncate(String desc) { if (desc == null) { return ""; } if (desc.length() <= MAX_ERROR_STR_LEN) { return desc; } return desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN); }
Since:2.9
/** * @since 2.9 */
protected String _quotedString(String desc) { if (desc == null) { return "[N/A]"; } // !!! should we quote it? (in case there are control chars, linefeeds) return String.format("\"%s\"", _truncate(desc)); }
Since:2.9
/** * @since 2.9 */
protected String _colonConcat(String msgBase, String extra) { if (extra == null) { return msgBase; } return msgBase + ": " + extra; }
Since:2.9
/** * @since 2.9 */
protected String _desc(String desc) { if (desc == null) { return "[N/A]"; } // !!! should we quote it? (in case there are control chars, linefeeds) return _truncate(desc); } }