This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag 
org.apache.sling.serviceusermapper-1.0.2
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-serviceusermapper.git

commit 90f2a66d834dc34482d215956fbe8d4e339c5263
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Tue May 20 13:57:19 2014 +0000

    SLING-3578 : Support mapping amendments
    
    git-svn-id: 
https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/serviceusermapper@1596248
 13f79535-47bb-0310-9956-ffa450edef68
---
 ...MapperImpl.java => MappingConfigAmendment.java} | 78 ++++++++------------
 .../impl/ServiceUserMapperImpl.java                | 79 +++++++++++++++++---
 .../impl/ServiceUserMapperImplTest.java            | 86 ++++++++++++++++++++++
 3 files changed, 185 insertions(+), 58 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
 
b/src/main/java/org/apache/sling/serviceusermapping/impl/MappingConfigAmendment.java
similarity index 53%
copy from 
src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
copy to 
src/main/java/org/apache/sling/serviceusermapping/impl/MappingConfigAmendment.java
index d9393f6..2c2c962 100644
--- 
a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
+++ 
b/src/main/java/org/apache/sling/serviceusermapping/impl/MappingConfigAmendment.java
@@ -23,22 +23,29 @@ import java.util.Map;
 
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
 import org.apache.felix.scr.annotations.Modified;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyUnbounded;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.serviceusermapping.ServiceUserMapper;
-import org.osgi.framework.Bundle;
+import org.apache.sling.commons.osgi.ServiceUtil;
+import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Component(
-        metatype = true,
-        label = "Apache Sling Service User Mapper Service",
-        description = "Configuration for the service mapping service names to 
names of users.")
-@Service(value=ServiceUserMapper.class)
-public class ServiceUserMapperImpl implements ServiceUserMapper {
+@Component(metatype=true,
+        
name="org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended",
+        label="Apache Sling Service User Mapper Service Amendment",
+        description="An amendment mapping for the user mapping service.",
+        configurationFactory=true,
+        policy=ConfigurationPolicy.REQUIRE)
+@Service(value={MappingConfigAmendment.class})
+@Property(name=Constants.SERVICE_RANKING, intValue=0, propertyPrivate=false,
+          label="Ranking",
+          description="Amendments are processed in order of their ranking, an 
amendment with a higher ranking has" +
+                      " precedence over a mapping with a lower ranking.")
+public class MappingConfigAmendment implements 
Comparable<MappingConfigAmendment> {
 
     @Property(
             label = "Service Mappings",
@@ -51,21 +58,12 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
 
     private static final String[] PROP_SERVICE2USER_MAPPING_DEFAULT = {};
 
-    private static final String PROP_DEFAULT_USER = "user.default";
-
-    @Property(
-            name = PROP_DEFAULT_USER,
-            label = "Default User",
-            description = "The name of the user to use as the default if no 
service mapping"
-                + "applies. If this property is missing or empty no default 
user is defined.")
-    private static final String PROP_DEFAULT_USER_DEFAULT = null;
-
-    /** default log */
-    private final Logger log = LoggerFactory.getLogger(getClass());
+    /** default logger */
+    private final Logger logger = LoggerFactory.getLogger(getClass());
 
     private Mapping[] serviceUserMappings;
 
-    private String defaultUser;
+    private Comparable<Object> comparable;
 
     @Activate
     @Modified
@@ -74,44 +72,26 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
             PROP_SERVICE2USER_MAPPING_DEFAULT);
 
         ArrayList<Mapping> mappings = new ArrayList<Mapping>(props.length);
-        for (String prop : props) {
-            if (prop != null) {
+        for (final String prop : props) {
+            if (prop != null && prop.trim().length() > 0 ) {
                 try {
-                    Mapping mapping = new Mapping(prop);
+                    final Mapping mapping = new Mapping(prop.trim());
                     mappings.add(mapping);
-                } catch (IllegalArgumentException iae) {
-                    log.info("configure: Ignoring '{}': {}", prop, 
iae.getMessage());
+                } catch (final IllegalArgumentException iae) {
+                    logger.info("configure: Ignoring '{}': {}", prop, 
iae.getMessage());
                 }
             }
         }
 
         this.serviceUserMappings = mappings.toArray(new 
Mapping[mappings.size()]);
-        this.defaultUser = 
PropertiesUtil.toString(config.get(PROP_DEFAULT_USER), 
PROP_DEFAULT_USER_DEFAULT);
+        this.comparable = ServiceUtil.getComparableForServiceRanking(config);
     }
 
-    /**
-     * @see 
org.apache.sling.serviceusermapping.ServiceUserMapper#getServiceUserID(org.osgi.framework.Bundle,
 java.lang.String)
-     */
-    public String getServiceUserID(final Bundle bundle, final String 
subServiceName) {
-        final String serviceName = bundle.getSymbolicName();
-
-        // try with serviceInfo first
-        for (Mapping mapping : this.serviceUserMappings) {
-            final String user = mapping.map(serviceName, subServiceName);
-            if (user != null) {
-                return user;
-            }
-        }
-
-        // second round without serviceInfo
-        for (Mapping mapping : this.serviceUserMappings) {
-            final String user = mapping.map(serviceName, null);
-            if (user != null) {
-                return user;
-            }
-        }
+    public Mapping[] getServiceUserMappings() {
+        return this.serviceUserMappings;
+    }
 
-        // finally, fall back to default user
-        return this.defaultUser;
+    public int compareTo(final MappingConfigAmendment o) {
+        return -this.comparable.compareTo(o.comparable);
     }
 }
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 d9393f6..f044e02 100644
--- 
a/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
+++ 
b/src/main/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImpl.java
@@ -19,6 +19,9 @@
 package org.apache.sling.serviceusermapping.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.scr.annotations.Activate;
@@ -26,10 +29,14 @@ import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Modified;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.serviceusermapping.ServiceUserMapper;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,6 +45,11 @@ import org.slf4j.LoggerFactory;
         label = "Apache Sling Service User Mapper Service",
         description = "Configuration for the service mapping service names to 
names of users.")
 @Service(value=ServiceUserMapper.class)
+@Reference(name="amendment",
+           referenceInterface=MappingConfigAmendment.class,
+           cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+           policy=ReferencePolicy.DYNAMIC,
+           updated="update")
 public class ServiceUserMapperImpl implements ServiceUserMapper {
 
     @Property(
@@ -63,30 +75,37 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
     /** default log */
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    private Mapping[] serviceUserMappings;
+    private Mapping[] globalServiceUserMappings = new Mapping[0];
 
     private String defaultUser;
 
+    private Map<Long, MappingConfigAmendment> amendments = new HashMap<Long, 
MappingConfigAmendment>();
+
+    private Mapping[] activeMappings = new Mapping[0];
+
     @Activate
     @Modified
     void configure(final Map<String, Object> config) {
         final String[] props = 
PropertiesUtil.toStringArray(config.get(PROP_SERVICE2USER_MAPPING),
             PROP_SERVICE2USER_MAPPING_DEFAULT);
 
-        ArrayList<Mapping> mappings = new ArrayList<Mapping>(props.length);
-        for (String prop : props) {
-            if (prop != null) {
+        final ArrayList<Mapping> mappings = new 
ArrayList<Mapping>(props.length);
+        for (final String prop : props) {
+            if (prop != null && prop.trim().length() > 0 ) {
                 try {
-                    Mapping mapping = new Mapping(prop);
+                    final Mapping mapping = new Mapping(prop.trim());
                     mappings.add(mapping);
-                } catch (IllegalArgumentException iae) {
+                } catch (final IllegalArgumentException iae) {
                     log.info("configure: Ignoring '{}': {}", prop, 
iae.getMessage());
                 }
             }
         }
 
-        this.serviceUserMappings = mappings.toArray(new 
Mapping[mappings.size()]);
+        this.globalServiceUserMappings = mappings.toArray(new 
Mapping[mappings.size()]);
         this.defaultUser = 
PropertiesUtil.toString(config.get(PROP_DEFAULT_USER), 
PROP_DEFAULT_USER_DEFAULT);
+        synchronized ( this.amendments ) {
+            this.updateMappings();
+        }
     }
 
     /**
@@ -96,7 +115,7 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
         final String serviceName = bundle.getSymbolicName();
 
         // try with serviceInfo first
-        for (Mapping mapping : this.serviceUserMappings) {
+        for (Mapping mapping : this.activeMappings) {
             final String user = mapping.map(serviceName, subServiceName);
             if (user != null) {
                 return user;
@@ -104,7 +123,7 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
         }
 
         // second round without serviceInfo
-        for (Mapping mapping : this.serviceUserMappings) {
+        for (Mapping mapping : this.activeMappings) {
             final String user = mapping.map(serviceName, null);
             if (user != null) {
                 return user;
@@ -114,4 +133,46 @@ public class ServiceUserMapperImpl implements 
ServiceUserMapper {
         // finally, fall back to default user
         return this.defaultUser;
     }
+
+    protected void bindAmendment(final MappingConfigAmendment amendment, final 
Map<String, Object> props) {
+        final Long key = (Long) props.get(Constants.SERVICE_ID);
+        synchronized ( this.amendments ) {
+            amendments.put(key, amendment);
+            this.updateMappings();
+        }
+    }
+
+    protected void unbindAmendment(final MappingConfigAmendment amendment, 
final Map<String, Object> props) {
+        final Long key = (Long) props.get(Constants.SERVICE_ID);
+        synchronized ( this.amendments ) {
+            if ( amendments.remove(key) != null ) {
+                this.updateMappings();
+            };
+        }
+
+    }
+
+    protected void updateAmendment(final MappingConfigAmendment amendment, 
final Map<String, Object> props) {
+        this.bindAmendment(amendment, props);
+    }
+
+    protected void updateMappings() {
+        final List<MappingConfigAmendment> sortedMappings = new 
ArrayList<MappingConfigAmendment>();
+        for(final MappingConfigAmendment amendment : this.amendments.values() 
) {
+            sortedMappings.add(amendment);
+        }
+        Collections.sort(sortedMappings);
+
+        final List<Mapping> mappings = new ArrayList<Mapping>();
+        for(final Mapping m : this.globalServiceUserMappings) {
+            mappings.add(m);
+        }
+        for(final MappingConfigAmendment mca : sortedMappings) {
+            for(final Mapping m : mca.getServiceUserMappings()) {
+                mappings.add(m);
+            }
+        }
+        activeMappings = mappings.toArray(new Mapping[mappings.size()]);
+    }
 }
+
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 635193f..2b007be 100644
--- 
a/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java
+++ 
b/src/test/java/org/apache/sling/serviceusermapping/impl/ServiceUserMapperImplTest.java
@@ -27,6 +27,7 @@ import junit.framework.TestCase;
 import org.apache.sling.commons.testing.osgi.MockBundle;
 import org.junit.Test;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
 
 public class ServiceUserMapperImplTest {
     private static final String BUNDLE_SYMBOLIC1 = "bundle1";
@@ -99,4 +100,89 @@ public class ServiceUserMapperImplTest {
         TestCase.assertEquals(SAMPLE_SUB, sum.getServiceUserID(BUNDLE1, SUB));
         TestCase.assertEquals(ANOTHER_SUB, sum.getServiceUserID(BUNDLE2, SUB));
     }
+
+    @Test
+    public void test_amendment() {
+        @SuppressWarnings("serial")
+        Map<String, Object> config = new HashMap<String, Object>() {
+            {
+                put("user.mapping", new String[] {
+                    BUNDLE_SYMBOLIC1 + "=" + SAMPLE, //
+                    BUNDLE_SYMBOLIC1 + ":" + SUB + "=" + SAMPLE_SUB, //
+                });
+                put("user.default", NONE);
+            }
+        };
+
+        final ServiceUserMapperImpl sum = new ServiceUserMapperImpl();
+        sum.configure(config);
+        final MappingConfigAmendment mca1 = new MappingConfigAmendment();
+        @SuppressWarnings("serial")
+        final Map<String, Object> mca1Config = new HashMap<String, Object>() {
+            {
+                put("user.mapping", new String [] {BUNDLE_SYMBOLIC2 + "=" + 
ANOTHER});
+                put(Constants.SERVICE_ID, 1L);
+                put(Constants.SERVICE_RANKING, 100);
+            }
+        };
+        mca1.configure(mca1Config);
+        sum.bindAmendment(mca1, mca1Config);
+        final MappingConfigAmendment mca2 = new MappingConfigAmendment();
+        @SuppressWarnings("serial")
+        final Map<String, Object> mca2Config = new HashMap<String, Object>() {
+            {
+                put("user.mapping", new String [] {BUNDLE_SYMBOLIC2 + ":" + 
SUB + "=" + ANOTHER_SUB});
+                put(Constants.SERVICE_ID, 2L);
+                put(Constants.SERVICE_RANKING, 200);
+            }
+        };
+        mca2.configure(mca2Config);
+        sum.bindAmendment(mca2, mca2Config);
+
+        TestCase.assertEquals(SAMPLE, sum.getServiceUserID(BUNDLE1, null));
+        TestCase.assertEquals(ANOTHER, sum.getServiceUserID(BUNDLE2, null));
+        TestCase.assertEquals(SAMPLE, sum.getServiceUserID(BUNDLE1, ""));
+        TestCase.assertEquals(ANOTHER, sum.getServiceUserID(BUNDLE2, ""));
+        TestCase.assertEquals(SAMPLE_SUB, sum.getServiceUserID(BUNDLE1, SUB));
+        TestCase.assertEquals(ANOTHER_SUB, sum.getServiceUserID(BUNDLE2, SUB));
+    }
+
+    @Test
+    public void test_amendmentOverlap() {
+        @SuppressWarnings("serial")
+        final Map<String, Object> config = new HashMap<String, Object>() {
+            {
+                put("user.default", NONE);
+            }
+        };
+
+        final ServiceUserMapperImpl sum = new ServiceUserMapperImpl();
+        sum.configure(config);
+
+        final MappingConfigAmendment mca1 = new MappingConfigAmendment();
+        @SuppressWarnings("serial")
+        final Map<String, Object> mca1Config = new HashMap<String, Object>() {
+            {
+                put("user.mapping", new String [] {BUNDLE_SYMBOLIC2 + "=" + 
ANOTHER});
+                put(Constants.SERVICE_ID, 1L);
+                put(Constants.SERVICE_RANKING, 100);
+            }
+        };
+        mca1.configure(mca1Config);
+        final MappingConfigAmendment mca2 = new MappingConfigAmendment();
+        @SuppressWarnings("serial")
+        final Map<String, Object> mca2Config = new HashMap<String, Object>() {
+            {
+                put("user.mapping", new String [] {BUNDLE_SYMBOLIC2 + "=" + 
ANOTHER_SUB});
+                put(Constants.SERVICE_ID, 2L);
+                put(Constants.SERVICE_RANKING, 200);
+            }
+        };
+        mca2.configure(mca2Config);
+
+        sum.bindAmendment(mca1, mca1Config);
+        sum.bindAmendment(mca2, mca2Config);
+
+        TestCase.assertEquals(ANOTHER_SUB, sum.getServiceUserID(BUNDLE2, ""));
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to