Skip to content

Commit d7975d4

Browse files
Copilotanidotnet
andcommitted
Address code review feedback in FieldAccessHelper
- Added null/empty checks for propertyName to prevent StringIndexOutOfBoundsException - Added support for 'is' prefix in getter method lookup for boolean properties - Extracted capitalizePropertyName helper method to eliminate code duplication - Created findGetterMethod to handle both 'get' and 'is' prefixed getters - All tests still pass (1623 tests) Co-authored-by: anidotnet <[email protected]>
1 parent 1d74e68 commit d7975d4

File tree

1 file changed

+48
-12
lines changed

1 file changed

+48
-12
lines changed

nitrite/src/main/java/org/dizitart/no2/repository/FieldAccessHelper.java

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,38 @@ static void set(Field field, Object obj, Object value) throws IllegalAccessExcep
7474
* Gets a property value from an object, trying both field access and getter method.
7575
*/
7676
private static Object getPropertyValue(Object obj, String propertyName) throws IllegalAccessException {
77+
if (propertyName == null || propertyName.isEmpty()) {
78+
throw new IllegalAccessException("Property name cannot be null or empty");
79+
}
80+
7781
// Try to find the field in the object's class
7882
Field realField = findFieldInHierarchy(obj.getClass(), propertyName);
7983
if (realField != null) {
8084
realField.setAccessible(true);
8185
return realField.get(obj);
8286
}
8387

84-
// Fall back to getter method
88+
// Fall back to getter method - try both 'get' and 'is' prefixes
8589
try {
86-
String getterName = "get" + Character.toUpperCase(propertyName.charAt(0));
87-
if (propertyName.length() > 1) {
88-
getterName += propertyName.substring(1);
90+
Method getter = findGetterMethod(obj.getClass(), propertyName);
91+
if (getter != null) {
92+
getter.setAccessible(true);
93+
return getter.invoke(obj);
8994
}
90-
Method getter = obj.getClass().getMethod(getterName);
91-
getter.setAccessible(true);
92-
return getter.invoke(obj);
95+
throw new IllegalAccessException("No getter method found for property '" + propertyName + "'");
9396
} catch (Exception e) {
94-
throw new IllegalAccessException("Cannot access property '" + propertyName + "' on " + obj.getClass().getName());
97+
throw new IllegalAccessException("Cannot access property '" + propertyName + "' on " + obj.getClass().getName() + ": " + e.getMessage());
9598
}
9699
}
97100

98101
/**
99102
* Sets a property value on an object, trying both field access and setter method.
100103
*/
101104
private static void setPropertyValue(Object obj, String propertyName, Object value) throws IllegalAccessException {
105+
if (propertyName == null || propertyName.isEmpty()) {
106+
throw new IllegalAccessException("Property name cannot be null or empty");
107+
}
108+
102109
// Try to find the field in the object's class
103110
Field realField = findFieldInHierarchy(obj.getClass(), propertyName);
104111
if (realField != null) {
@@ -109,10 +116,7 @@ private static void setPropertyValue(Object obj, String propertyName, Object val
109116

110117
// Fall back to setter method
111118
try {
112-
String setterName = "set" + Character.toUpperCase(propertyName.charAt(0));
113-
if (propertyName.length() > 1) {
114-
setterName += propertyName.substring(1);
115-
}
119+
String setterName = "set" + capitalizePropertyName(propertyName);
116120
Method setter = findSetterMethod(obj.getClass(), setterName, value);
117121
if (setter != null) {
118122
setter.setAccessible(true);
@@ -124,6 +128,38 @@ private static void setPropertyValue(Object obj, String propertyName, Object val
124128
throw new IllegalAccessException("Cannot set property '" + propertyName + "' on " + obj.getClass().getName() + ": " + e.getMessage());
125129
}
126130
}
131+
132+
/**
133+
* Finds a getter method for a property (tries both 'get' and 'is' prefixes).
134+
*/
135+
private static Method findGetterMethod(Class<?> clazz, String propertyName) {
136+
String capitalizedName = capitalizePropertyName(propertyName);
137+
String getterName = "get" + capitalizedName;
138+
String isGetterName = "is" + capitalizedName;
139+
140+
Method[] methods = clazz.getMethods();
141+
for (Method method : methods) {
142+
if ((method.getName().equals(getterName) || method.getName().equals(isGetterName))
143+
&& method.getParameterTypes().length == 0) {
144+
return method;
145+
}
146+
}
147+
return null;
148+
}
149+
150+
/**
151+
* Capitalizes a property name following JavaBeans conventions.
152+
*/
153+
private static String capitalizePropertyName(String propertyName) {
154+
if (propertyName == null || propertyName.isEmpty()) {
155+
return propertyName;
156+
}
157+
// Follow JavaBeans convention: if first two chars are uppercase, don't change
158+
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(0)) && Character.isUpperCase(propertyName.charAt(1))) {
159+
return propertyName;
160+
}
161+
return Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
162+
}
127163

128164
/**
129165
* Finds a field in the class hierarchy.

0 commit comments

Comments
 (0)