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]>.
