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> {