Skip to content

Commit f4167ba

Browse files
committed
Updated PR
1 parent 955cfb6 commit f4167ba

File tree

3 files changed

+153
-58
lines changed

3 files changed

+153
-58
lines changed

ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -647,15 +647,39 @@ public void setTenantValue(EntityBean entityBean, Object tenantId) {
647647
setValue(entityBean, tenantId);
648648
}
649649

650+
/**
651+
* By default, getIntercept and setIntercept will check, if the passed bean is an instance of descriptor type.
652+
* <p>
653+
* If the property is not part of the type hierarchy (i.e. is this property from this descriptor)
654+
* an UnsuppoertedOperation is thrown.
655+
* <p>
656+
* If inheritance is involved, this method returns false instead of an exception, if the property might exist in
657+
* one of the child beans. This is necessary for getIntercept, as it returns <code>null</code> in this case.
658+
* @return true if property can be
659+
*/
660+
private boolean checkPropertyAccess(EntityBean bean) {
661+
if (bean == null || descriptor.type().isInstance(bean)) { // null = fall through - NPE is catched later.
662+
return true;
663+
}
664+
InheritInfo inheritInfo = descriptor.inheritInfo();
665+
if (inheritInfo == null || inheritInfo.isRoot() || !inheritInfo.getRoot().getType().isInstance(bean)) {
666+
throw new IllegalArgumentException(propertyIncomatibleMsg(bean));
667+
} else {
668+
return false;
669+
}
670+
}
671+
672+
private String propertyIncomatibleMsg(EntityBean bean) {
673+
String beanType = bean == null ? "null" : bean.getClass().getName();
674+
return "Property " + name + " on [" + descriptor + "] is incompatible with type[" + beanType + "]";
675+
}
676+
650677
/**
651678
* Set the value of the property without interception or
652679
* PropertyChangeSupport.
653680
*/
654681
public void setValue(EntityBean bean, Object value) {
655682
try {
656-
if (!beanHasProperty(bean)) {
657-
throw new IllegalArgumentException("Property does not exist");
658-
}
659683
setter.set(bean, value);
660684
} catch (Exception ex) {
661685
throw new RuntimeException(setterErrorMsg(bean, value, "set "), ex);
@@ -666,10 +690,10 @@ public void setValue(EntityBean bean, Object value) {
666690
* Set the value of the property.
667691
*/
668692
public void setValueIntercept(EntityBean bean, Object value) {
693+
if (!checkPropertyAccess(bean)) {
694+
throw new IllegalArgumentException(propertyIncomatibleMsg(bean));
695+
}
669696
try {
670-
if (!beanHasProperty(bean)) {
671-
throw new IllegalArgumentException("Property does not exist");
672-
}
673697
setter.setIntercept(bean, value);
674698
} catch (Exception ex) {
675699
throw new RuntimeException(setterErrorMsg(bean, value, "setIntercept "), ex);
@@ -766,18 +790,12 @@ public Object value(Object bean) {
766790
return getValueIntercept((EntityBean) bean);
767791
}
768792

769-
private boolean beanHasProperty(EntityBean bean) {
770-
return descriptor.inheritInfo() == null // fast exit for non inherited beans
771-
|| owningType == null
772-
|| owningType.isInstance(bean);
773-
}
774-
775793
/**
776794
* Return the value of the property method.
777795
*/
778796
public Object getValue(EntityBean bean) {
779797
try {
780-
return beanHasProperty(bean) ? getter.get(bean) : null;
798+
return getter.get(bean);
781799
} catch (Exception ex) {
782800
String beanType = bean == null ? "null" : bean.getClass().getName();
783801
String msg = "get " + name + " on [" + descriptor + "] type[" + beanType + "] threw error.";
@@ -786,8 +804,11 @@ public Object getValue(EntityBean bean) {
786804
}
787805

788806
public Object getValueIntercept(EntityBean bean) {
807+
if (!checkPropertyAccess(bean)) {
808+
return null;
809+
}
789810
try {
790-
return beanHasProperty(bean) ? getter.getIntercept(bean) : null;
811+
return getter.getIntercept(bean);
791812
} catch (Exception ex) {
792813
String beanType = bean == null ? "null" : bean.getClass().getName();
793814
String msg = "getIntercept " + name + " on [" + descriptor + "] type[" + beanType + "] threw error.";

ebean-test/src/test/java/org/tests/inheritance/TestInheritancePropertyAccess.java

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package org.tests.inheritance;
2+
3+
import io.ebean.DB;
4+
import io.ebean.plugin.ExpressionPath;
5+
import org.junit.jupiter.api.Test;
6+
import org.tests.model.basic.*;
7+
8+
import java.sql.Timestamp;
9+
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
12+
13+
/**
14+
* @author Roland Praml, FOCONIS AG
15+
*/
16+
public class TestPropertyAccess {
17+
18+
19+
private ExpressionPath custCretime = DB.getDefault().pluginApi().beanType(Customer.class).expressionPath("cretime");
20+
private ExpressionPath custName = DB.getDefault().pluginApi().beanType(Customer.class).expressionPath("name");
21+
// Note: Animal.name is only present in "Cat" not in "Dog"
22+
private ExpressionPath animalName = DB.getDefault().pluginApi().beanType(Animal.class).expressionPath("name");
23+
private ExpressionPath productName = DB.getDefault().pluginApi().beanType(Product.class).expressionPath("name");
24+
private ExpressionPath animalSpecies = DB.getDefault().pluginApi().beanType(Animal.class).expressionPath("species");
25+
26+
@Test
27+
void testOnInheritance() {
28+
Cat cat = new Cat();
29+
cat.setName("Tom");
30+
DB.save(cat);
31+
32+
Dog dog = new Dog();
33+
dog.setRegistrationNumber("FOO");
34+
DB.save(dog);
35+
36+
37+
Animal animal = DB.find(Animal.class, cat.getId());
38+
assertThat(animalName.pathGet(animal)).isEqualTo("Tom");
39+
40+
animal = DB.find(Animal.class, dog.getId());
41+
assertThat(animalName.pathGet(animal)).isNull();
42+
43+
animalName.pathSet(cat, "Jerry");
44+
assertThat(cat.getName()).isEqualTo("Jerry");
45+
46+
assertThatThrownBy(() -> animalName.pathSet(dog, "Jerry"))
47+
.isInstanceOf(IllegalArgumentException.class);
48+
49+
animalSpecies.pathSet(cat, "Angora");
50+
animalSpecies.pathSet(dog, "Bulldog");
51+
52+
assertThat(cat.getSpecies()).isEqualTo("Angora");
53+
assertThat(dog.getSpecies()).isEqualTo("Bulldog");
54+
}
55+
56+
@Test
57+
void testOnMappedSuperClass() {
58+
Customer cust = new Customer();
59+
60+
Timestamp ts = new Timestamp(123);
61+
custCretime.pathSet(cust, ts);
62+
assertThat(custCretime.pathGet(cust)).isEqualTo(ts);
63+
64+
custName.pathSet(cust, "Roland");
65+
assertThat(custName.pathGet(cust)).isEqualTo("Roland");
66+
67+
}
68+
69+
@Test
70+
void testOnPlainBean() {
71+
Product product = new Product();
72+
73+
productName.pathSet(product, "Roland");
74+
assertThat(productName.pathGet(product)).isEqualTo("Roland");
75+
}
76+
77+
@Test
78+
void testOnContactGroup() {
79+
ContactGroup cg = new ContactGroup();
80+
81+
// CHECKEM: Ist it OK to us the "custCretime" on "contactGroup"
82+
assertThatThrownBy(() -> custCretime.pathGet(cg)).isInstanceOf(IllegalArgumentException.class);
83+
}
84+
85+
@Test
86+
void testOnCrossUsage() {
87+
Product product = new Product();
88+
Customer cust = new Customer();
89+
Cat cat = new Cat();
90+
Dog dog = new Dog();
91+
92+
93+
assertThatThrownBy(() -> custCretime.pathGet(product)).isInstanceOf(IllegalArgumentException.class);
94+
custCretime.pathGet(cust);
95+
assertThatThrownBy(() -> custCretime.pathGet(cat)).isInstanceOf(IllegalArgumentException.class);
96+
assertThatThrownBy(() -> custCretime.pathGet(dog)).isInstanceOf(IllegalArgumentException.class);
97+
98+
assertThatThrownBy(() -> custName.pathGet(product)).isInstanceOf(IllegalArgumentException.class);
99+
custName.pathGet(cust);
100+
assertThatThrownBy(() -> custName.pathGet(cat)).isInstanceOf(IllegalArgumentException.class);
101+
assertThatThrownBy(() -> custName.pathGet(dog)).isInstanceOf(IllegalArgumentException.class);
102+
103+
assertThatThrownBy(() -> animalName.pathGet(product)).isInstanceOf(IllegalArgumentException.class);
104+
assertThatThrownBy(() -> animalName.pathGet(cust)).isInstanceOf(IllegalArgumentException.class);
105+
animalName.pathGet(cat);
106+
animalName.pathGet(dog);
107+
108+
productName.pathGet(product);
109+
assertThatThrownBy(() -> productName.pathGet(cust)).isInstanceOf(IllegalArgumentException.class);
110+
assertThatThrownBy(() -> productName.pathGet(cat)).isInstanceOf(IllegalArgumentException.class);
111+
assertThatThrownBy(() -> productName.pathGet(dog)).isInstanceOf(IllegalArgumentException.class);
112+
113+
assertThatThrownBy(() -> animalSpecies.pathGet(product)).isInstanceOf(IllegalArgumentException.class);
114+
assertThatThrownBy(() -> animalSpecies.pathGet(cust)).isInstanceOf(IllegalArgumentException.class);
115+
animalSpecies.pathGet(cat);
116+
animalSpecies.pathGet(dog);
117+
}
118+
}

0 commit comments

Comments
 (0)