Skip to content

Commit 8dbf55f

Browse files
committed
Cleaning up #877 fix for 2.8.3, by deferring access-forcing at a later point
1 parent e9ade49 commit 8dbf55f

14 files changed

+160
-89
lines changed

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java

+71-24
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,22 @@ public class BeanDeserializerBuilder
2020
{
2121
/*
2222
/**********************************************************
23-
/* General information about POJO
23+
/* Configuration
2424
/**********************************************************
2525
*/
2626

27-
/**
28-
* Introspected information about POJO for deserializer to handle
29-
*/
30-
final protected BeanDescription _beanDesc;
27+
final protected DeserializationConfig _config;
3128

32-
/**
33-
* Whether default setting for properties without any view annotations
34-
* is to include (true) or exclude (false).
29+
/*
30+
/**********************************************************
31+
/* General information about POJO
32+
/**********************************************************
3533
*/
36-
final protected boolean _defaultViewInclusion;
3734

3835
/**
39-
* Flag that indicates whether default settings suggest use of case-insensitive
40-
* property comparison or not.
36+
* Introspected information about POJO for deserializer to handle
4137
*/
42-
final protected boolean _caseInsensitivePropertyComparison;
38+
final protected BeanDescription _beanDesc;
4339

4440
/*
4541
/**********************************************************
@@ -114,8 +110,7 @@ public BeanDeserializerBuilder(BeanDescription beanDesc,
114110
DeserializationConfig config)
115111
{
116112
_beanDesc = beanDesc;
117-
_defaultViewInclusion = config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
118-
_caseInsensitivePropertyComparison = config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
113+
_config = config;
119114
}
120115

121116
/**
@@ -125,8 +120,7 @@ public BeanDeserializerBuilder(BeanDescription beanDesc,
125120
protected BeanDeserializerBuilder(BeanDeserializerBuilder src)
126121
{
127122
_beanDesc = src._beanDesc;
128-
_defaultViewInclusion = src._defaultViewInclusion;
129-
_caseInsensitivePropertyComparison = src._caseInsensitivePropertyComparison;
123+
_config = src._config;
130124

131125
// let's make copy of properties
132126
_properties.putAll(src._properties);
@@ -205,6 +199,11 @@ public void addInjectable(PropertyName propName, JavaType propType,
205199
if (_injectables == null) {
206200
_injectables = new ArrayList<ValueInjector>();
207201
}
202+
boolean fixAccess = _config.canOverrideAccessModifiers();
203+
boolean forceAccess = fixAccess && _config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
204+
if (fixAccess) {
205+
member.fixAccess(forceAccess);
206+
}
208207
_injectables.add(new ValueInjector(propName, propType,
209208
contextAnnotations, member, valueId));
210209
}
@@ -314,7 +313,7 @@ public AnnotatedMethod getBuildMethod() {
314313
public JsonPOJOBuilder.Value getBuilderConfig() {
315314
return _builderConfig;
316315
}
317-
316+
318317
/*
319318
/**********************************************************
320319
/* Build method(s)
@@ -328,14 +327,16 @@ public JsonPOJOBuilder.Value getBuilderConfig() {
328327
public JsonDeserializer<?> build()
329328
{
330329
Collection<SettableBeanProperty> props = _properties.values();
331-
BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _caseInsensitivePropertyComparison);
330+
_fixAccess(props);
331+
332+
BeanPropertyMap propertyMap = BeanPropertyMap.construct(props,
333+
_config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
332334
propertyMap.assignIndexes();
333335

334336
// view processing must be enabled if:
335337
// (a) fields are not included by default (when deserializing with view), OR
336338
// (b) one of properties has view(s) to included in defined
337-
boolean anyViews = !_defaultViewInclusion;
338-
339+
boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
339340
if (!anyViews) {
340341
for (SettableBeanProperty prop : props) {
341342
if (prop.hasViews()) {
@@ -382,8 +383,10 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
382383
if (_buildMethod == null) {
383384
// as per [databind#777], allow empty name
384385
if (!expBuildMethodName.isEmpty()) {
385-
throw new IllegalArgumentException("Builder class "+_beanDesc.getBeanClass().getName()
386-
+" does not have build method (name: '"+expBuildMethodName+"')");
386+
throw new IllegalArgumentException(String.format(
387+
"Builder class %s does not have build method (name: '%s')",
388+
_beanDesc.getBeanClass().getName(),
389+
expBuildMethodName));
387390
}
388391
} else {
389392
// also: type of the method must be compatible
@@ -399,10 +402,12 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
399402
}
400403
// And if so, we can try building the deserializer
401404
Collection<SettableBeanProperty> props = _properties.values();
402-
BeanPropertyMap propertyMap = BeanPropertyMap.construct(props, _caseInsensitivePropertyComparison);
405+
_fixAccess(props);
406+
BeanPropertyMap propertyMap = BeanPropertyMap.construct(props,
407+
_config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
403408
propertyMap.assignIndexes();
404409

405-
boolean anyViews = !_defaultViewInclusion;
410+
boolean anyViews = !_config.isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION);
406411

407412
if (!anyViews) {
408413
for (SettableBeanProperty prop : props) {
@@ -427,4 +432,46 @@ public JsonDeserializer<?> buildBuilderBased(JavaType valueType,
427432
_beanDesc, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown,
428433
anyViews);
429434
}
435+
436+
/*
437+
/**********************************************************
438+
/* Internal helper method(s)
439+
/**********************************************************
440+
*/
441+
442+
private void _fixAccess(Collection<SettableBeanProperty> mainProps)
443+
{
444+
/* 07-Sep-2016, tatu: Ideally we should be able to avoid forcing
445+
* access to properties that are likely ignored, but due to
446+
* renaming it seems this is not a safe thing to do (there was
447+
* at least one failing test). May need to dig deeper in future;
448+
* for now let's just play it safe.
449+
*/
450+
/*
451+
Set<String> ignorable = _ignorableProps;
452+
if (ignorable == null) {
453+
ignorable = Collections.emptySet();
454+
}
455+
*/
456+
for (SettableBeanProperty prop : mainProps) {
457+
/*
458+
// first: no point forcing access on to-be-ignored properties
459+
if (ignorable.contains(prop.getName())) {
460+
continue;
461+
}
462+
*/
463+
prop.fixAccess(_config);
464+
}
465+
if (_backRefProperties != null) {
466+
for (SettableBeanProperty prop : _backRefProperties.values()) {
467+
prop.fixAccess(_config);
468+
}
469+
}
470+
if (_anySetter != null) {
471+
_anySetter.fixAccess(_config);
472+
}
473+
if (_buildMethod != null) {
474+
_buildMethod.fixAccess(_config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
475+
}
476+
}
430477
}

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java

+2-29
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ public JsonDeserializer<Object> buildBeanDeserializer(DeserializationContext ctx
231231
addInjectables(ctxt, beanDesc, builder);
232232

233233
final DeserializationConfig config = ctxt.getConfig();
234-
// [JACKSON-440]: update builder now that all information is in?
235234
if (_factoryConfig.hasDeserializerModifiers()) {
236235
for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
237236
builder = mod.updateBuilder(config, beanDesc, builder);
@@ -640,8 +639,8 @@ protected void addReferenceProperties(DeserializationContext ctxt,
640639
}
641640
SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(
642641
ctxt.getConfig(), m);
643-
builder.addBackReferenceProperty(name, constructSettableProperty(
644-
ctxt, beanDesc, propDef, type));
642+
builder.addBackReferenceProperty(name, constructSettableProperty(ctxt,
643+
beanDesc, propDef, type));
645644
}
646645
}
647646
}
@@ -656,13 +655,8 @@ protected void addInjectables(DeserializationContext ctxt,
656655
{
657656
Map<Object, AnnotatedMember> raw = beanDesc.findInjectables();
658657
if (raw != null) {
659-
boolean fixAccess = ctxt.canOverrideAccessModifiers();
660-
boolean forceAccess = fixAccess && ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
661658
for (Map.Entry<Object, AnnotatedMember> entry : raw.entrySet()) {
662659
AnnotatedMember m = entry.getValue();
663-
if (fixAccess) {
664-
m.fixAccess(forceAccess); // to ensure we can call it
665-
}
666660
builder.addInjectable(PropertyName.construct(m.getName()),
667661
m.getType(),
668662
beanDesc.getClassAnnotations(), m, entry.getKey());
@@ -683,10 +677,6 @@ protected SettableAnyProperty constructAnySetter(DeserializationContext ctxt,
683677
BeanDescription beanDesc, AnnotatedMember mutator)
684678
throws JsonMappingException
685679
{
686-
if (ctxt.canOverrideAccessModifiers()) {
687-
mutator.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); // to ensure we can call it
688-
}
689-
690680
//find the java type based on the annotated setter method or setter field
691681
JavaType type = null;
692682
if (mutator instanceof AnnotatedMethod) {
@@ -729,19 +719,6 @@ protected SettableBeanProperty constructSettableProperty(DeserializationContext
729719
{
730720
// need to ensure method is callable (for non-public)
731721
AnnotatedMember mutator = propDef.getNonConstructorMutator();
732-
733-
if (ctxt.canOverrideAccessModifiers()) {
734-
// [databind#877]: explicitly prevent forced access to `cause` of `Throwable`;
735-
// never needed and attempts may cause problems on some platforms.
736-
// !!! NOTE: should be handled better for 2.8 and later
737-
if ((mutator instanceof AnnotatedField)
738-
&& "cause".equals(mutator.getName())
739-
&& Throwable.class.isAssignableFrom(propType0.getRawClass())) {
740-
;
741-
} else {
742-
mutator.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
743-
}
744-
}
745722
JavaType type = resolveMemberAndTypeAnnotations(ctxt, mutator, propType0);
746723
// Does the Method specify the deserializer to use? If so, let's use it.
747724
TypeDeserializer typeDeser = type.getTypeHandler();
@@ -782,10 +759,6 @@ protected SettableBeanProperty constructSetterlessProperty(DeserializationContex
782759
throws JsonMappingException
783760
{
784761
final AnnotatedMethod getter = propDef.getGetter();
785-
// need to ensure it is callable now:
786-
if (ctxt.canOverrideAccessModifiers()) {
787-
getter.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
788-
}
789762
JavaType type = resolveMemberAndTypeAnnotations(ctxt, getter, getter.getType());
790763
TypeDeserializer typeDeser = type.getTypeHandler();
791764
SettableBeanProperty prop = new SetterlessProperty(propDef, type, typeDeser,

src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import java.lang.annotation.Annotation;
55

66
import com.fasterxml.jackson.core.JsonParser;
7-
import com.fasterxml.jackson.core.JsonProcessingException;
7+
88
import com.fasterxml.jackson.databind.*;
99
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
1010
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
@@ -114,6 +114,13 @@ public CreatorProperty withValueDeserializer(JsonDeserializer<?> deser) {
114114
return new CreatorProperty(this, deser);
115115
}
116116

117+
@Override
118+
public void fixAccess(DeserializationConfig config) {
119+
if (_fallbackSetter != null) {
120+
_fallbackSetter.fixAccess(config);
121+
}
122+
}
123+
117124
/**
118125
* NOTE: one exception to immutability, due to problems with CreatorProperty instances
119126
* being shared between Bean, separate PropertyBasedCreator
@@ -173,19 +180,17 @@ public <A extends Annotation> A getAnnotation(Class<A> acls) {
173180
*/
174181

175182
@Override
176-
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
177-
Object instance)
178-
throws IOException, JsonProcessingException
183+
public void deserializeAndSet(JsonParser p, DeserializationContext ctxt,
184+
Object instance) throws IOException
179185
{
180-
set(instance, deserialize(jp, ctxt));
186+
set(instance, deserialize(p, ctxt));
181187
}
182188

183189
@Override
184-
public Object deserializeSetAndReturn(JsonParser jp,
185-
DeserializationContext ctxt, Object instance)
186-
throws IOException, JsonProcessingException
190+
public Object deserializeSetAndReturn(JsonParser p,
191+
DeserializationContext ctxt, Object instance) throws IOException
187192
{
188-
return setAndReturn(instance, deserialize(jp, ctxt));
193+
return setAndReturn(instance, deserialize(p, ctxt));
189194
}
190195

191196
@Override

src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,6 @@ public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaTy
5959
_valueTypeDeserializer = typeDeser;
6060
_setterIsField = setter instanceof AnnotatedField;
6161
}
62-
63-
public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) {
64-
return new SettableAnyProperty(_property, _setter, _type,
65-
deser, _valueTypeDeserializer);
66-
}
6762

6863
/**
6964
* Constructor used for JDK Serialization when reading persisted object
@@ -78,6 +73,16 @@ protected SettableAnyProperty(SettableAnyProperty src)
7873
_setterIsField = src._setterIsField;
7974
}
8075

76+
public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) {
77+
return new SettableAnyProperty(_property, _setter, _type,
78+
deser, _valueTypeDeserializer);
79+
}
80+
81+
public void fixAccess(DeserializationConfig config) {
82+
_setter.fixAccess(
83+
config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
84+
}
85+
8186
/*
8287
/**********************************************************
8388
/* JDK serialization handling

src/main/java/com/fasterxml/jackson/databind/deser/SettableBeanProperty.java

+14-5
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
import java.lang.annotation.Annotation;
55

66
import com.fasterxml.jackson.core.*;
7+
78
import com.fasterxml.jackson.databind.*;
89
import com.fasterxml.jackson.databind.deser.impl.FailingDeserializer;
9-
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
10-
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
11-
import com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase;
12-
import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
10+
import com.fasterxml.jackson.databind.introspect.*;
1311
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
1412
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
1513
import com.fasterxml.jackson.databind.util.Annotations;
@@ -309,7 +307,18 @@ public void assignIndex(int index) {
309307
}
310308
_propertyIndex = index;
311309
}
312-
310+
311+
/**
312+
* Method called to ensure that the mutator has proper access rights to
313+
* be called, as per configuration. Overridden by implementations that
314+
* have mutators that require access, fields and setters.
315+
*
316+
* @since 2.8.3
317+
*/
318+
public void fixAccess(DeserializationConfig config) {
319+
;
320+
}
321+
313322
/*
314323
/**********************************************************
315324
/* BeanProperty impl

src/main/java/com/fasterxml/jackson/databind/deser/impl/FieldProperty.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
1313
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
1414
import com.fasterxml.jackson.databind.util.Annotations;
15+
import com.fasterxml.jackson.databind.util.ClassUtil;
1516

1617
/**
1718
* This concrete sub-class implements property that is set
@@ -74,7 +75,13 @@ public FieldProperty withName(PropertyName newName) {
7475
public FieldProperty withValueDeserializer(JsonDeserializer<?> deser) {
7576
return new FieldProperty(this, deser);
7677
}
77-
78+
79+
@Override
80+
public void fixAccess(DeserializationConfig config) {
81+
ClassUtil.checkAndFixAccess(_field,
82+
config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
83+
}
84+
7885
/*
7986
/**********************************************************
8087
/* BeanProperty impl

src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java

+5
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ public InnerClassProperty withValueDeserializer(JsonDeserializer<?> deser) {
8484
return new InnerClassProperty(this, deser);
8585
}
8686

87+
@Override
88+
public void fixAccess(DeserializationConfig config) {
89+
_delegate.fixAccess(config);
90+
}
91+
8792
// // // BeanProperty impl
8893

8994
@Override

0 commit comments

Comments
 (0)