SLING-7404 - ObjectModel and similar classes need consistent null checks
(closes #2)
diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/util/ObjectModel.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/util/ObjectModel.java
index ea6eb2a..f852f03 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/compiler/util/ObjectModel.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/util/ObjectModel.java
@@ -42,6 +42,7 @@
public final class ObjectModel {
private static final Logger LOGGER = LoggerFactory.getLogger(ObjectModel.class);
+ private static final String EMPTY_STRING = "";
/**
* A {@link Set} that stores all the supported primitive classes.
@@ -153,7 +154,7 @@
}
String s = object.toString().trim();
- if ("".equals(s)) {
+ if (EMPTY_STRING.equals(s)) {
return false;
} else if ("true".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s)) {
return Boolean.parseBoolean(s);
@@ -217,7 +218,7 @@
* @return the string representation of the object or an empty string
*/
public static String toString(Object object) {
- String output = "";
+ String output = EMPTY_STRING;
if (object != null) {
if (object instanceof String) {
output = (String) object;
@@ -298,8 +299,11 @@
* @return the CSV; if the {@code collection} is empty then an empty string will be returned
*/
public static String collectionToString(Collection<?> collection) {
+ if (collection == null) {
+ return EMPTY_STRING;
+ }
StringBuilder builder = new StringBuilder();
- String prefix = "";
+ String prefix = EMPTY_STRING;
for (Object o : collection) {
builder.append(prefix).append(toString(o));
prefix = ",";
@@ -314,6 +318,9 @@
* @return a collection with the iterator's elements
*/
public static Collection<Object> fromIterator(Iterator<Object> iterator) {
+ if (iterator == null) {
+ return Collections.EMPTY_LIST;
+ }
ArrayList<Object> result = new ArrayList<>();
while (iterator.hasNext()) {
result.add(iterator.next());
@@ -330,6 +337,9 @@
* @return the value stored at the {@code index} or {@code null}
*/
public static Object getIndex(Object object, int index) {
+ if (object == null) {
+ return null;
+ }
Class<?> cls = object.getClass();
if (cls.isArray() && index >= 0 && index < Array.getLength(object)) {
return Array.get(object, index);
@@ -349,6 +359,9 @@
* @return the value of the field or {@code null} if the field was not found
*/
public static Object getField(Object object, String fieldName) {
+ if (object == null || StringUtils.isEmpty(fieldName)) {
+ return null;
+ }
Class<?> cls = object.getClass();
if (cls.isArray() && "length".equals(fieldName)) {
return Array.getLength(object);
@@ -370,6 +383,9 @@
* @return the invocation's result or {@code null} if such a method cannot be found
*/
public static Object invokeBeanMethod(Object object, String methodName) {
+ if (object == null || StringUtils.isEmpty(methodName)) {
+ return null;
+ }
Class<?> cls = object.getClass();
Method method = findBeanMethod(cls, methodName);
if (method != null) {
@@ -396,6 +412,9 @@
* @return a method that matches the criteria or {@code null}
*/
public static Method findBeanMethod(Class<?> cls, String baseName) {
+ if (cls == null || StringUtils.isEmpty(baseName)) {
+ return null;
+ }
Method[] publicMethods = cls.getMethods();
String capitalized = StringUtils.capitalize(baseName);
for (Method method : publicMethods) {
@@ -421,6 +440,9 @@
* {@link Object#toString()}, {@code false} otherwise
*/
public static boolean isMethodAllowed(Method method) {
+ if (method == null) {
+ return false;
+ }
Class<?> declaringClass = method.getDeclaringClass();
return declaringClass != Object.class || TO_STRING_METHOD.equals(method.getName());
}
diff --git a/src/test/java/org/apache/sling/scripting/sightly/util/ObjectModelTest.java b/src/test/java/org/apache/sling/scripting/sightly/util/ObjectModelTest.java
index d3e0924..eb16513 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/util/ObjectModelTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/util/ObjectModelTest.java
@@ -122,6 +122,7 @@
@Test
public void testCollectionToString() {
+ assertEquals("", ObjectModel.collectionToString(null));
Integer[] testArray = new Integer[] {1, 2, 3};
List testList = Arrays.asList(testArray);
assertEquals("1,2,3", ObjectModel.collectionToString(testList));
@@ -129,6 +130,7 @@
@Test
public void testFromIterator() {
+ assertTrue(ObjectModel.fromIterator(null).isEmpty());
Integer[] testArray = new Integer[] {1, 2, 3};
List testList = Arrays.asList(testArray);
assertEquals(testList, ObjectModel.fromIterator(testList.iterator()));
@@ -136,8 +138,10 @@
@Test
public void testResolveProperty() {
- assertEquals(0, ObjectModel.resolveProperty(Collections.EMPTY_LIST, "size"));
+ assertNull(ObjectModel.resolveProperty(null, 0));
+ assertNull(ObjectModel.resolveProperty(this, null));
assertNull(ObjectModel.resolveProperty(null, null));
+ assertEquals(0, ObjectModel.resolveProperty(Collections.EMPTY_LIST, "size"));
Integer[] testArray = new Integer[] {1, 2, 3};
assertEquals(2, ObjectModel.resolveProperty(testArray, 1));
assertNull(ObjectModel.resolveProperty(testArray, 3));
@@ -173,6 +177,7 @@
@Test
public void testGetIndex() {
+ assertNull(ObjectModel.getIndex(null, 0));
Integer[] testArray = new Integer[] {1, 2, 3};
assertEquals(2, ObjectModel.getIndex(testArray, 1));
assertNull(ObjectModel.getIndex(testArray, 3));
@@ -189,6 +194,19 @@
assertNull(ObjectModel.getIndex(stringMap, 2));
}
+ @Test
+ public void testClassBasedMethodsForNulls() {
+ assertNull(ObjectModel.getField(null, null));
+ assertNull(ObjectModel.getField("", null));
+ assertNull(ObjectModel.getField(this, ""));
+ assertNull(ObjectModel.findBeanMethod(null, null));
+ assertNull(ObjectModel.findBeanMethod(this.getClass(), null));
+ assertNull(ObjectModel.findBeanMethod(this.getClass(), ""));
+ assertNull(ObjectModel.invokeBeanMethod(null, null));
+ assertNull(ObjectModel.invokeBeanMethod(this, null));
+ assertNull(ObjectModel.invokeBeanMethod(this, ""));
+ }
+
private class Bag<T> implements Iterable<T> {