Initial attempt on providing default ServiceUserMapped and only mapping service users that verify.
diff --git a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilter.java b/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilter.java
index bdf794c..ae95071 100644
--- a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilter.java
+++ b/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilter.java
@@ -24,14 +24,19 @@
 import java.util.Map;
 
 import org.apache.sling.serviceusermapping.Mapping;
+import org.apache.sling.serviceusermapping.ServiceUserMapped;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.hooks.service.EventListenerHook;
 import org.osgi.framework.hooks.service.FindHook;
 import org.osgi.framework.hooks.service.ListenerHook;
+import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
 
 /**
  * The <code>ServiceUserMappingBundleFilter</code> only allows the bundle for which the service mapping is available to see it.
@@ -40,20 +45,40 @@
            service = {EventListenerHook.class, FindHook.class} )
 public class ServiceUserMappedBundleFilter implements EventListenerHook, FindHook {
 
+    @Reference
+    volatile ServiceUserMapperImpl mapper;
+
+    volatile BundleContext context;
+
+    @Activate
+    void start(BundleContext context) {
+        this.context = context;
+    }
+
     @Override
     public void event(ServiceEvent serviceEvent, Map map) {
 
         ServiceReference serviceReference = serviceEvent.getServiceReference();
-        if (isServiceMappingReference(serviceReference)) {
+        if (isServiceMappingReference(serviceReference) && serviceEvent.getType() == ServiceEvent.REGISTERED) {
             Object serviceName = serviceReference.getProperty(Mapping.SERVICENAME);
+            String subserviceName = getSubServiceName(serviceReference);
+            Iterator<Map.Entry<BundleContext, Collection<ListenerHook.ListenerInfo>>> it = map.entrySet().iterator();
+            while (it.hasNext()) {
+                Map.Entry<BundleContext, Collection<ListenerHook.ListenerInfo>> entry = it.next();
+                BundleContext ctx = entry.getKey();
 
-            if (serviceName != null && serviceName instanceof String) {
-                Iterator<Map.Entry<BundleContext, Collection<ListenerHook.ListenerInfo>>> it = map.entrySet().iterator();
-                while (it.hasNext()) {
-                    BundleContext ctx = it.next().getKey();
-
-                    String bundleServiceName = ServiceUserMapperImpl.getServiceName(ctx.getBundle());
-                    if (!serviceName.equals(bundleServiceName)) {
+                if (!ctx.getBundle().equals(context.getBundle()) && !isValid(ctx.getBundle(), serviceName, subserviceName)) {
+                    boolean keep = false;
+                    Iterator<ListenerHook.ListenerInfo> iter = entry.getValue().iterator();
+                    while (iter.hasNext()) {
+                        if (!matchDefault(ctx.getBundle(), serviceName, subserviceName, iter.next().getFilter(), serviceReference)) {
+                            iter.remove();
+                        }
+                        else {
+                            keep = true;
+                        }
+                    }
+                    if (!keep) {
                         it.remove();
                     }
                 }
@@ -64,21 +89,64 @@
     @Override
     public void find(BundleContext bundleContext, String name, String filter, boolean allServices,
                      Collection references) {
-        String bundleServiceName = ServiceUserMapperImpl.getServiceName(bundleContext.getBundle());
 
         Iterator<ServiceReference> it = references.iterator();
         while (it.hasNext()) {
             ServiceReference serviceReference = it.next();
             if (isServiceMappingReference(serviceReference)) {
                 Object serviceName = serviceReference.getProperty(Mapping.SERVICENAME);
-
-                if (serviceName != null && !serviceName.equals(bundleServiceName)) {
-                    it.remove();
+                String subserviceName = getSubServiceName(serviceReference);
+                if (!isValid(bundleContext.getBundle(), serviceName, subserviceName)) {
+                    if (!matchDefault(bundleContext.getBundle(), serviceName, subserviceName, filter, serviceReference)) {
+                        it.remove();
+                    }
                 }
             }
         }
     }
 
+    private boolean isValid(Bundle bundle, Object serviceName, String subserviceName) {
+        String bundleServiceName = mapper.getServiceName(bundle);
+        if (bundleServiceName.equals(serviceName)) {
+            Iterable<String> principals = mapper.getServicePrincipalNames(bundle, subserviceName);
+            if (principals != null && principals.iterator().hasNext()) {
+                return true;
+            }
+            String user = mapper.getServiceUserID(bundle, subserviceName);
+            if (user != null && !user.isEmpty()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean matchDefault(Bundle bundle, Object serviceName, String subserviceName, String filter, ServiceReference ref) {
+         if ( mapper.getServiceName(context.getBundle()).equals(serviceName) ) {
+             try {
+                 if (filter != null && context.createFilter(filter).match(ref)) {
+                     for (Mapping mapping : mapper.getActiveMappings()) {
+                         if (mapping.getServiceName().equals(mapper.getServiceName(bundle))) {
+                             return false;
+                         }
+                     }
+                     Iterable<String> principals = mapper.getServicePrincipalNames(bundle, subserviceName);
+                     if (principals != null && principals.iterator().hasNext()) {
+                         return true;
+                     }
+                     String user = mapper.getServiceUserID(bundle, subserviceName);
+                     if (user != null && !user.isEmpty()) {
+                         return true;
+                     }
+                 }
+             } catch (InvalidSyntaxException e) {
+                 // this shouldn't happen as the framework will have validated the filter already
+                 throw new RuntimeException(e);
+             }
+         }
+         return false;
+    }
+
     private static boolean isServiceMappingReference(ServiceReference serviceReference) {
         Object objectClass = serviceReference.getProperty(Constants.OBJECTCLASS);
         for (Object o :  (Object[]) objectClass) {
@@ -89,6 +157,11 @@
         return false;
     }
 
-
-
+    private static String getSubServiceName(ServiceReference ref) {
+        Object subserviceName = ref.getProperty(ServiceUserMapped.SUBSERVICENAME);
+        if (subserviceName != null && subserviceName instanceof String) {
+            return (String) subserviceName;
+        }
+        return null;
+    }
 }
diff --git a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java b/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
index 7fb23e4..492513b 100644
--- a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
+++ b/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
@@ -34,6 +34,7 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.sling.serviceusermapping.Mapping;
 import org.apache.sling.serviceusermapping.ServicePrincipalsValidator;
@@ -81,7 +82,7 @@
         @AttributeDefinition(name = "Default Mapping",
                 description = "If enabled and no mapping for a requested service user exists and no " +
                       " default user is defined, a " +
-                     "default mapping is applied which uses the service user \"serviceuser@\" + {bundleId} + [\":\" + subServiceName]")
+                     "default mapping is applied which uses the service user \"serviceuser--\" + bundleId + [\"--\" + subServiceName]")
         boolean user_enable_default_mapping() default true;
     }
 
@@ -92,7 +93,7 @@
 
     private String defaultUser;
 
-    private boolean useDefaultMapping;
+    volatile boolean useDefaultMapping;
 
     private Map<Long, MappingConfigAmendment> amendments = new HashMap<>();
 
@@ -108,7 +109,9 @@
 
     private ExecutorService executorService;
 
-    public boolean registerAsync = true;
+    boolean registerAsync = true;
+
+    private final AtomicReference<ServiceRegistration> defaultRegistration = new AtomicReference<>();
 
     @Activate
     @Modified
@@ -340,6 +343,10 @@
 
     private void executeServiceRegistrations(final RegistrationSet registrationSet) {
 
+        ServiceRegistration reg = defaultRegistration.getAndSet(null);
+        if (reg != null) {
+            reg.unregister();
+        }
         if (registrationSet == null) {
             return;
         }
@@ -388,6 +395,16 @@
             }
         }
 
+        if (this.useDefaultMapping || (defaultUser != null && !defaultUser.isEmpty())) {
+            Dictionary<String, Object> properties = new Hashtable<>();
+            properties.put(Mapping.SERVICENAME, getServiceName(savedBundleContext.getBundle()));
+            final ServiceRegistration serviceRegistration = savedBundleContext.registerService(ServiceUserMappedImpl.SERVICEUSERMAPPED,
+                new ServiceUserMappedImpl(), properties);
+            ServiceRegistration oldServiceRegistration = this.defaultRegistration.getAndSet(serviceRegistration);
+            if (oldServiceRegistration != null) {
+                oldServiceRegistration.unregister();
+            }
+        }
     }
 
     private String internalGetUserId(final String serviceName, final String subServiceName) {
@@ -417,7 +434,7 @@
         }
 
         // use default mapping if configured and no default user
-        if ( this.defaultUser == null || this.defaultUser.isEmpty() ) {
+        if ( this.useDefaultMapping && (this.defaultUser == null || this.defaultUser.isEmpty() )) {
             final String userName = "serviceuser--" + serviceName + (subServiceName == null ? "" : "--" + subServiceName);
             log.debug("internalGetUserId: no mapping found, using default mapping [{}]", userName);
             return userName;
@@ -497,7 +514,7 @@
         return null;
     }
 
-    static String getServiceName(final Bundle bundle) {
+    String getServiceName(final Bundle bundle) {
         return bundle.getSymbolicName();
     }
 
diff --git a/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilterTest.java b/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilterTest.java
index e95ef7e..08fe051 100644
--- a/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilterTest.java
+++ b/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMappedBundleFilterTest.java
@@ -53,14 +53,21 @@
 
     final static BundleContext bundleContext1;
     final static BundleContext bundleContext2;
+    final static BundleContext mapperContext;
 
     static  {
+        Bundle mapper = mock(Bundle.class);
+        when(mapper.getSymbolicName()).thenReturn("mapper");
+        mapperContext = mock(BundleContext.class);
+        when(mapperContext.getBundle()).thenReturn(mapper);
+
         bundleContext1 = mock(BundleContext.class);
         Bundle bundle1 = mock(Bundle.class);
         when(bundleContext1.getBundle()).thenReturn(bundle1);
         when(bundle1.getSymbolicName()).thenReturn(BUNDLE1);
 
 
+
         bundleContext2 = mock(BundleContext.class);
         Bundle bundle2 = mock(Bundle.class);
         when(bundleContext2.getBundle()).thenReturn(bundle2);
@@ -83,12 +90,24 @@
         when(serviceEvent.getServiceReference()).thenReturn(serviceReference);
         when(serviceReference.getProperty(Constants.OBJECTCLASS)).thenReturn(new String[]{ServiceUserMappedImpl.SERVICEUSERMAPPED});
         when(serviceReference.getProperty(Mapping.SERVICENAME)).thenReturn(BUNDLE1);
+        when(serviceEvent.getType()).thenReturn(ServiceEvent.REGISTERED);
 
 
-        EventListenerHook eventListenerHook = new ServiceUserMappedBundleFilter();
-        eventListenerHook.event(serviceEvent, map);
+        ServiceUserMappedBundleFilter eventListenerHook = new ServiceUserMappedBundleFilter();
 
-        TestCase.assertEquals(1, map.size());
+        eventListenerHook.mapper = new ServiceUserMapperImpl();
+        eventListenerHook.start(mapperContext);
+
+        Map<BundleContext, Collection<ListenerHook.ListenerInfo>> map1 = new HashMap<>(map);
+        eventListenerHook.event(serviceEvent, map1);
+
+        TestCase.assertEquals(0, map1.size());
+
+        Map<BundleContext, Collection<ListenerHook.ListenerInfo>> map2 = new HashMap<>(map);
+        eventListenerHook.mapper.useDefaultMapping = true;
+        eventListenerHook.event(serviceEvent, map2);
+
+        TestCase.assertEquals(1, map2.size());
         TestCase.assertTrue(map.containsKey(bundleContext1));
 
     }
@@ -108,10 +127,24 @@
         when(serviceReference2.getProperty(Mapping.SERVICENAME)).thenReturn(BUNDLE2);
         when(serviceReference2.getProperty(Constants.OBJECTCLASS)).thenReturn(new String[]{ServiceUserMappedImpl.SERVICEUSERMAPPED});
 
-        FindHook findHook = new ServiceUserMappedBundleFilter();
-        findHook.find(bundleContext1, null, null, false, collection);
+        ServiceUserMappedBundleFilter findHook = new ServiceUserMappedBundleFilter();
 
-        TestCase.assertEquals(1, collection.size());
+        findHook.mapper = new ServiceUserMapperImpl();
+        findHook.start(mapperContext);
+
+        List collection1 = new ArrayList(collection);
+        findHook.find(bundleContext1, null, null, false, collection1);
+
+        TestCase.assertEquals(0, collection1.size());
+
+        findHook.mapper.useDefaultMapping = true;
+
+        List collection2 = new ArrayList(collection);
+        findHook.find(bundleContext1, null, null, false, collection2);
+
+        TestCase.assertEquals(1, collection2.size());
         TestCase.assertTrue(collection.contains(serviceReference1));
+
+
     }
 }
diff --git a/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java b/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java
index 41da0f6..1fc5abb 100644
--- a/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java
+++ b/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java
@@ -424,7 +424,7 @@
         final ServiceRegistrationContextHelper context = new ServiceRegistrationContextHelper();
         sum.configure(context.getBundleContext(), config);
 
-        TestCase.assertEquals(2, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
+        TestCase.assertEquals(3, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
 
         final MappingConfigAmendment mca1 = new MappingConfigAmendment();
 
@@ -439,7 +439,7 @@
         mca1.configure(mca1Config);
         sum.bindAmendment(mca1, mca1ConfigMap);
 
-        TestCase.assertEquals(3, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
+        TestCase.assertEquals(4, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
 
         final MappingConfigAmendment mca2 = new MappingConfigAmendment();
 
@@ -454,11 +454,11 @@
         mca2.configure(mca2Config);
         sum.bindAmendment(mca2, mca2ConfigMap);
 
-        TestCase.assertEquals(4, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
+        TestCase.assertEquals(5, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
 
         sum.unbindAmendment(mca1, mca1ConfigMap);
 
-        TestCase.assertEquals(3, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
+        TestCase.assertEquals(4, context.getRegistrations(ServiceUserMappedImpl.SERVICEUSERMAPPED).size());
     }
 
 
@@ -466,6 +466,7 @@
 
 
         final BundleContext bundleContext = mock(BundleContext.class);
+        final Bundle bundle = mock(Bundle.class);
         final Map<String, Map<Object, Dictionary>> registrations = new HashMap<>();
 
         public ServiceRegistrationContextHelper() {
@@ -478,6 +479,8 @@
                             return registerService((String) arguments[0], arguments[1], (Dictionary) arguments[2]);
                         }
                     });
+            when(bundleContext.getBundle()).thenReturn(bundle);
+            when(bundle.getSymbolicName()).thenReturn("mock");
         }
 
         private ServiceRegistration registerService(String string, Object o, Dictionary dictionary) {