SLING-10086 : Validate configuration properties case-insensitive
diff --git a/pom.xml b/pom.xml
index 20b2365..4b101f8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.cm.json</artifactId>
+            <version>1.0.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature</artifactId>
             <version>1.2.18</version>
@@ -83,12 +89,6 @@
             <version>1.2</version>
             <scope>provided</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.cm.json</artifactId>
-            <version>1.0.2</version>
-            <scope>provided</scope>
-        </dependency>
 
         <!-- Testing -->
         <dependency>
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMap.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMap.java
deleted file mode 100644
index d7af7ad..0000000
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMap.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sling.feature.extension.apiregions.api.config;
-
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-class CaseInsensitiveMap<T> implements Map<String, T> {
-    
-    private final Map<CaseInsensitiveKey, T> map = new LinkedHashMap<>();
-
-	@Override
-	public void clear() {
-		this.map.clear();		
-	}
-
-	@Override
-	public boolean containsKey(final Object key) {
-		return this.map.containsKey(new CaseInsensitiveKey(key.toString()));
-	}
-
-	@Override
-	public boolean containsValue(final Object value) {
-		return this.map.containsValue(value);
-	}
-
-	@Override
-	public Set<Entry<String, T>> entrySet() {
-		return new EntrySet();
-	}
-
-	@Override
-	public T get(final Object key) {
-        final CaseInsensitiveKey k = new CaseInsensitiveKey(key.toString());
-        return this.map.get(k);
-	}
-
-	@Override
-	public boolean isEmpty() {
-		return this.map.isEmpty();
-	}
-
-	@Override
-	public Set<String> keySet() {
-		return new KeySet();
-	}
-
-	@Override
-	public T put(final String key, final T value) {
-        final CaseInsensitiveKey k = new CaseInsensitiveKey(key.toString());
-        final T old = this.map.remove(k);
-        this.map.put(k, value);
-        return old;
-	}
-
-	@Override
-	public void putAll(final Map<? extends String, ? extends T> m) {
-		for(final Map.Entry<? extends String, ? extends T> entry : m.entrySet()) {
-            this.put(entry.getKey(), entry.getValue());
-        }		
-	}
-
-	@Override
-	public T remove(final Object key) {
-        final CaseInsensitiveKey k = new CaseInsensitiveKey(key.toString());
-        return this.map.remove(k);
-	}
-
-	@Override
-	public int size() {
-		return this.map.size();
-	}
-
-	@Override
-	public Collection<T> values() {
-		return this.map.values();
-    } 
-    
-    private static final class CaseInsensitiveKey {
-
-        private final String value;
-
-        private final int hashCode;
-
-        public CaseInsensitiveKey(final String v) {
-            this.value = v;
-            this.hashCode = v.toUpperCase().hashCode();
-        }
-
-		/* (non-Javadoc)
-		 * @see java.lang.Object#hashCode()
-		 */		
-		@Override
-		public int hashCode() {
-			return this.hashCode;
-		}
-
-		/* (non-Javadoc)
-		 * @see java.lang.Object#equals(java.lang.Object)
-		 */		
-		@Override
-		public boolean equals(final Object obj) {
-			if (this == obj) {
-                return true;
-            }
-			if (!(obj instanceof CaseInsensitiveKey)) {
-				return false;
-            }
-            final CaseInsensitiveKey other = (CaseInsensitiveKey) obj;
-            if ( value == null ) {
-                if ( other.value == null ) {
-                    return true;
-                }
-                return false;
-            }
-            if ( other.value == null ) {
-                return false;
-            }
-            return value.equalsIgnoreCase(other.value);
-		}
-    }
-
-    private final class KeySet extends AbstractSet<String> {
-
-		@Override
-		public int size() {
-			return CaseInsensitiveMap.this.size();
-		}
-
-		@Override
-		public boolean isEmpty() {
-			return CaseInsensitiveMap.this.isEmpty();
-		}
-
-		@Override
-		public boolean contains(Object o) {
-			return CaseInsensitiveMap.this.containsKey(o);
-		}
-
-		@Override
-		public Iterator<String> iterator() {
-			return new KeyIterator(CaseInsensitiveMap.this.map.keySet());
-		}
-
-		@Override
-		public boolean remove(Object o) {
-			return CaseInsensitiveMap.this.remove(o) != null;
-		}
-
-		@Override
-		public void clear() {
-			CaseInsensitiveMap.this.clear();
-		}
-	}
-
-	private static final class KeyIterator implements Iterator<String> {
-		private final Iterator<CaseInsensitiveKey> i;
-
-		KeyIterator(final Collection<CaseInsensitiveKey> c) {
-			this.i = c.iterator();
-		}
-
-		@Override
-		public boolean hasNext() {
-			return i.hasNext();
-		}
-
-		@Override
-		public String next() {
-			final CaseInsensitiveKey k = i.next();
-			return k.value;
-		}
-
-		@Override
-		public void remove() {
-			i.remove();
-		}
-	}
-
-	private final class EntrySet extends AbstractSet<Entry<String, T>> {
-
-		@Override
-		public int size() {
-			return CaseInsensitiveMap.this.size();
-		}
-
-		@Override
-		public boolean isEmpty() {
-			return CaseInsensitiveMap.this.isEmpty();
-		}
-
-		@Override
-		public Iterator<Entry<String, T>> iterator() {
-			return new EntryIterator<>(CaseInsensitiveMap.this.map.entrySet());
-		}
-
-		@Override
-		public void clear() {
-			CaseInsensitiveMap.this.clear();
-		}
-	}
-
-	private static final class EntryIterator<T> implements Iterator<Entry<String, T>> {
-		private final Iterator<Entry<CaseInsensitiveKey, T>> i;
-
-		EntryIterator(final Collection<Entry<CaseInsensitiveKey, T>> c) {
-			this.i = c.iterator();
-		}
-
-		@Override
-		public boolean hasNext() {
-			return i.hasNext();
-		}
-
-		@Override
-		public Entry<String, T> next() {
-			return new CaseInsentiveEntry<>(i.next());
-		}
-
-		@Override
-		public void remove() {
-			i.remove();
-		}
-	}
-
-	private static final class CaseInsentiveEntry<T> implements Entry<String, T> {
-		private final Entry<CaseInsensitiveKey, T> entry;
-
-		CaseInsentiveEntry(final Entry<CaseInsensitiveKey, T> entry) {
-			this.entry = entry;
-		}
-
-		@Override
-		public String getKey() {
-			return entry.getKey().value;
-		}
-
-		@Override
-		public T getValue() {
-			return entry.getValue();
-		}
-
-		@Override
-		public T setValue(final T value) {
-			return entry.setValue(value);
-		}
-
-		@Override
-		public int hashCode() {
-            return entry.hashCode();
-		}
-
-		@Override
-		public boolean equals(final Object obj) {
-			if (obj instanceof CaseInsentiveEntry) {
-                final CaseInsentiveEntry<?> other = (CaseInsentiveEntry<?>) obj;
-                return Objects.equals(other.entry.getKey(), this.entry.getKey()) && Objects.equals(other.entry.getValue(), this.entry.getValue());
-			}
-			return false;
-		}
-	}
-}
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
index c7c9f31..15e1319 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/ConfigurableEntity.java
@@ -25,14 +25,16 @@
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonValue;
 
+import org.apache.felix.cm.json.Configurations;
+
 /** 
  * A configurable entity has properties
  * This class is not thread safe.
  */
 public abstract class ConfigurableEntity extends DescribableEntity {
 	
-	/** The properties */
-    private final Map<String, PropertyDescription> properties = new CaseInsensitiveMap<>();
+    /** The properties */
+    private final Map<String, PropertyDescription> properties = (Map)Configurations.newConfiguration();
 
     /**
      * Clear the object and reset to defaults
diff --git a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
index a0e9bc7..f0315b3 100644
--- a/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
+++ b/src/main/java/org/apache/sling/feature/extension/apiregions/api/config/validation/ConfigurationValidator.java
@@ -89,8 +89,7 @@
         final Dictionary<String, Object> properties = configuration.getConfigurationProperties();
         // validate the described properties
         for(final Map.Entry<String, PropertyDescription> propEntry : desc.getPropertyDescriptions().entrySet()) {
-           // TODO - we need to make a case-insensitive lookup (see SLING-10084)
-           final Object value = properties.get(propEntry.getKey());
+            final Object value = properties.get(propEntry.getKey());
             final PropertyValidationResult result = propertyValidator.validate(value, propEntry.getValue());
             results.put(propEntry.getKey(), result);
         }
diff --git a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMapTest.java b/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMapTest.java
deleted file mode 100644
index ff120b3..0000000
--- a/src/test/java/org/apache/sling/feature/extension/apiregions/api/config/CaseInsensitiveMapTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sling.feature.extension.apiregions.api.config;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.junit.Test;
-
-public class CaseInsensitiveMapTest {
-
-    @Test public void testKeys() {
-        final Map<String, String> map = new CaseInsensitiveMap<>();
-        assertNull(map.put("hello", "helloV"));
-        assertNull(map.put("world", "worldV"));
-
-        assertEquals(2, map.size());
-        assertEquals(2, map.values().size());
-        assertTrue(map.values().contains("helloV"));
-        assertTrue(map.values().contains("worldV"));
-
-        assertEquals(2, map.entrySet().size());
-        final Map<String, String> m = map.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
-        assertEquals("helloV", m.get("hello"));
-        assertEquals("worldV", m.get("world"));
-
-        Set<String> keys = new HashSet<>(map.keySet());
-        assertEquals(2, keys.size());
-        assertTrue(keys.contains("hello"));
-        assertTrue(keys.contains("world"));
-
-        assertEquals("helloV", map.get("hello"));
-        assertEquals("worldV", map.get("world"));
-        assertNull(map.get("foo"));
-
-        assertEquals("helloV", map.get("HELLO"));
-        assertEquals("worldV", map.get("WORLD"));
-
-        assertEquals("helloV", map.put("heLLo", "bar"));
-        assertEquals(2, map.size());
-
-        keys = new HashSet<>(map.keySet());
-        assertEquals(2, keys.size());
-        assertTrue(keys.contains("heLLo"));
-        assertTrue(keys.contains("world"));
-
-        assertEquals("bar", map.get("hello"));
-        assertEquals("worldV", map.get("world"));
-
-        assertEquals("bar", map.remove("HellO"));
-        assertEquals("worldV", map.remove("WoRlD"));
-        assertTrue(map.isEmpty());
-    }
-
-    @Test public void testClear() {
-        final Map<String, String> map = new CaseInsensitiveMap<>();
-        map.put("hello", "hello");
-        map.put("world", "world");
-
-        map.clear();
-        assertTrue(map.isEmpty());
-        assertEquals(0, map.size());
-        assertTrue(map.values().isEmpty());
-        assertTrue(map.keySet().isEmpty());
-        assertTrue(map.entrySet().isEmpty());
-    }
-
-    @Test public void testContains() {
-        final Map<String, String> map = new CaseInsensitiveMap<>();
-        map.put("hello", "helloV");
-
-        assertTrue(map.containsKey("hello"));
-        assertTrue(map.containsKey("heLLo"));
-        assertFalse(map.containsKey("hell o"));
-
-        assertTrue(map.containsValue("helloV"));
-        assertFalse(map.containsValue("heLLoV"));
-        assertFalse(map.containsValue("hello"));    
-    }
-}