SLING-10138 Add proper throws declarations for the MockConfigurationAdmin and provide implementation for listConfigurations
diff --git a/core/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java b/core/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java
index ba69124..9900d6d 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/osgi/MockBundleContext.java
@@ -71,7 +71,7 @@
     private final SortedSet<MockServiceRegistration> registeredServices = new ConcurrentSkipListSet<MockServiceRegistration>();
     private final Map<ServiceListener, Filter> serviceListeners = new ConcurrentHashMap<ServiceListener, Filter>();
     private final Queue<BundleListener> bundleListeners = new ConcurrentLinkedQueue<BundleListener>();
-    private final ConfigurationAdmin configAdmin = new MockConfigurationAdmin();
+    private final ConfigurationAdmin configAdmin = new MockConfigurationAdmin(this);
     private File dataFileBaseDir;
     
     private final Bundle systemBundle;
diff --git a/core/src/main/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdmin.java b/core/src/main/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdmin.java
index c6146f8..2298d4d 100644
--- a/core/src/main/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdmin.java
+++ b/core/src/main/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdmin.java
@@ -18,22 +18,30 @@
  */
 package org.apache.sling.testing.mock.osgi;
 
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
 import java.io.IOException;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
 /**
  * Mock implementation of {@link ConfigurationAdmin}.
  */
 class MockConfigurationAdmin implements ConfigurationAdmin {
-    
-    private ConcurrentMap<String, Configuration> configs = new ConcurrentHashMap<String, Configuration>();
+    private final BundleContext bundleContext;
+    private final ConcurrentMap<String, Configuration> configs = new ConcurrentHashMap<>();
+
+    MockConfigurationAdmin(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
 
     @Override
-    public Configuration getConfiguration(String pid) {
+    public Configuration getConfiguration(final String pid) throws IOException {
         configs.putIfAbsent(pid, new MockConfiguration(pid));
         return configs.get(pid);
     }
@@ -41,32 +49,42 @@
     // --- unsupported operations ---
 
     @Override
-    public Configuration getConfiguration(String pid, String location) {
+    public Configuration getConfiguration(final String pid, final String location) throws IOException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public Configuration createFactoryConfiguration(String factoryPid) {
+    public Configuration createFactoryConfiguration(final String factoryPid) throws IOException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public Configuration createFactoryConfiguration(String factoryPid, String location) {
+    public Configuration createFactoryConfiguration(final String factoryPid, final String location) throws IOException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public Configuration[] listConfigurations(String filter) {
+    @SuppressWarnings("squid:S1168")
+    public Configuration[] listConfigurations(final String filter) throws IOException, InvalidSyntaxException {
+        final Filter filterObject = bundleContext.createFilter(filter);
+        final Configuration[] filtered = configs
+                .values()
+                .stream()
+                .filter(configuration -> filterObject.match(configuration.getProperties()))
+                .toArray(Configuration[]::new);
+        if (filtered.length != 0) {
+            return filtered;
+        }
+        return null;
+    }
+
+    @Override
+    public Configuration getFactoryConfiguration(final String factoryPid, final String name, final String location) throws IOException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public Configuration getFactoryConfiguration(String factoryPid, String name, String location) throws IOException {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Configuration getFactoryConfiguration(String factoryPid, String name) throws IOException {
+    public Configuration getFactoryConfiguration(final String factoryPid, final String name) throws IOException {
         throw new UnsupportedOperationException();
     }
 
diff --git a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdminTest.java b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdminTest.java
index 187efbd..145432f 100644
--- a/core/src/test/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdminTest.java
+++ b/core/src/test/java/org/apache/sling/testing/mock/osgi/MockConfigurationAdminTest.java
@@ -20,6 +20,8 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 
@@ -28,9 +30,12 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
 import com.google.common.collect.ImmutableMap;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
 
 public class MockConfigurationAdminTest {
     
@@ -101,6 +106,23 @@
         assertEquals(2, reference.getProperty("prop2"));
     }
 
+    @Test
+    public void testFilteringConfigurations() throws IOException, InvalidSyntaxException {
+        MockOsgi.setConfigForPid(context.bundleContext(), "Configuration1", "prop1", 1, "prop2", "B");
+        MockOsgi.setConfigForPid(context.bundleContext(), "Configuration2", "prop1", 2, "prop2", "A");
+        MockOsgi.setConfigForPid(context.bundleContext(), "Configuration3", "prop1", 3, "prop2", "A");
+
+        final ConfigurationAdmin configurationAdmin = context.bundleContext().getService(context.bundleContext().getServiceReference(ConfigurationAdmin.class));
+        final Configuration[] allConfigurations = configurationAdmin.listConfigurations("(prop1=*)");
+        assertEquals(3, allConfigurations.length);
+        final Configuration[] prop2AConfigurations = configurationAdmin.listConfigurations("(prop2=A)");
+        assertEquals(2, prop2AConfigurations.length);
+        final Configuration[] searchForAllConfigurations = configurationAdmin.listConfigurations(null);
+        assertTrue(searchForAllConfigurations.length >= 3); // Other configurations could be registered outside this method as well
+        final Configuration[] noConfigurations = configurationAdmin.listConfigurations("(nonexistingprop=nonexistingvalue)");
+        assertNull(noConfigurations);
+    }
+
     static class ServiceWithConfigurationPID {}
 
     static class ServiceWithMultipleConfigurationPID {}