You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2017/03/19 14:53:02 UTC

svn commit: r1787626 [1/2] - in /sling/trunk/bundles/extensions/caconfig: impl/ impl/src/main/java/org/apache/sling/caconfig/impl/ impl/src/main/java/org/apache/sling/caconfig/impl/def/ impl/src/main/java/org/apache/sling/caconfig/management/ impl/src/...

Author: sseifert
Date: Sun Mar 19 14:53:02 2017
New Revision: 1787626

URL: http://svn.apache.org/viewvc?rev=1787626&view=rev
Log:
SLING-6669 introduce new SPI ConfigurationPersistenceStrategy2, deprecate ConfigurationPersistenceStrategy
export ConfigurationPersistenceStrategyMultiplexer as part of the management API

Added:
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence2Test.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImplTest.java   (with props)
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy2.java   (with props)
    sling/trunk/bundles/extensions/caconfig/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy2.java   (with props)
Removed:
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexer.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerTest.java
Modified:
    sling/trunk/bundles/extensions/caconfig/impl/pom.xml
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/ConfigurationManager.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
    sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategyTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/metadata/ConfigurationMetadataProviderMultiplexerTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationCollectionDataImplTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java
    sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/management/impl/CustomConfigurationPersistenceStrategy.java
    sling/trunk/bundles/extensions/caconfig/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationPersistenceStrategy.java
    sling/trunk/bundles/extensions/caconfig/spi/src/main/java/org/apache/sling/caconfig/spi/package-info.java

Modified: sling/trunk/bundles/extensions/caconfig/impl/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/pom.xml?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/pom.xml Sun Mar 19 14:53:02 2017
@@ -71,7 +71,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.caconfig.spi</artifactId>
-            <version>1.2.0</version>
+            <version>1.2.1-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java Sun Mar 19 14:53:02 2017
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.collections.IteratorUtils;
@@ -38,12 +39,12 @@ import org.apache.sling.caconfig.Configu
 import org.apache.sling.caconfig.impl.ConfigurationProxy.ChildResolver;
 import org.apache.sling.caconfig.impl.metadata.AnnotationClassParser;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer;
 import org.apache.sling.caconfig.resource.impl.util.ConfigNameUtil;
 import org.apache.sling.caconfig.resource.impl.util.MapUtil;
 import org.apache.sling.caconfig.resource.spi.ConfigurationResourceResolvingStrategy;
 import org.apache.sling.caconfig.spi.ConfigurationInheritanceStrategy;
 import org.apache.sling.caconfig.spi.ConfigurationMetadataProvider;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
 import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
 import org.slf4j.Logger;
@@ -54,7 +55,7 @@ class ConfigurationBuilderImpl implement
     private final Resource contentResource;
     private final ConfigurationResolver configurationResolver;
     private final ConfigurationResourceResolvingStrategy configurationResourceResolvingStrategy;
-    private final ConfigurationPersistenceStrategy configurationPersistenceStrategy;
+    private final ConfigurationPersistenceStrategyMultiplexer configurationPersistenceStrategy;
     private final ConfigurationInheritanceStrategy configurationInheritanceStrategy;
     private final ConfigurationOverrideManager configurationOverrideManager;
     private final ConfigurationMetadataProvider configurationMetadataProvider;
@@ -67,7 +68,7 @@ class ConfigurationBuilderImpl implement
     public ConfigurationBuilderImpl(final Resource resource,
             final ConfigurationResolver configurationResolver,
             final ConfigurationResourceResolvingStrategy configurationResourceResolvingStrategy,
-            final ConfigurationPersistenceStrategy configurationPersistenceStrategy,
+            final ConfigurationPersistenceStrategyMultiplexer configurationPersistenceStrategy,
             final ConfigurationInheritanceStrategy configurationInheritanceStrategy,
             final ConfigurationOverrideManager configurationOverrideManager,
             final ConfigurationMetadataProvider configurationMetadataProvider,
@@ -104,7 +105,7 @@ class ConfigurationBuilderImpl implement
      * @param <T> Target class
      */
     private interface Converter<T> {
-        T convert(Resource resource, Class<T> clazz, String configName);
+        T convert(Resource resource, Class<T> clazz, String configName, boolean isCollection);
     }
 
     /**
@@ -134,9 +135,19 @@ class ConfigurationBuilderImpl implement
     private <T> Collection<T> getConfigResourceCollection(String configName, Class<T> clazz, Converter<T> converter) {
         if (this.contentResource != null) {
            validateConfigurationName(configName);
+           
+           // get all possible colection parent config names
+           Collection<String> collectionParentConfigNames = configurationPersistenceStrategy.getAllCollectionParentConfigNames(configName);
+           List<Iterator<Resource>> resourceInheritanceChains = new ArrayList<>();
+           for (String collectionParentConfigName : collectionParentConfigNames) {
+               Collection<Iterator<Resource>> result = this.configurationResourceResolvingStrategy
+                       .getResourceCollectionInheritanceChain(this.contentResource, configBucketNames, collectionParentConfigName);
+               if (result != null) {
+                   resourceInheritanceChains.addAll(result);
+               }
+           }
+
            final Collection<T> result = new ArrayList<>();
-           Collection<Iterator<Resource>> resourceInheritanceChains = this.configurationResourceResolvingStrategy
-                   .getResourceCollectionInheritanceChain(this.contentResource, configBucketNames, configName);;
            if (resourceInheritanceChains != null) {
                for (final Iterator<Resource> resourceInheritanceChain : resourceInheritanceChains) {
                    final T obj = convert(resourceInheritanceChain, clazz, converter, configName, true);
@@ -153,8 +164,8 @@ class ConfigurationBuilderImpl implement
     }
     
     @SuppressWarnings("unchecked")
-    private <T> T convert(Iterator<Resource> resourceInhertianceChain, Class<T> clazz, Converter<T> converter,
-            String name, boolean appendResourceName) {
+    private <T> T convert(final Iterator<Resource> resourceInhertianceChain, final Class<T> clazz, final Converter<T> converter,
+            final String name, final boolean isCollection) {
         Resource configResource = null;
         String conversionName = name;
         if (resourceInhertianceChain != null) {
@@ -163,7 +174,12 @@ class ConfigurationBuilderImpl implement
                     new Transformer() {
                         @Override
                         public Object transform(Object input) {
-                            return configurationPersistenceStrategy.getResource((Resource)input);
+                            if (isCollection) {
+                                return configurationPersistenceStrategy.getCollectionItemResource((Resource)input);
+                            }
+                            else {
+                                return configurationPersistenceStrategy.getResource((Resource)input);
+                            }
                         }
                     });
             // apply resource inheritance
@@ -171,7 +187,7 @@ class ConfigurationBuilderImpl implement
             // apply overrides
             configResource = configurationOverrideManager.overrideProperties(contentResource.getPath(), name, configResource);
             // build name
-            if (configResource != null && appendResourceName) {
+            if (configResource != null && isCollection) {
                 conversionName = conversionName + "/" + configResource.getName();
             }
         }
@@ -179,7 +195,7 @@ class ConfigurationBuilderImpl implement
             log.trace("+ Found config resource for context path " + contentResource.getPath() + ": " + configResource.getPath() + " "
                     + MapUtil.traceOutput(configResource.getValueMap()));
         }
-        return converter.convert(configResource, clazz, conversionName);
+        return converter.convert(configResource, clazz, conversionName, isCollection);
     }
     
     /**
@@ -262,10 +278,16 @@ class ConfigurationBuilderImpl implement
 
     private class AnnotationConverter<T> implements Converter<T> {
         @Override
-        public T convert(final Resource resource, final Class<T> clazz, final String configName) {
+        public T convert(final Resource resource, final Class<T> clazz, final String configName, final boolean isCollection) {
             return ConfigurationProxy.get(resource, clazz, new ChildResolver() {
                 private ConfigurationBuilder getConfiguration(String nestedConfigName) {
-                    String childName = configurationPersistenceStrategy.getResourcePath(configName) + "/" + nestedConfigName;
+                    String childName;
+                    if (isCollection) {
+                        childName = configurationPersistenceStrategy.getCollectionItemConfigName(configName, resource) + "/" + nestedConfigName;
+                    }
+                    else {
+                        childName = configurationPersistenceStrategy.getConfigName(configName, resource) + "/" + nestedConfigName;
+                    }
                     return configurationResolver.get(contentResource).name(childName);
                 }
                 @Override
@@ -300,7 +322,7 @@ class ConfigurationBuilderImpl implement
 
     private class ValueMapConverter implements Converter<ValueMap> {
         @Override
-        public ValueMap convert(Resource resource, Class<ValueMap> clazz, String configName) {
+        public ValueMap convert(Resource resource, Class<ValueMap> clazz, String configName, boolean isCollection) {
             ValueMap props = ResourceUtil.getValueMap(resource);
             Map<String,Object> updatedMap = applyDefaultValues(props, configName);
             if (updatedMap != null) {
@@ -332,7 +354,7 @@ class ConfigurationBuilderImpl implement
 
     private class AdaptableConverter<T> implements Converter<T> {
         @Override
-        public T convert(Resource resource, Class<T> clazz, String configName) {
+        public T convert(Resource resource, Class<T> clazz, String configName, boolean isCollection) {
             if (resource == null || clazz == ConfigurationBuilder.class) {
                 return null;
             }

Added: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,203 @@
+/*
+ * 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.caconfig.impl;
+
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.caconfig.spi.ConfigurationCollectionPersistData;
+import org.apache.sling.caconfig.spi.ConfigurationPersistData;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.apache.sling.commons.osgi.Order;
+import org.apache.sling.commons.osgi.ServiceUtil;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Bridges services implementing the deprecated {@link ConfigurationPersistenceStrategy} interface
+ * to the {@link ConfigurationPersistenceStrategy2} interface for backwards compatibility.
+ */
+@Component(reference={
+        @Reference(name="configurationPersistenceStrategy", service=ConfigurationPersistenceStrategy.class,
+                bind="bindConfigurationPersistenceStrategy", unbind="unbindConfigurationPersistenceStrategy",
+                cardinality=ReferenceCardinality.MULTIPLE,
+                policy=ReferencePolicy.DYNAMIC, policyOption=ReferencePolicyOption.GREEDY)
+})
+@SuppressWarnings("deprecation")
+public final class ConfigurationPersistenceStrategyBridge {
+    
+    private volatile BundleContext bundleContext;
+    private final ConcurrentMap<Comparable<Object>, ServiceRegistration<ConfigurationPersistenceStrategy2>> services = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Comparable<Object>, ServiceInfo> preActivateServices = new ConcurrentHashMap<>();
+    
+    protected void bindConfigurationPersistenceStrategy(ConfigurationPersistenceStrategy item, Map<String, Object> props) {
+        ServiceInfo serviceInfo = new ServiceInfo(item, props);
+        Comparable<Object> key = ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING);
+        if (bundleContext != null) {
+            services.put(key, registerBridgeService(serviceInfo));
+        }
+        else {
+            preActivateServices.put(key, serviceInfo);
+        }
+    }
+    
+    protected void unbindConfigurationPersistenceStrategy(ConfigurationPersistenceStrategy item, Map<String, Object> props) {
+        Comparable<Object> key = ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING);
+        unregisterBridgeService(services.remove(key));
+    }
+    
+    /**
+     * Register {@link ConfigurationPersistenceStrategy2} bridge service for {@link ConfigurationPersistenceStrategy} service.
+     * @param serviceInfo Service information
+     * @return Service registration
+     */
+    private ServiceRegistration<ConfigurationPersistenceStrategy2> registerBridgeService(ServiceInfo serviceInfo) {
+        return bundleContext.registerService(ConfigurationPersistenceStrategy2.class,
+                new Adapter(serviceInfo.getService()), new Hashtable<>(serviceInfo.getProps()));
+    }
+    
+    /**
+     * Unregister {@link ConfigurationPersistenceStrategy2} bridge service.
+     * @param service Service registration
+     */
+    private void unregisterBridgeService(ServiceRegistration<ConfigurationPersistenceStrategy2> service) {
+        if (service != null) {
+            service.unregister();
+        }
+    }
+    
+    @Activate
+    private void activate(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        for (Map.Entry<Comparable<Object>, ServiceInfo> entry : preActivateServices.entrySet()) {
+            services.put(entry.getKey(), registerBridgeService(entry.getValue()));
+        }
+    }
+   
+    
+    private static class ServiceInfo {
+        private final ConfigurationPersistenceStrategy service;
+        private final Map<String,Object> props;
+        
+        public ServiceInfo(ConfigurationPersistenceStrategy service, Map<String, Object> props) {
+            this.service = service;
+            this.props = props;
+        }
+        public ConfigurationPersistenceStrategy getService() {
+            return service;
+        }
+        public Map<String, Object> getProps() {
+            return props;
+        }
+    }
+    
+    
+    /**
+     * Adapter which delegates {@link ConfigurationPersistenceStrategy2} methods to a {@link ConfigurationPersistenceStrategy} service.
+     */
+    public static class Adapter implements ConfigurationPersistenceStrategy2 {
+        private final ConfigurationPersistenceStrategy delegate;
+
+        public Adapter(ConfigurationPersistenceStrategy delegate) {
+            this.delegate = delegate;
+        }
+        
+        /**
+         * @return Implementation class of the original service.
+         */
+        public Class<?> getOriginalServiceClass() {
+            return delegate.getClass();
+        }
+
+        @Override
+        public Resource getResource(Resource resource) {
+            return delegate.getResource(resource);
+        }
+
+        @Override
+        public Resource getCollectionParentResource(Resource resource) {
+            return delegate.getResource(resource);
+        }
+
+        @Override
+        public Resource getCollectionItemResource(Resource resource) {
+            return delegate.getResource(resource);
+        }
+
+        @Override
+        public String getResourcePath(String resourcePath) {
+            return delegate.getResourcePath(resourcePath);
+        }
+
+        @Override
+        public String getCollectionParentResourcePath(String resourcePath) {
+            return delegate.getResourcePath(resourcePath);
+        }
+
+        @Override
+        public String getCollectionItemResourcePath(String resourcePath) {
+            return delegate.getResourcePath(resourcePath);
+        }
+
+        @Override
+        public String getConfigName(String configName, Resource relatedConfigResource) {
+            return delegate.getResourcePath(configName);
+        }
+
+        @Override
+        public String getCollectionParentConfigName(String configName, Resource relatedConfigResource) {
+            return delegate.getResourcePath(configName);
+        }
+
+        @Override
+        public String getCollectionItemConfigName(String configName, Resource relatedConfigResource) {
+            return delegate.getResourcePath(configName);
+        }
+
+        @Override
+        public boolean persistConfiguration(ResourceResolver resourceResolver, String configResourcePath,
+                ConfigurationPersistData data) {
+            return delegate.persistConfiguration(resourceResolver, configResourcePath, data);
+        }
+
+        @Override
+        public boolean persistConfigurationCollection(ResourceResolver resourceResolver,
+                String configResourceCollectionParentPath, ConfigurationCollectionPersistData data) {
+            return delegate.persistConfigurationCollection(resourceResolver, configResourceCollectionParentPath, data);
+        }
+
+        @Override
+        public boolean deleteConfiguration(ResourceResolver resourceResolver, String configResourcePath) {
+            return delegate.deleteConfiguration(resourceResolver, configResourcePath);
+        }
+        
+    }
+    
+}

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationPersistenceStrategyBridge.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java Sun Mar 19 14:53:02 2017
@@ -30,7 +30,7 @@ import org.apache.sling.caconfig.Configu
 import org.apache.sling.caconfig.ConfigurationResolver;
 import org.apache.sling.caconfig.impl.metadata.ConfigurationMetadataProviderMultiplexer;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
-import org.apache.sling.caconfig.management.impl.ConfigurationPersistenceStrategyMultiplexer;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer;
 import org.apache.sling.caconfig.resource.impl.ConfigurationResourceResolvingStrategyMultiplexer;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationPersistenceStrategy.java Sun Mar 19 14:53:02 2017
@@ -32,7 +32,7 @@ import org.apache.sling.caconfig.resourc
 import org.apache.sling.caconfig.spi.ConfigurationCollectionPersistData;
 import org.apache.sling.caconfig.spi.ConfigurationPersistData;
 import org.apache.sling.caconfig.spi.ConfigurationPersistenceException;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
@@ -47,9 +47,9 @@ import org.slf4j.LoggerFactory;
  * All existing properties are removed when new properties are stored in a singleton config resource.
  * All existing child resources are removed when a new configs are stored for collection config resources. 
  */
-@Component(service = ConfigurationPersistenceStrategy.class)
+@Component(service = ConfigurationPersistenceStrategy2.class)
 @Designate(ocd=DefaultConfigurationPersistenceStrategy.Config.class)
-public class DefaultConfigurationPersistenceStrategy implements ConfigurationPersistenceStrategy {
+public class DefaultConfigurationPersistenceStrategy implements ConfigurationPersistenceStrategy2 {
 
     @ObjectClassDefinition(name="Apache Sling Context-Aware Configuration Default Resource Persistence Strategy",
             description="Directly uses configuration resources for storing configuration data.")
@@ -77,6 +77,22 @@ public class DefaultConfigurationPersist
         }
         return resource;
     }
+    
+    @Override
+    public Resource getCollectionParentResource(Resource resource) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return resource;
+    }
+
+    @Override
+    public Resource getCollectionItemResource(Resource resource) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return resource;
+    }
 
     @Override
     public String getResourcePath(String resourcePath) {
@@ -87,6 +103,46 @@ public class DefaultConfigurationPersist
     }
 
     @Override
+    public String getCollectionParentResourcePath(String resourcePath) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return resourcePath;
+    }
+
+    @Override
+    public String getCollectionItemResourcePath(String resourcePath) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return resourcePath;
+    }
+
+    @Override
+    public String getConfigName(String configName, Resource relatedConfigResource) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return configName;
+    }
+
+    @Override
+    public String getCollectionParentConfigName(String configName, Resource relatedConfigResource) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return configName;
+    }
+
+    @Override
+    public String getCollectionItemConfigName(String configName, Resource relatedConfigResource) {
+        if (!config.enabled()) {
+            return null;
+        }
+        return configName;
+    }
+    
+    @Override
     public boolean persistConfiguration(ResourceResolver resourceResolver, String configResourcePath,
             ConfigurationPersistData data) {
         if (!config.enabled()) {

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/ConfigurationManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/ConfigurationManager.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/ConfigurationManager.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/ConfigurationManager.java Sun Mar 19 14:53:02 2017
@@ -103,8 +103,10 @@ public interface ConfigurationManager {
     /**
      * Rewrite given resource path or configuration name according to current persistence strategies.
      * @param configResourcePath Resource path or config name
-     * @return Rewritten resoure path or config name
+     * @return Rewritten resource path or config name
+     * @deprecated Please use {@link org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer} instead.
      */
+    @Deprecated
     @CheckForNull String getPersistenceResourcePath(@Nonnull String configResourcePath);
     
 }

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java Sun Mar 19 14:53:02 2017
@@ -39,7 +39,7 @@ import org.apache.sling.caconfig.managem
 import org.apache.sling.caconfig.management.ConfigurationManager;
 import org.apache.sling.caconfig.management.ValueInfo;
 import org.apache.sling.caconfig.resource.impl.util.PropertiesFilterUtil;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
 import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
 import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
 
@@ -53,7 +53,7 @@ final class ConfigurationDataImpl implem
     private final String configName;
     private final ConfigurationManager configurationManager;
     private final ConfigurationOverrideManager configurationOverrideManager;
-    private final ConfigurationPersistenceStrategy configurationPersistenceStrategy;
+    private final ConfigurationPersistenceStrategy2 configurationPersistenceStrategy;
     private final boolean configResourceCollection;
     private final String collectionItemName;
     private final boolean isAllOverridden;
@@ -68,7 +68,7 @@ final class ConfigurationDataImpl implem
             Iterator<Resource> configurationResourceInheritanceChain,
             Resource contextResource, String configName,
             ConfigurationManager configurationManager, ConfigurationOverrideManager configurationOverrideManager,
-            ConfigurationPersistenceStrategy configurationPersistenceStrategy,
+            ConfigurationPersistenceStrategy2 configurationPersistenceStrategy,
             boolean configResourceCollection, String collectionItemName) {
         this.configMetadata = configMetadata;
         this.resolvedConfigurationResource = resolvedConfigurationResource;
@@ -88,7 +88,7 @@ final class ConfigurationDataImpl implem
     public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
             Resource contextResource, String configName,
             ConfigurationManager configurationManager, ConfigurationOverrideManager configurationOverrideManager,
-            ConfigurationPersistenceStrategy configurationPersistenceStrategy,
+            ConfigurationPersistenceStrategy2 configurationPersistenceStrategy,
             boolean configResourceCollection) {
         this(configMetadata, null, null, null,
                 contextResource, configName,
@@ -177,10 +177,12 @@ final class ConfigurationDataImpl implem
                 ConfigurationMetadata nestedConfigMetadata = propertyMetadata.getConfigurationMetadata();
                 String nestedConfigName;
                 if (configResourceCollection) {
-                    nestedConfigName = configurationPersistenceStrategy.getResourcePath(configName + "/" + getCollectionItemName()) + "/" + nestedConfigMetadata.getName();
+                    nestedConfigName = configurationPersistenceStrategy.getCollectionParentConfigName(configName, resolvedConfigurationResource)
+                            + "/" + configurationPersistenceStrategy.getCollectionItemConfigName(getCollectionItemName(), resolvedConfigurationResource)
+                            + "/" + nestedConfigMetadata.getName();
                 }
                 else {
-                    nestedConfigName = configurationPersistenceStrategy.getResourcePath(configName) + "/" + nestedConfigMetadata.getName();
+                    nestedConfigName = configurationPersistenceStrategy.getConfigName(configName, resolvedConfigurationResource) + "/" + nestedConfigMetadata.getName();
                 }
                 if (propertyMetadata.getType().equals(ConfigurationMetadata.class)) {
                     ConfigurationData configData = configurationManager.getConfiguration(contextResource, nestedConfigName);

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java Sun Mar 19 14:53:02 2017
@@ -23,8 +23,10 @@ import static org.apache.sling.caconfig.
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedSet;
 
 import org.apache.commons.collections.IteratorUtils;
@@ -40,6 +42,7 @@ import org.apache.sling.caconfig.impl.ov
 import org.apache.sling.caconfig.management.ConfigurationCollectionData;
 import org.apache.sling.caconfig.management.ConfigurationData;
 import org.apache.sling.caconfig.management.ConfigurationManager;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer;
 import org.apache.sling.caconfig.resource.impl.ConfigurationResourceResolvingStrategyMultiplexer;
 import org.apache.sling.caconfig.resource.impl.util.ConfigNameUtil;
 import org.apache.sling.caconfig.resource.impl.util.MapUtil;
@@ -82,11 +85,11 @@ public class ConfigurationManagerImpl im
         Resource configResource = null;
         
         Iterator<Resource> configResourceInheritanceChain = configurationResourceResolvingStrategy
-                .getResourceInheritanceChain(resource, configurationResourceResolverConfig.configBucketNames(), configName);;
+                .getResourceInheritanceChain(resource, configurationResourceResolverConfig.configBucketNames(), configName);
         
         if (configResourceInheritanceChain != null) {
             ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
-            configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
+            configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain, false);
             if (configResource != null) {
                 // get writeback resource for "reverse inheritance detection"
                 Resource writebackConfigResource = null;
@@ -110,7 +113,7 @@ public class ConfigurationManagerImpl im
                 }
                 resettableConfigResourceInheritanceChain.reset();
                 return new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
-                        applyPersistence(resettableConfigResourceInheritanceChain),
+                        applyPersistence(resettableConfigResourceInheritanceChain, false),
                         resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy, false, null);
             }
         }
@@ -132,15 +135,24 @@ public class ConfigurationManagerImpl im
         ConfigurationMetadata configMetadata = getConfigurationMetadata(configName);
         List<ConfigurationData> configData = new ArrayList<>();
 
+        // get all possible colection parent config names
+        Collection<String> collectionParentConfigNames = configurationPersistenceStrategy.getAllCollectionParentConfigNames(configName);
+
         // get configuration resource items
-        Collection<Iterator<Resource>> configResourceInheritanceChains = configurationResourceResolvingStrategy
-                    .getResourceCollectionInheritanceChain(resource, configurationResourceResolverConfig.configBucketNames(), configName);   
+        List<Iterator<Resource>> configResourceInheritanceChains = new ArrayList<>();
+        for (String collectionParentConfigName : collectionParentConfigNames) {
+            Collection<Iterator<Resource>> result = configurationResourceResolvingStrategy
+                    .getResourceCollectionInheritanceChain(resource, configurationResourceResolverConfig.configBucketNames(), collectionParentConfigName);
+            if (result != null) {
+                configResourceInheritanceChains.addAll(result);
+            }
+        }
 
         String writebackConfigResourceCollectionParentPath = null;
         if (configResourceInheritanceChains != null) {
             for (Iterator<Resource> configResourceInheritanceChain : configResourceInheritanceChains) {
                 ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
-                Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
+                Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain, true);
                 resettableConfigResourceInheritanceChain.reset();
                 Resource untransformedConfigResource = (Resource)resettableConfigResourceInheritanceChain.next();
                 if (configResource != null) {
@@ -151,10 +163,11 @@ public class ConfigurationManagerImpl im
                     for (String configBucketName : configurationResourceResolverConfig.configBucketNames()) {
                         writebackConfigResourceCollectionParentPath = configurationResourceResolvingStrategy.getResourceCollectionParentPath(resource, configBucketName, configName);
                         if (writebackConfigResourceCollectionParentPath != null) {
+                            writebackConfigResourceCollectionParentPath = configurationPersistenceStrategy.getCollectionParentResourcePath(writebackConfigResourceCollectionParentPath);
                             writebackConfigResourcePath = writebackConfigResourceCollectionParentPath + "/" + untransformedConfigResource.getName();
                             writebackConfigResource = configResource.getResourceResolver().getResource(writebackConfigResourcePath);
                             if (writebackConfigResource != null) {
-                                writebackConfigResource = configurationPersistenceStrategy.getResource(writebackConfigResource);
+                                writebackConfigResource = configurationPersistenceStrategy.getCollectionItemResource(writebackConfigResource);
                                 break;
                             }
                         }
@@ -167,7 +180,7 @@ public class ConfigurationManagerImpl im
                     }
                     resettableConfigResourceInheritanceChain.reset();
                     configData.add(new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
-                            applyPersistence(resettableConfigResourceInheritanceChain),
+                            applyPersistence(resettableConfigResourceInheritanceChain, true),
                             resource, configName, this, configurationOverrideManager, configurationPersistenceStrategy,
                             true, untransformedConfigResource.getName()));
                 }
@@ -192,7 +205,7 @@ public class ConfigurationManagerImpl im
     }
     
     @SuppressWarnings("unchecked")
-    private Iterator<Resource> applyPersistence(Iterator<Resource> configResourceInheritanceChain) {
+    private Iterator<Resource> applyPersistence(final Iterator<Resource> configResourceInheritanceChain, final boolean isCollection) {
         if (configResourceInheritanceChain == null) {
             return null;
         }
@@ -200,18 +213,24 @@ public class ConfigurationManagerImpl im
                 new Transformer() {
                     @Override
                     public Object transform(Object input) {
-                        return configurationPersistenceStrategy.getResource((Resource)input);
+                        if (isCollection) {
+                            return configurationPersistenceStrategy.getCollectionItemResource((Resource)input);
+                        }
+                        else {
+                            return configurationPersistenceStrategy.getResource((Resource)input);
+                        }
                     }
                 });
     }
 
-    private Resource applyPersistenceAndInheritance(String contextPath, String configName, Iterator<Resource> configResourceInheritanceChain) {
+    private Resource applyPersistenceAndInheritance(String contextPath, String configName, Iterator<Resource> configResourceInheritanceChain,
+            boolean isCollection) {
         if (configResourceInheritanceChain == null) {
             return null;
         }
         
         // apply configuration persistence transformation
-        Iterator<Resource> transformedConfigResources = applyPersistence(configResourceInheritanceChain);
+        Iterator<Resource> transformedConfigResources = applyPersistence(configResourceInheritanceChain, isCollection);
         
         // apply resource inheritance
         Resource configResource = configurationInheritanceStrategy.getResource(transformedConfigResources);
@@ -316,27 +335,38 @@ public class ConfigurationManagerImpl im
     
     private ConfigurationMetadata getNestedConfigurationMetadata(ConfigurationMetadata configMetadata, String configName, String partialConfigName) {
         if (StringUtils.startsWith(configName, partialConfigName + "/")) {
-            String prefixToRemove;
+            
+            // depending on different persistence strategies config names can be transformed differently - try all combinations here
+            Set<String> prefixesToRemove = new LinkedHashSet<>();
             if (configMetadata.isCollection()) {
                 String collectionItemName = StringUtils.substringBefore(StringUtils.substringAfter(configName, partialConfigName + "/"), "/");
-                prefixToRemove = configurationPersistenceStrategy.getResourcePath(partialConfigName + "/" + collectionItemName) + "/";
+                for (String collectionParentConfigName : configurationPersistenceStrategy.getAllCollectionParentConfigNames(partialConfigName)) {
+                    for (String collectionItemConfigName : configurationPersistenceStrategy.getAllCollectionItemConfigNames(collectionItemName)) {
+                        prefixesToRemove.add(collectionParentConfigName  + "/" + collectionItemConfigName + "/");
+                    }
+                }
             }
             else {
-                prefixToRemove = configurationPersistenceStrategy.getResourcePath(partialConfigName) + "/";
-            }
-            String remainingConfigName = StringUtils.substringAfter(configName, prefixToRemove);
-            // try direct match
-            ConfigurationMetadata nestedConfigMetadata = getNestedConfigurationMetadataFromProperty(configMetadata, remainingConfigName);
-            if (nestedConfigMetadata != null) {
-                return nestedConfigMetadata;
+                for (String configNameItem : configurationPersistenceStrategy.getAllConfigNames(partialConfigName)) {
+                    prefixesToRemove.add(configNameItem + "/");
+                }
             }
-            // try to find partial match for deeper nestings
-            for (String partialRemainingConfigName : ConfigNameUtil.getAllPartialConfigNameVariations(remainingConfigName)) {
-                ConfigurationMetadata partialConfigMetadata = getNestedConfigurationMetadataFromProperty(configMetadata, partialRemainingConfigName);
-                if (partialConfigMetadata != null) {
-                    nestedConfigMetadata = getNestedConfigurationMetadata(partialConfigMetadata, remainingConfigName, partialRemainingConfigName);
-                    if (nestedConfigMetadata != null) {
-                        return nestedConfigMetadata;
+            
+            for (String prefixToRemove : prefixesToRemove) {
+                String remainingConfigName = StringUtils.substringAfter(configName, prefixToRemove);
+                // try direct match
+                ConfigurationMetadata nestedConfigMetadata = getNestedConfigurationMetadataFromProperty(configMetadata, remainingConfigName);
+                if (nestedConfigMetadata != null) {
+                    return nestedConfigMetadata;
+                }
+                // try to find partial match for deeper nestings
+                for (String partialRemainingConfigName : ConfigNameUtil.getAllPartialConfigNameVariations(remainingConfigName)) {
+                    ConfigurationMetadata partialConfigMetadata = getNestedConfigurationMetadataFromProperty(configMetadata, partialRemainingConfigName);
+                    if (partialConfigMetadata != null) {
+                        nestedConfigMetadata = getNestedConfigurationMetadata(partialConfigMetadata, remainingConfigName, partialRemainingConfigName);
+                        if (nestedConfigMetadata != null) {
+                            return nestedConfigMetadata;
+                        }
                     }
                 }
             }

Added: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,239 @@
+/*
+ * 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.caconfig.management.impl;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer;
+import org.apache.sling.caconfig.spi.ConfigurationCollectionPersistData;
+import org.apache.sling.caconfig.spi.ConfigurationPersistData;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.apache.sling.commons.osgi.Order;
+import org.apache.sling.commons.osgi.RankedServices;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Detects all {@link ConfigurationPersistenceStrategy2} implementations in the container
+ * and consolidates their result based on service ranking.
+ */
+@Component(service = ConfigurationPersistenceStrategyMultiplexer.class,
+reference={
+        @Reference(name="configurationPersistenceStrategy", service=ConfigurationPersistenceStrategy2.class,
+                bind="bindConfigurationPersistenceStrategy", unbind="unbindConfigurationPersistenceStrategy",
+                cardinality=ReferenceCardinality.MULTIPLE,
+                policy=ReferencePolicy.DYNAMIC, policyOption=ReferencePolicyOption.GREEDY)
+})
+public class ConfigurationPersistenceStrategyMultiplexerImpl implements ConfigurationPersistenceStrategyMultiplexer {
+    
+    private RankedServices<ConfigurationPersistenceStrategy2> items = new RankedServices<>(Order.DESCENDING);
+        
+    protected void bindConfigurationPersistenceStrategy(ConfigurationPersistenceStrategy2 configurationPersistenceStrategy, Map<String, Object> props) {
+        items.bind(configurationPersistenceStrategy, props);
+    }
+    
+    protected void unbindConfigurationPersistenceStrategy(ConfigurationPersistenceStrategy2 configurationPersistenceStrategy, Map<String, Object> props) {
+        items.unbind(configurationPersistenceStrategy, props);
+    }
+
+    /**
+     * Transform the configuration resource by the first implementation that has an answer.
+     */    
+    @Override
+    public Resource getResource(Resource resource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            Resource result = item.getResource(resource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Resource getCollectionParentResource(Resource resource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            Resource result = item.getCollectionParentResource(resource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Resource getCollectionItemResource(Resource resource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            Resource result = item.getCollectionItemResource(resource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }    
+        
+    @Override
+    public String getResourcePath(String resourcePath) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getResourcePath(resourcePath);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getCollectionParentResourcePath(String resourcePath) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionParentResourcePath(resourcePath);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getCollectionItemResourcePath(String resourcePath) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionItemResourcePath(resourcePath);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getConfigName(String configName, Resource relatedConfigResource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getConfigName(configName, relatedConfigResource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getCollectionParentConfigName(String configName, Resource relatedConfigResource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionParentConfigName(configName, relatedConfigResource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getCollectionItemConfigName(String configName, Resource relatedConfigResource) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionItemConfigName(configName, relatedConfigResource);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+    
+    @Override
+    public Collection<String> getAllConfigNames(String configName) {
+        Set<String> configNames = new LinkedHashSet<>();
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getConfigName(configName, null);
+            if (result != null) {
+                configNames.add(result);
+            }
+        }
+        return configNames;
+    }
+
+    @Override
+    public Collection<String> getAllCollectionParentConfigNames(String configName) {
+        Set<String> configNames = new LinkedHashSet<>();
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionParentConfigName(configName, null);
+            if (result != null) {
+                configNames.add(result);
+            }
+        }
+        return configNames;
+    }
+
+    @Override
+    public Collection<String> getAllCollectionItemConfigNames(String configName) {
+        Set<String> configNames = new LinkedHashSet<>();
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            String result = item.getCollectionItemConfigName(configName, null);
+            if (result != null) {
+                configNames.add(result);
+            }
+        }
+        return configNames;
+    }
+        
+    /**
+     * Persist configuration data with the first implementation that accepts it.
+     */
+    @Override
+    public boolean persistConfiguration(ResourceResolver resourceResolver, String configResourcePath,
+            ConfigurationPersistData data) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            if (item.persistConfiguration(resourceResolver, configResourcePath, data)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Persist configuration data with the first implementation that accepts it.
+     */
+    @Override
+    public boolean persistConfigurationCollection(ResourceResolver resourceResolver, String configResourceCollectionParentPath,
+            ConfigurationCollectionPersistData data) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            if (item.persistConfigurationCollection(resourceResolver, configResourceCollectionParentPath, data)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean deleteConfiguration(ResourceResolver resourceResolver, String configResourcePath) {
+        for (ConfigurationPersistenceStrategy2 item : items) {
+            if (item.deleteConfiguration(resourceResolver, configResourcePath)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java Sun Mar 19 14:53:02 2017
@@ -35,7 +35,7 @@ import org.apache.sling.caconfig.resourc
 import org.apache.sling.caconfig.spi.ConfigurationInheritanceStrategy;
 import org.apache.sling.caconfig.spi.ConfigurationMetadataProvider;
 import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
 import org.apache.sling.commons.osgi.Order;
 import org.apache.sling.commons.osgi.ServiceUtil;
 import org.osgi.framework.BundleContext;
@@ -75,7 +75,8 @@ public class CAConfigInventoryPrinter im
         printSPISection(pw, ConfigurationResourceResolvingStrategy.class, "Configuration Resource Resolving Strategies");
         printSPISection(pw, CollectionInheritanceDecider.class, "Collection Inheritance Deciders");
         printSPISection(pw, ConfigurationInheritanceStrategy.class, "Configuration Inheritance Strategies");
-        printSPISection(pw, ConfigurationPersistenceStrategy.class, "Configuration Persistance Strategies");
+        printSPISection(pw, ConfigurationPersistenceStrategy2.class, "Configuration Persistance Strategies",
+                new ConfigurationPersistenceStrategyPrinter());
         printSPISection(pw, ConfigurationMetadataProvider.class, "Configuration Metadata Providers",
                 new ConfigurationMetadataPrinter());
         printSPISection(pw, ConfigurationOverrideProvider.class, "Configuration Override Providers",

Added: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,46 @@
+/*
+ * 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.caconfig.management.impl.console;
+
+import java.io.PrintWriter;
+
+import org.apache.sling.caconfig.impl.ConfigurationPersistenceStrategyBridge;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Print original class information for a {@link ConfigurationPersistenceStrategy2} bridge service.
+ */
+class ConfigurationPersistenceStrategyPrinter implements ServiceConfigurationPrinter<ConfigurationPersistenceStrategy2> {
+
+    @Override
+    public void printConfiguration(PrintWriter pw, ServiceReference<ConfigurationPersistenceStrategy2> serviceReference, BundleContext bundleContext) {
+        ConfigurationPersistenceStrategy2 service = bundleContext.getService(serviceReference);
+        if (service instanceof ConfigurationPersistenceStrategyBridge.Adapter) {
+            ConfigurationPersistenceStrategyBridge.Adapter adapter =
+                    (ConfigurationPersistenceStrategyBridge.Adapter)service;
+            pw.print(INDENT);
+            pw.print(BULLET);
+            pw.println("Delegates to " + adapter.getOriginalServiceClass().getName());
+        }
+        bundleContext.ungetService(serviceReference);
+    }
+    
+}

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationPersistenceStrategyPrinter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,54 @@
+/*
+ * 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.caconfig.management.multiplexer;
+
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+
+/**
+ * Detects all {@link ConfigurationPersistenceStrategy2} implementations in the container
+ * and consolidates their result based on service ranking.
+ */
+public interface ConfigurationPersistenceStrategyMultiplexer extends ConfigurationPersistenceStrategy2 {
+    
+    /**
+     * Get all configuration names from all configuration persistence strategies. This can be used when no nested parent resources is known.
+     * @param configName Configuration name
+     * @return Possible configuration names in order of persistence strategy service ranking.
+     */
+    @Nonnull Collection<String> getAllConfigNames(@Nonnull String configName);
+
+    /**
+     * Get all configuration names from all configuration persistence strategies. This can be used when no nested parent resources is known.
+     * @param configName Configuration name
+     * @return Possible configuration names in order of persistence strategy service ranking.
+     */
+    @Nonnull Collection<String> getAllCollectionParentConfigNames(@Nonnull String configName);
+
+    /**
+     * Get all configuration names from all configuration persistence strategies. This can be used when no nested parent resources is known.
+     * @param configName Configuration name
+     * @return Possible configuration names in order of persistence strategy service ranking.
+     */
+    @Nonnull Collection<String> getAllCollectionItemConfigNames(@Nonnull String configName);
+        
+}

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/ConfigurationPersistenceStrategyMultiplexer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+/**
+ * Multiplexer services provide aggregated access to all implementations of the related SPI interface.
+ */
+@org.osgi.annotation.versioning.Version("1.0.0")
+package org.apache.sling.caconfig.management.multiplexer;

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/main/java/org/apache/sling/caconfig/management/multiplexer/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java?rev=1787626&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java (added)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java Sun Mar 19 14:53:02 2017
@@ -0,0 +1,192 @@
+/*
+ * 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.caconfig.impl;
+
+import static org.apache.sling.caconfig.resource.impl.def.ConfigurationResourceNameConstants.PROPERTY_CONFIG_REF;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.geom.Rectangle2D;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.caconfig.ConfigurationResolveException;
+import org.apache.sling.caconfig.ConfigurationResolver;
+import org.apache.sling.caconfig.example.ListConfig;
+import org.apache.sling.caconfig.example.NestedConfig;
+import org.apache.sling.caconfig.example.SimpleConfig;
+import org.apache.sling.caconfig.management.impl.CustomConfigurationPersistenceStrategy2;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.framework.Constants;
+
+/**
+ * Test {@link ConfigurationResolver} with annotation classes for reading the config.
+ */
+public class ConfigurationResolverCustomPersistence2Test {
+
+    @Rule
+    public SlingContext context = new SlingContext();
+
+    private ConfigurationResolver underTest;
+
+    private Resource site1Page1;
+
+    @Before
+    public void setUp() {
+        // custom config with defines alternative bucket name "settings"
+        underTest = ConfigurationTestUtils.registerConfigurationResolver(context,
+                "configBucketNames", "settings");
+
+        // custom strategy which redirects all config resources to a jcr:content subnode
+        context.registerService(ConfigurationPersistenceStrategy2.class,
+                new CustomConfigurationPersistenceStrategy2(), Constants.SERVICE_RANKING, 2000);
+        
+        // content resources
+        context.build().resource("/content/site1", PROPERTY_CONFIG_REF, "/conf/content/site1");
+        site1Page1 = context.create().resource("/content/site1/page1");
+    }
+
+    @Test
+    public void testNonExistingConfig_Simple() {
+        SimpleConfig cfg = underTest.get(site1Page1).as(SimpleConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertEquals(5, cfg.intParam());
+        assertEquals(false, cfg.boolParam());
+    }
+
+    @Test
+    public void testNonExistingConfig_List() {
+        Collection<ListConfig> cfgList = underTest.get(site1Page1).asCollection(ListConfig.class);
+        assertTrue(cfgList.isEmpty());
+    }
+
+    @Test
+    public void testNonExistingConfig_Nested() {
+        NestedConfig cfg = underTest.get(site1Page1).as(NestedConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertNotNull(cfg.subConfig());
+        assertNotNull(cfg.subListConfig());
+    }
+
+
+    @Test
+    public void testConfig_Simple() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.SimpleConfig/jcr:content",
+                "stringParam", "configValue1",
+                "intParam", 111,
+                "boolParam", true);
+
+        SimpleConfig cfg = underTest.get(site1Page1).as(SimpleConfig.class);
+
+        assertEquals("configValue1", cfg.stringParam());
+        assertEquals(111, cfg.intParam());
+        assertEquals(true, cfg.boolParam());
+    }
+
+    @Test
+    public void testConfig_SimpleWithName() {
+        context.build().resource("/conf/content/site1/settings/sampleName/jcr:content",
+                "stringParam", "configValue1.1",
+                "intParam", 1111,
+                "boolParam", true);
+
+        SimpleConfig cfg = underTest.get(site1Page1).name("sampleName").as(SimpleConfig.class);
+
+        assertEquals("configValue1.1", cfg.stringParam());
+        assertEquals(1111, cfg.intParam());
+        assertEquals(true, cfg.boolParam());
+    }
+
+    @Test
+    public void testConfig_List() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.ListConfig/jcr:content")
+            .siblingsMode()
+            .resource("1", "stringParam", "configValue1.1")
+            .resource("2", "stringParam", "configValue1.2")
+            .resource("3", "stringParam", "configValue1.3");
+
+        Collection<ListConfig> cfgList = underTest.get(site1Page1).asCollection(ListConfig.class);
+
+        assertEquals(3, cfgList.size());
+        Iterator<ListConfig> cfgIterator = cfgList.iterator();
+        assertEquals("configValue1.1", cfgIterator.next().stringParam());
+        assertEquals("configValue1.2", cfgIterator.next().stringParam());
+        assertEquals("configValue1.3", cfgIterator.next().stringParam());
+    }
+
+    @Test
+    public void testConfig_Nested() {
+        context.build().resource("/conf/content/site1/settings/org.apache.sling.caconfig.example.NestedConfig")
+            .resource("jcr:content", "stringParam", "configValue3")
+                .siblingsMode()
+                .resource("subConfig", "stringParam", "configValue4", "intParam", 444, "boolParam", true)
+                .hierarchyMode()
+                .resource("subListConfig")
+                    .siblingsMode()
+                    .resource("1", "stringParam", "configValue2.1")
+                    .resource("2", "stringParam", "configValue2.2")
+                    .resource("3", "stringParam", "configValue2.3");
+
+        NestedConfig cfg = underTest.get(site1Page1).as(NestedConfig.class);
+
+        assertEquals("configValue3", cfg.stringParam());
+        
+        SimpleConfig subConfig = cfg.subConfig();
+        assertEquals("configValue4", subConfig.stringParam());
+        assertEquals(444, subConfig.intParam());
+        assertEquals(true, subConfig.boolParam());
+        
+        ListConfig[] listConfig = cfg.subListConfig();
+        assertEquals(3, listConfig.length);
+        assertEquals("configValue2.1", listConfig[0].stringParam());
+        assertEquals("configValue2.2", listConfig[1].stringParam());
+        assertEquals("configValue2.3", listConfig[2].stringParam());
+    }
+
+    @Test(expected=ConfigurationResolveException.class)
+    public void testInvalidClassConversion() {
+        // test with class not supported for configuration mapping
+        underTest.get(site1Page1).as(Rectangle2D.class);
+    }
+
+    @Test
+    public void testNonExistingContentResource_Simple() {
+        SimpleConfig cfg = underTest.get(null).as(SimpleConfig.class);
+
+        assertNull(cfg.stringParam());
+        assertEquals(5, cfg.intParam());
+        assertEquals(false, cfg.boolParam());
+    }
+
+    @Test
+    public void testNonExistingContentResource_List() {
+        Collection<ListConfig> cfgList = underTest.get(null).asCollection(ListConfig.class);
+        assertTrue(cfgList.isEmpty());
+    }
+
+}

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Sun Mar 19 14:53:02 2017
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistence2Test.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverCustomPersistenceTest.java Sun Mar 19 14:53:02 2017
@@ -35,7 +35,7 @@ import org.apache.sling.caconfig.example
 import org.apache.sling.caconfig.example.NestedConfig;
 import org.apache.sling.caconfig.example.SimpleConfig;
 import org.apache.sling.caconfig.management.impl.CustomConfigurationPersistenceStrategy;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
+import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
 import org.junit.Before;
 import org.junit.Rule;
@@ -61,7 +61,7 @@ public class ConfigurationResolverCustom
                 "configBucketNames", "settings");
 
         // custom strategy which redirects all config resources to a jcr:content subnode
-        context.registerService(ConfigurationPersistenceStrategy.class,
+        context.registerService(ConfigurationPersistenceStrategy2.class,
                 new CustomConfigurationPersistenceStrategy(), Constants.SERVICE_RANKING, 2000);
         
         // content resources

Modified: sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java?rev=1787626&r1=1787625&r2=1787626&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java (original)
+++ sling/trunk/bundles/extensions/caconfig/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java Sun Mar 19 14:53:02 2017
@@ -23,7 +23,7 @@ import org.apache.sling.caconfig.impl.de
 import org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.impl.metadata.ConfigurationMetadataProviderMultiplexer;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
-import org.apache.sling.caconfig.management.impl.ConfigurationPersistenceStrategyMultiplexer;
+import org.apache.sling.caconfig.management.impl.ConfigurationPersistenceStrategyMultiplexerImpl;
 import org.apache.sling.caconfig.resource.impl.ConfigurationResourceTestUtils;
 import org.apache.sling.testing.mock.sling.junit.SlingContext;
 
@@ -40,7 +40,7 @@ public final class ConfigurationTestUtil
     public static ConfigurationResolver registerConfigurationResolver(SlingContext context, Object... properties) {
         ConfigurationResourceTestUtils.registerConfigurationResourceResolver(context);        
         context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
-        context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexer());
+        context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexerImpl());
         context.registerInjectActivateService(new DefaultConfigurationInheritanceStrategy());
         context.registerInjectActivateService(new ConfigurationInheritanceStrategyMultiplexer());
         context.registerInjectActivateService(new ConfigurationOverrideManager());
@@ -55,7 +55,7 @@ public final class ConfigurationTestUtil
      */
     public static ConfigurationResolver registerConfigurationResolverWithoutDefaultImpl(SlingContext context, Object... properties) {
         ConfigurationResourceTestUtils.registerConfigurationResourceResolverWithoutDefaultImpl(context);
-        context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexer());
+        context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexerImpl());
         context.registerInjectActivateService(new ConfigurationInheritanceStrategyMultiplexer());
         context.registerInjectActivateService(new ConfigurationOverrideManager());
         context.registerInjectActivateService(new ConfigurationMetadataProviderMultiplexer());